On this page

3 endpoints.

MethodPathSummary
GET/api/communities/{communityId}/api-keysList this community's API keys
POST/api/communities/{communityId}/api-keysCreate an API key
DELETE/api/communities/{communityId}/api-keys/{apiKeyId}Revoke an API key

Never returns a key or a hash. Revoked keys are included on purpose — "revoked on the 4th, last used on the 3rd" is the sentence an incident review needs, and hiding the row deletes the evidence.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
communityIdpathyesstring (uuid)

Responses

StatusDescriptionBody
200The community's API keys, newest firstobject
403The caller lacks api_keys:manage, or authenticated with an API key (keys cannot manage keys).

The response carries a plaintext key EXACTLY ONCE. There is no route that reads it back and no reveal button — if it is lost, revoke this key and create another. The key acts as the user who created it and can never exceed that member's own permissions. If their membership is removed, un-approved, banned or suspended, the key stops authenticating immediately. Scopes cannot be changed later. Widening a live key's power without re-issuing it would make the audit trail untrue, so rotation is create-then-revoke.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
communityIdpathyesstring (uuid)

Request body (required) — application/json

FieldTypeRequiredDescription
namestringyesHuman label. This is what the owner reads when deciding what to revoke, so make it say who holds it.
scopesenum: read, write[]noDefaults to read and write. A read-only key is rejected with 403 on any non-GET request.
expiresAtstring (date-time)noOptional. Must be in the future and within ten years. Omit for a key that never expires.

Responses

StatusDescriptionBody
201Created. data.key is present here and never again.object
400Invalid name, unknown scope, or a bad expiry
409This community already holds the maximum number of live keys. Revoke one first.
429Rate limited — 10 burst, roughly 1 per 10 seconds

Takes effect on the very next request that presents the key. There is no cache on the authentication path, deliberately — the one moment anyone revokes a key is the moment they know it has leaked, and "effective within N seconds" is not revocation. One-way. A revoked key cannot be un-revoked; create a new one. The row is kept rather than deleted so its prefix and last-used timestamp remain available as evidence. Idempotent — revoking an already-revoked key returns 200 with the same row, not an error.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
communityIdpathyesstring (uuid)
apiKeyIdpathyesstring (uuid)

Responses

StatusDescriptionBody
200The revoked key, with revokedAt setobject
404No such key in this community