The Transit API encrypts and decrypts data in transit without storing the application payload. It offers Encryption as a Service (EaaS).
The transit engine generates a Data Encryption Key (DEK) for each transit key created. The API then uses this DEK to encrypt or decrypt data provided by the client, returning the ciphertext or plaintext directly. The system handles DEK management, versioning, and rotation automatically.
graph TD
A[Client] -->|POST /v1/transit/keys/name/encrypt| B(API Server)
B --> C{Authentication & Authorization}
C -->|Valid| D[Retrieve DEK for Key Name]
D --> E[Encrypt Plaintext with DEK]
E --> F[Return Ciphertext to Client]
C -->|Invalid| H[401/403 Error]
All endpoints require Authorization: Bearer <token>.
Creates the initial transit key version (version = 1).
- Endpoint:
POST /v1/transit/keys - Capability:
write - Body:
{"name": "string", "algorithm": "aes-gcm" | "chacha20-poly1305"}
curl -X POST http://localhost:8080/v1/transit/keys
-H "Authorization: Bearer <token>"
-H "Content-Type: application/json"
-d '{"name":"payment-data","algorithm":"aes-gcm"}'Creates a new active version for encryption while old versions remain valid for decryption.
- Endpoint:
POST /v1/transit/keys/:name/rotate - Capability:
rotate - Body:
{"algorithm": "aes-gcm" | "chacha20-poly1305"}
- Endpoint:
POST /v1/transit/keys/:name/encrypt - Capability:
encrypt - Body:
{"plaintext": "base64-encoded-string"}
curl -X POST http://localhost:8080/v1/transit/keys/payment-data/encrypt
-H "Authorization: Bearer <token>"
-H "Content-Type: application/json"
-d '{"plaintext":"c2Vuc2l0aXZlLWRhdGE="}'Returns:
{
"ciphertext": "1:ZW5jcnlwdGVkLWJ5dGVzLi4u",
"version": 1
}Example encrypt response (200 OK):
{
"ciphertext": "1:ZW5jcnlwdGVkLWJ5dGVzLi4u",
"version": 1
}- Endpoint:
POST /v1/transit/keys/:name/decrypt - Capability:
decrypt - Body:
{"ciphertext": "1:ZW5jcnlwdGVkLWJ5dGVzLi4u"}
curl -X POST http://localhost:8080/v1/transit/keys/payment-data/decrypt
-H "Authorization: Bearer <token>"
-H "Content-Type: application/json"
-d '{"ciphertext":"1:ZW5jcnlwdGVkLi4u"}'Example decrypt response (200 OK):
{
"plaintext": "YjY0LXBsYWludGV4dA==",
"version": 1
}Retrieves metadata for a specific transit key and version.
- Endpoint:
GET /v1/transit/keys/:name - Capability:
read - Query Params:
version(optional) - Specific version to retrieve. If omitted, returns latest version.
- Success:
200 OK
curl "http://localhost:8080/v1/transit/keys/payment-data?version=1" \
-H "Authorization: Bearer <token>"Example response (200 OK):
{
"name": "payment-data",
"type": "aes-gcm",
"version": 1,
"created_at": "2026-03-07T12:00:00Z"
}- Endpoint:
GET /v1/transit/keys - Capability:
read - Query Params:
after_name(optional) - Cursor for pagination. Omit for first page.limit(default 50, max 1000) - Number of items per page.
- Success:
200 OK
# First page
curl "http://localhost:8080/v1/transit/keys?limit=50" \
-H "Authorization: Bearer <token>"
# Subsequent pages (use next_cursor from previous response)
curl "http://localhost:8080/v1/transit/keys?after_name=main-encryption&limit=50" \
-H "Authorization: Bearer <token>"Example response (200 OK):
{
"data": [
{
"id": "0194f4e1-c3ab-7d8e-a9f2-5cde3b8fa6c1",
"name": "app-encryption",
"algorithm": "aes256-gcm96",
"version": 3,
"created_at": "2026-02-27T22:00:00Z",
"updated_at": "2026-02-28T12:00:00Z"
},
{
"id": "0194f4f2-d5bc-7a1f-b8c3-6def4c9eb7d2",
"name": "main-encryption",
"algorithm": "chacha20-poly1305",
"version": 1,
"created_at": "2026-02-27T23:15:00Z",
"updated_at": "2026-02-27T23:15:00Z"
}
],
"next_cursor": "main-encryption"
}Note: The next_cursor field is only present when there are more pages available.
- Endpoint:
DELETE /v1/transit/keys/:name - Capability:
delete - Success:
204 No Content
rewrap-deks: Rewraps transit key DEKs when rotating the KEK.
The Transit API supports Authenticated Encryption with Associated Data (AEAD). This allows you to provide an optional context (also known as AAD - Additional Authenticated Data) that is cryptographically bound to the ciphertext but not encrypted itself.
AEAD context prevents ciphertext substitution attacks. By providing a context (e.g., a user ID, a transaction ID, or a resource type), you ensure that the ciphertext can only be decrypted if the same context is provided during the decryption operation.
Both encrypt and decrypt endpoints accept an optional context field in the JSON body. The context must be base64-encoded.
curl -X POST http://localhost:8080/v1/transit/keys/payment-data/encrypt \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"plaintext": "c2Vuc2l0aXZlLWRhdGE=",
"context": "dXNlci0xMjM="
}'To successfully decrypt, you MUST provide the exact same context used during encryption:
curl -X POST http://localhost:8080/v1/transit/keys/payment-data/decrypt \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"ciphertext": "1:ZW5jcnlwdGVkLWJ5dGVzLi4u",
"context": "dXNlci0xMjM="
}'If the context does not match, the API will return a 422 Unprocessable Entity error indicating that decryption failed.