Skip to content

API Keys API

API key endpoints require the admin scope. All responses redact the plaintext key (it is only returned at creation time).

Key Endpoints

MethodPathDescription
POST/api/v1/api-keysCreate API key
GET/api/v1/api-keysList API keys
DELETE/api/v1/api-keys/:idRevoke API key
POST/api/v1/api-keys/:id/rotateRotate API key
GET/api/v1/api-keys/dormantList dormant keys

Role Endpoints (RBAC)

MethodPathDescription
POST/api/v1/rolesCreate role
GET/api/v1/rolesList roles
GET/api/v1/roles/:idGet role
PATCH/api/v1/roles/:idUpdate role
DELETE/api/v1/roles/:idDelete role
POST/api/v1/roles/assign/:keyIdAssign role to API key
DELETE/api/v1/roles/assign/:keyIdRemove role from API key

Create API Key

POST /api/v1/api-keys

Body:

{
"tenant_id": "uuid",
"name": "my-service",
"rate_limit_max": 100,
"rate_limit_window": "1 minute"
}
FieldTypeRequiredDescription
tenant_idUUIDYesTenant to scope the key to
namestringNoDescriptive name
rate_limit_maxintegerNoMax requests per window (1—100,000)
rate_limit_windowstringNoTime window (e.g., "30 seconds", "1 minute", "1 hour")

Response: 201 Created

{
"id": "key-uuid",
"tenant_id": "tenant-uuid",
"key_prefix": "sk_live_abc",
"name": "my-service",
"created_at": "2024-01-01T00:00:00.000Z",
"plaintext_key": "sk_live_abc123..."
}

The plaintext_key is only returned in this response and cannot be retrieved again.


List API Keys

GET /api/v1/api-keys?tenant_id=<uuid>

Query Parameters:

ParamTypeDescription
tenant_idUUIDFilter by tenant (optional; scoped keys auto-filter)

Response: 200 OK — array of API key records (without plaintext keys).


Revoke API Key

DELETE /api/v1/api-keys/:id

Response: 204 No Content

Returns 404 if the key does not exist or is already revoked.


Rotate API Key

POST /api/v1/api-keys/:id/rotate

Revokes the existing key and creates a new one. Optionally update the name.

Body (optional):

{
"name": "my-service-v2"
}

Response: 201 Created — returns the new key with plaintext_key.


List Dormant Keys

GET /api/v1/api-keys/dormant?days=90

Returns keys that have not been used in the specified number of days.

ParamTypeDefaultDescription
daysinteger90Minimum days since last use (1—365)

Response: 200 OK — array of API key records.


Create Role

POST /api/v1/roles

Body:

{
"name": "Editor",
"description": "Can read and write but not manage keys",
"scopes": ["read", "write"],
"tenant_id": "uuid (optional, null for global)"
}
FieldTypeRequiredDescription
namestringYesRole name (1—100 chars)
descriptionstringNoDescription (max 500 chars)
scopesstring[]YesArray of "read", "write", "admin"
tenant_idUUIDNoScope role to a tenant (null for global)

Response: 201 Created — returns the role object.


List Roles

GET /api/v1/roles?tenant_id=<uuid>

Response: 200 OK — array of role objects.


Update Role

PATCH /api/v1/roles/:id

Body (all optional):

{
"name": "Senior Editor",
"scopes": ["read", "write", "admin"]
}

Response: 200 OK — returns the updated role.


Assign Role to API Key

POST /api/v1/roles/assign/:keyId

Body:

{
"role_id": "uuid"
}

When a role is assigned, the role’s scopes override the key’s default scopes.

Response: 200 OK{"success": true}


Remove Role from API Key

DELETE /api/v1/roles/assign/:keyId

Removes the role, reverting the key to its own default scopes.

Response: 200 OK{"success": true}


Error Responses

CodeStatusDescription
UNAUTHORIZED401Missing or invalid API key / JWT
FORBIDDEN403Insufficient scope
NOT_FOUND404Key or role not found
VALIDATION_ERROR400Invalid request body