Tokens
Copy token from the create response. Later responses only show prefix and lastFour. tokenHash is never returned.
Personal access tokens (kfx_…)
Section titled “Personal access tokens (kfx_…)”| Method | Path | Description |
|---|---|---|
| GET/POST | /api/auth/api-keys |
List / create (secret returned once) |
| DELETE | /api/auth/api-keys/:keyId |
Revoke |
Bearer token for console APIs and data API (rules bypassed). See Personal access tokens.
Create
Section titled “Create”POST /api/auth/api-keys
Auth is a platform session JWT. A PAT calling GET, POST, or DELETE on this path is 403 { "success": false, "message": "Use a session token to manage API keys" }. 401 when there is no session.
| Key | Handling |
|---|---|
name |
Required string. 400 "name is required". Empty or over 100 characters is 400 "name must be 1–100 characters". |
organizationId |
Optional string. |
projectId |
Optional string. |
readOnly |
True only when the JSON value is boolean true. Any other value counts as false. |
expiresAt |
Optional ISO-8601 string. A non-empty string that does not parse is 400 "expiresAt must be an ISO-8601 timestamp". A past time is 400 "expiresAt must be in the future". |
An unknown project is 400 "project not found". An org/project mismatch is 400 "project does not belong to the selected organization". A non-member is 403 "You are not a member of that organization".
{ "name": "laptop", "readOnly": false}201. token is present only on this response. prefix is the first 12 characters. lastFour is the last 4.
{ "success": true, "data": { "id": "<uuid>", "userId": "<user uuid>", "name": "laptop", "prefix": "kfx_xxxxxxxx", "lastFour": "abcd", "readOnly": false, "createdAt": "<ISO-8601>", "token": "kfx_…" }}organizationId, projectId, expiresAt, and lastUsedAt appear only when set.
GET list is { "success": true, "data": { "keys": [ ... ] } }. Each item omits token.
429 when the user is at the key cap. limit_key is max_api_keys_per_user, and the body includes limit and current. message is the plan-catalog text.
{ "success": false, "message": "<plan-limit text>", "code": "quota_exceeded", "limit_key": "max_api_keys_per_user", "limit": 0, "current": 0}Service tokens (kfxs_…)
Section titled “Service tokens (kfxs_…)”| Method | Path | Description |
|---|---|---|
| GET/POST | /api/projects/:projectId/service-tokens |
List / create (secret once) |
| DELETE | /api/projects/:projectId/service-tokens/:tokenId |
Revoke |
Data API + POST /api/p/:projectId/:databaseId/auth/verify only. See Service tokens.
Create
Section titled “Create”POST /api/projects/:projectId/service-tokens
Auth is a platform JWT or a PAT with serviceTokens.write. A kfxs_ token on this route is 403 "Platform authentication required". The same 403 applies when that secret calls GET /api/auth/me.
| Key | Handling |
|---|---|
name |
String, default "". An empty name is 400. |
readOnly |
Bool, default false. |
expiresAt |
ISO-8601 string, or omitted. A string that fails to parse becomes null. A parsed time that is not in the future is 400. |
{ "name": "billing-worker", "readOnly": true}201. token starts with kfxs_ and is present only on this response. prefix starts with kfxs_.
{ "success": true, "data": { "id": "<uuid>", "projectId": "<project uuid>", "createdByUserId": "<user uuid>", "name": "billing-worker", "prefix": "kfxs_xxxxxxx", "lastFour": "abcd", "readOnly": true, "createdAt": "<ISO-8601>", "token": "kfxs_…" }}createdByUserId is omitted if null. expiresAt and lastUsedAt are omitted when null.
List shape is data.keys, and each item omits token. 404 "Project not found" without serviceTokens.write. 429 uses the same quota object with limit_key max_service_tokens_per_project. When plan limits are not wired, the hard cap is 20.
Compare
Section titled “Compare”PAT kfx_ |
Service kfxs_ |
Project JWT | |
|---|---|---|---|
Console /api/* |
Yes | No | No |
Data /api/p/* |
Yes, bypass rules | Yes, bypass rules | Yes, rules apply |
auth/verify |
Not the intended caller | Yes | No |
| Ship in a client app | No | No | Yes |
A read-only PAT fails any permission whose last segment is not read. Schema, token, CI, hosting, and project-management writes then come back as 404, or hosting create as 403 "Not allowed for this project".