Skip to content

Authentication and keys

Every request carries an API key as a bearer token (the one exception is GET /openapi.json, the contract itself):

Terminal window
curl https://api.sealpost.app/v1/ping -H "Authorization: Bearer sk_test_…"
Prefix Mode Use it for
sk_test_ Always test mode Building and testing your integration. Nothing is emailed or billed.
sk_live_ Live, or test per request Production. Add Sign-Test-Mode: true to run one request in test mode.

A key is the prefix and 43 letters and digits. Sealpost stores only its SHA-256, so a secret is shown once, when the key is created, and never again. The first 16 characters (prefix in responses) are enough to tell keys apart in lists and logs.

A key carries scopes, and every operation except GET /ping, GET /me and the public GET /openapi.json needs one. A key can only create keys with scopes it holds itself.

Scope Allows
envelopes:read Reading files and envelopes
envelopes:write Uploading files and creating envelopes
api_keys:read Listing keys
api_keys:write Creating, rotating and revoking keys
requests:read Reading the request log
templates:read, templates:write, webhooks:write, tenant:read, tenant:write Accepted now, so keys can be minted ahead of the endpoints that will use them

A key without the scope gets 403 insufficient_scope.

Terminal window
curl -X POST https://api.sealpost.app/v1/api-keys \
-H "Authorization: Bearer $SEALPOST_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ci-key-2026-10" \
-d '{"name":"CI","mode":"test","scopes":["envelopes:read","envelopes:write"]}'
{"id":"01a1669f-4cdc-718d-b93f-bc1dfcf13633","name":"CI","prefix":"sk_test_PbaNbkhM","mode":"test",
"scopes":["envelopes:read","envelopes:write"],"rotated_from_id":null,"created_at":"2026-10-23T02:37:58+00:00",
"last_used_at":null,"expires_at":null,"revoked_at":null,"secret":"sk_test_…"}

scopes defaults to the calling key’s scopes. A test key can create, rotate and revoke only test keys; touching a live key needs a live key (403 live_key_required).

If the response is lost, retrying with the same Idempotency-Key returns the same key with Idempotent-Replayed: true, without secret, because the secret was never stored. Create or rotate again to get a new one.

Terminal window
curl "https://api.sealpost.app/v1/api-keys?limit=20" -H "Authorization: Bearer $SEALPOST_KEY"
curl -X POST https://api.sealpost.app/v1/api-keys/<id>/rotate -H "Authorization: Bearer $SEALPOST_KEY"
curl -X DELETE https://api.sealpost.app/v1/api-keys/<id> -H "Authorization: Bearer $SEALPOST_KEY"
  • Rotate creates a replacement with the same name, mode and scopes and keeps the old key working for 24 hours, so you can deploy the new secret without a gap. After that the old key answers 401 api_key_expired.
  • Revoke is immediate and permanent: 401 api_key_revoked from then on.

Listing never shows secrets.

Sealpost is in early access. Your first live and test keys come with your account; ask for a test key to start.