API-Schlüssel
API-Schlüssel ausstellen, rotieren, sperren und widerrufen – mit den Scopes, die jede Operation verlangt.
Issue, rotate, suspend, and revoke programmatic API keys.
Operationen
-
GET/tenants/{tenantId}/api-key-statusWhether the tenant has ≥1 usable live API key -
GET/tenants/{tenantId}/api-keysList the tenant's API keys (masked) -
POST/tenants/{tenantId}/api-keysIssue an API key -
POST/tenants/{tenantId}/api-keys/{id}/rotateRotate a key -
POST/tenants/{tenantId}/api-keys/{id}/revokeRevoke a key immediately -
POST/tenants/{tenantId}/api-keys/{id}/suspendSuspend a key (operator-driven, reversible) -
POST/tenants/{tenantId}/api-keys/{id}/unsuspendClear a key's suspension -
DELETE/tenants/{tenantId}/api-keys/{id}Revoke a key (REST alias for /revoke)
Whether the tenant has ≥1 usable live API key
GET /tenants/{tenantId}/api-key-status
A boolean signal the dashboard reads during session-mode resolution to pick a fresh session's default (Live vs Test). Open to every active member (no requireRole) and any valid credential; returns only the boolean, no key material.
- Erforderlicher Scope
- keiner
- Zugang
- angemeldete Sitzung oder API-Schlüssel
(
authenticated)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
Antworten
-
200The live-key presence signal.
application/jsonApiKeyStatus -
403tenant_mismatch— the path tenantId is not the caller's active tenant.application/jsonValidationError
List the tenant's API keys (masked)
GET /tenants/{tenantId}/api-keys
Admin/owner only (role-gated; a capability scope for key management is not offered on this route). Returns MASKED keys only: the plaintext is NEVER retrievable after issuance (reveal-once, unlike webhook secrets). Each key carries its displayPrefix, scopes, mode, derived status, and lastUsedAt.
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
Antworten
-
200The tenant's API keys (masked).
application/jsonobject -
403Caller lacks the admin role, or path tenantId ≠ active tenant.
Issue an API key
POST /tenants/{tenantId}/api-keys
Mints a key and returns the full plaintext EXACTLY ONCE (key) in this 201 body — it is never stored (only its SHA-256 hash) and never retrievable again (genuine reveal-once, contrast webhook secrets which are encrypted-and-retrievable). mode is REQUIRED (live/test) and permanently fixes the key's mode and its sk_live_/sk_test_ prefix — the one place mode comes from request input. entityId is optional (omitted = full tenant scope; must belong to the tenant). scopes optional, defaults to the full 8-scope set. Honors the optional Idempotency-Key header so a retried issuance does not mint a SECOND active credential. A retry of an issuance that already succeeded answers 409 idempotency_replay_secret_withheld with the key it created, minus the plaintext key: the secret is shown once and never stored for a replay.
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
Idempotency-Key | Header | string | Optional client-supplied key that makes this mutating request safe to retry. The FIRST request runs and its outcome is recorded keyed by Länge: max. 255 |
Request-Body erforderlich
application/json CreateApiKey
Antworten
-
201Created. Body is the masked key PLUS the one-time plaintext
key.application/jsonApiKeyWithSecret -
400Validation error or
invalid_entity(entityId not in the tenant). -
402The plan tier does not include LIVE API keys. Evaluated on the RESOLVED mode, so omitting
modeon a live session is refused too. No key row and no key event are written. Atestkey is never refused, at any tier and at any usage level — the sandbox is unlimited, permanent and card-free.application/jsonEntitlementRequiredError -
403Caller lacks the admin role, or path tenantId ≠ active tenant.
-
409Idempotency-Key conflict, on a route whose success body carries a one-time secret.
IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY— the key was already used with a different request body;REQUEST_IN_PROGRESS— the first request bearing this key is still in flight (retryable);idempotency_replay_secret_withheld— the first request bearing this key already SUCCEEDED. Nothing new was created. The secret it returned is shown only once and is never stored for a replay, so this answer carries the created resource inresourcewithout the secret. Do not retry it.application/jsonIdempotencyConflictOrSecretWithheldError
Rotate a key
POST /tenants/{tenantId}/api-keys/{id}/rotate
Mints a SUCCESSOR key (fresh secret) carrying the predecessor's mode, entity, scopes, and name, with rotatedFrom linking the pair. The old key is NOT auto-revoked (no forced overlap window — the customer revokes it on their own schedule; staleOverlapWarning nudges them if they keep using it). Returns the new plaintext ONCE (201).
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
id erforderlich | Pfad | string (uuid) | API key id. |
Antworten
-
201The new (masked) key PLUS its one-time plaintext
key.application/jsonApiKeyWithSecret -
404Not found / not visible to the caller.
Revoke a key immediately
POST /tenants/{tenantId}/api-keys/{id}/revoke
Permanent. Rejected by api's own verification on the very next request (immediate at the api layer, independent of any gateway cache). Idempotent — revoking an already-revoked key returns it unchanged. revoked_at never clears (contrast suspension).
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
id erforderlich | Pfad | string (uuid) | API key id. |
Antworten
-
200The revoked (masked) key.
application/jsonApiKey -
404Not found / not visible.
Suspend a key (operator-driven, reversible)
POST /tenants/{tenantId}/api-keys/{id}/suspend
Same immediate rejection as revoke, but REVERSIBLE (suspended_at, distinct from revoked_at) — for abuse / non-payment hard-blocks ("never a quota, always a suspension"). Idempotent.
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
id erforderlich | Pfad | string (uuid) | API key id. |
Antworten
-
200The suspended (masked) key.
application/jsonApiKey -
404Not found / not visible.
Clear a key's suspension
POST /tenants/{tenantId}/api-keys/{id}/unsuspend
Reverses a suspension so the key verifies again. Idempotent — a non-suspended key returns unchanged. A revoked key stays revoked (revocation is not clearable). A key the platform operator suspended cannot be reactivated here; it can still be rotated, or a new key created.
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
id erforderlich | Pfad | string (uuid) | API key id. |
Antworten
-
200The re-activated (masked) key.
application/jsonApiKey -
404Not found / not visible.
-
409api_key_held_by_suspension— the platform operator suspended this key; nothing was changed.application/jsonValidationError
Revoke a key (REST alias for /revoke)
DELETE /tenants/{tenantId}/api-keys/{id}
Idiomatic-DELETE alias of POST /revoke — same permanent revocation, returns 204.
- Erforderlicher Scope
- keiner
- Zugang
- nur mit angemeldeter Sitzung – ein API-Schlüssel wird abgelehnt
(
oidc-only)
Parameter
| Parameter | In | Typ | Beschreibung |
|---|---|---|---|
tenantId erforderlich | Pfad | string (uuid) | The tenant the key belongs to. Must equal the caller's active tenant (the resolved auth context) — a mismatch is 403 |
id erforderlich | Pfad | string (uuid) | API key id. |
Antworten
-
204Revoked.
-
404Not found / not visible.
Datenmodelle
Jedes Datenmodell dieser Gruppe einmal, mit allen Feldern – auch den verschachtelten. Verschachtelte Objekte sind aufklappbar; ein benannter Typ verweist auf seinen eigenen Abschnitt.
ApiKeyStatus object
Whether the tenant has at least one usable live API key.
| Feld | Typ | Beschreibung |
|---|---|---|
hasLiveKey erforderlich | boolean |
Verwendet von:
GET /tenants/{tenantId}/api-key-status
ValidationError object
A refused request body. error is validation_error when the body was read and failed validation (each problem is listed in issues), or invalid_json when the body is not valid JSON at all (then issues is absent). An unparsable body is answered 400 invalid_json on every operation that takes a JSON body. The submitted body is never echoed.
| Feld | Typ | Beschreibung | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
error | string | |||||||||||||
issues | Array<object> | Felder
|
Verwendet von:
GET /tenants/{tenantId}/api-key-status , POST /tenants/{tenantId}/api-keys/{id}/unsuspend
ApiKey object
A customer-issuable API key, MASKED. The plaintext is NEVER present here — only the safe-to-display displayPrefix (sk_live_a1b2c3d4).
| Feld | Typ | Beschreibung |
|---|---|---|
id erforderlich | string (uuid) | |
name erforderlich | string | |
mode erforderlich | string | Set at creation, permanently fixed; also determines the key prefix. Werte: "live", "test" |
entityId erforderlich | string (uuid) | null | NULL = full tenant scope; otherwise the key is restricted to this entity. |
displayPrefix erforderlich | string | Masked key identifier ( |
scopes erforderlich | Array<ApiKeyScope> | |
status erforderlich | string | Derived. Werte: "active", "revoked", "suspended", "expired" |
createdAt erforderlich | string (date-time) | |
expiresAt erforderlich | string (date-time) | null | |
lastUsedAt erforderlich | string (date-time) | null | |
revokedAt erforderlich | string (date-time) | null | |
suspendedAt erforderlich | string (date-time) | null | |
rotatedFrom erforderlich | string (uuid) | null | The predecessor key this one was rotated from; NULL if first-issued. |
staleOverlapWarning erforderlich | boolean | Rotation nudge: true when this key was rotated away from but is still valid AND still recently used (the customer forgot to retire it). Computed at read time; dashboard-facing only. |
Verwendet von:
GET /tenants/{tenantId}/api-keys , POST /tenants/{tenantId}/api-keys/{id}/revoke , POST /tenants/{tenantId}/api-keys/{id}/suspend , POST /tenants/{tenantId}/api-keys/{id}/unsuspend
CreateApiKey object
| Feld | Typ | Beschreibung |
|---|---|---|
name erforderlich | string | Länge: min. 1, max. 200 |
mode erforderlich | string | Required. Permanently fixes the key's mode and prefix. Werte: "live", "test" |
entityId | string (uuid) | Optional; omitted = full tenant scope. Must be an entity of the tenant (else 400). |
scopes | Array<ApiKeyScope> | Optional; defaults to the full 8-scope set when omitted. Elemente: min. 1 |
expiresAt | string (date-time) | Optional expiry; must be in the future. Verification rejects the key past it. |
Verwendet von:
POST /tenants/{tenantId}/api-keys
ApiKeyWithSecret object
An ApiKey plus the full plaintext key, returned ONCE at issuance.
| Feld | Typ | Beschreibung |
|---|---|---|
id erforderlich | string (uuid) | |
name erforderlich | string | |
mode erforderlich | string | Set at creation, permanently fixed; also determines the key prefix. Werte: "live", "test" |
entityId erforderlich | string (uuid) | null | NULL = full tenant scope; otherwise the key is restricted to this entity. |
displayPrefix erforderlich | string | Masked key identifier ( |
scopes erforderlich | Array<ApiKeyScope> | |
status erforderlich | string | Derived. Werte: "active", "revoked", "suspended", "expired" |
createdAt erforderlich | string (date-time) | |
expiresAt erforderlich | string (date-time) | null | |
lastUsedAt erforderlich | string (date-time) | null | |
revokedAt erforderlich | string (date-time) | null | |
suspendedAt erforderlich | string (date-time) | null | |
rotatedFrom erforderlich | string (uuid) | null | The predecessor key this one was rotated from; NULL if first-issued. |
staleOverlapWarning erforderlich | boolean | Rotation nudge: true when this key was rotated away from but is still valid AND still recently used (the customer forgot to retire it). Computed at read time; dashboard-facing only. |
key erforderlich | string | The full plaintext key. Shown ONCE here and never again — not retrievable, not logged, not stored (only its hash is). |
Verwendet von:
POST /tenants/{tenantId}/api-keys , POST /tenants/{tenantId}/api-keys/{id}/rotate
EntitlementRequiredError object
402 body when the tenant's plan tier does not include the capability the request needs. Cleared by an upgrade, never by the caller — which is what distinguishes it from entity_limit_reached (409), a conflict with current state that the same caller clears by deactivating an entity. Nothing already issued is affected: an entitlement change never touches a document, never touches the archive and never revokes a read.
| Feld | Typ | Beschreibung |
|---|---|---|
error erforderlich | string | Werte: "entitlement_required" |
message | string | |
capability erforderlich | string | The capability the current plan does not include. Werte: "live_issuance", "live_api_keys" |
planTier erforderlich | string | Werte: "launch", "entry", "platform", "sovereign" |
upgradeUrl | string | Relative dashboard hint to the plan surface. |
Verwendet von:
POST /tenants/{tenantId}/api-keys
IdempotencyConflictOrSecretWithheldError object
| Feld | Typ | Beschreibung |
|---|---|---|
error erforderlich | string | Werte: "IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY", "REQUEST_IN_PROGRESS", "idempotency_replay_secret_withheld" |
message | string | |
resource | object | Only with |
Verwendet von:
POST /tenants/{tenantId}/api-keys
ApiKeyScope string
The canonical customer-issuable capability set. This enum is the authoritative published list: a key-issuance request is validated against exactly the same vocabulary the server enforces, so a scope listed here is a scope the server accepts, and a scope absent here is refused. The equality is asserted by an automated check on every build, so the published list cannot drift from the enforced one.
- Werte: "documents:write", "documents:read", "customers:write", "customers:read", "subscriptions:write", "subscriptions:read", "archive:read", "webhooks:manage", "entities:read", "entities:write", "validation:run", "sandbox:write", "payments:write", "payments:read"
Verwendet von:
GET /tenants/{tenantId}/api-keys , POST /tenants/{tenantId}/api-keys , POST /tenants/{tenantId}/api-keys/{id}/rotate , POST /tenants/{tenantId}/api-keys/{id}/revoke , POST /tenants/{tenantId}/api-keys/{id}/suspend , POST /tenants/{tenantId}/api-keys/{id}/unsuspend
Nach oben · Alle Ressourcengruppen · OpenAPI-Spezifikation (YAML)