Authentication

Bearer keys, the scopes they carry, and what no key can do.

Getting a key

Keys are created in the workspace, under Developers. The plaintext is shown once, at creation, and is not recoverable afterwards — store it before you close the dialog. Creating, rotating and revoking a key each write an audit row, readable through the audit endpoint below. A request with no key, or with a key TAVONEL did not issue, is refused with 401 and the code AUTH_REQUIRED: that is the first error most integrations see, and it means the credential rather than the request.

POST/developer/keys

Creates a workspace-scoped key with an explicit scope set. The plaintext `token` is in this response and nowhere else: only its SHA-256 digest is stored. A free evaluation cannot create keys and is answered 402 TRIAL_FEATURE_NOT_INCLUDED; the same refusal meets a free evaluation approving a remote MCP connection, which mints a key (see `x-tavonel-remote-mcp`). Where trial AI access is enabled, a free evaluation may hold one live read-only key (the remote MCP scopes) -- hand-made or minted by a remote MCP connection -- and a spent evaluation bound is answered 402 TRIAL_LIMIT_REACHED.

# Browser session only. A developer API key is refused on this route.
curl -sS -X POST https://tavonel.com/api/developer/keys \
  -H "Authorization: Bearer $TAVONEL_SESSION_JWT" \
  -H "content-type: application/json" \
  -d '{ "name": "<name>", "scopes": [ "documents:read" ], "expiresInDays": "<expiresInDays>" }'
Request body
{
  "name": "<name>",
  "scopes": [
    "documents:read"
  ],
  "expiresInDays": "<expiresInDays>"
}
StatusResponse
201The key's record and its one-time plaintext token. Store the token now; it is not shown again.
400INVALID_JSON — The body was not parseable JSON. API_KEY_INPUT_INVALID — The rotation body did not validate.
401AUTH_REQUIRED — No credential was presented, or the bearer token is not a key TAVONEL issued. This is what an unauthenticated request to any scoped route returns.
402TRIAL_FEATURE_NOT_INCLUDED — The operation is not in the free evaluation: creating, rotating or revoking an API key, and approving a remote MCP connection (which mints a key), among them. TRIAL_LIMIT_REACHED — A free-evaluation bound is spent: its AI-access window, page, World or daily query bound, which Ask in the browser and World activation also read, or, with trial AI access enabled, its one live API key (hand-made, or minted by approving a remote MCP connection).
403PILOT_ACCESS_REQUIRED — The credential is valid and the workspace it names is not admitted to TAVONEL. AUTHORIZATION_CHANGED_RETRY — The caller's authorization changed while the request was in flight, so the request was abandoned rather than finished under a permission that may no longer hold.
413REQUEST_TOO_LARGE — The JSON body exceeded the route's bound.
503DEVELOPER_STORE_NOT_CONFIGURED — The developer store is not configured. API_KEY_CREATE_FAILED — The replacement key could not be written, so nothing was revoked either. DEVELOPER_STORE_BINDING_INVALID — A stored row did not validate, so it was refused rather than returned partially.

Sending the key

Send the key as a bearer token. Keys are workspace-scoped and carry an explicit scope set; a request outside its scopes is refused with 403 and API_SCOPE_REQUIRED rather than silently returning less.

Every request
curl -sS https://tavonel.com/api/v1/documents -H "Authorization: Bearer $TAVONEL_API_KEY"

The scopes a key can hold

ScopeGrants
documents:readList documents and read their processing state.
documents:intakeRequest upload capabilities and register document versions.
collections:readRead compile jobs, corpora and compiled packages.
collections:compileStart compiles, answer blockers, cancel a run.
collections:downloadDownload the signed knowledge package.
worlds:readRead the active World, its objects, relations and evidence.
ask:readGrounded answers and hybrid retrieval over the active World.
connections:readRead connection state and cursors.
connections:writeCreate and revoke connections.
connections:syncAdvance a connection cursor and collect what changed.

How often you may call

Every scoped request consumes one unit of a per-minute allowance held per key and per scope. The window is a clock minute rather than a rolling one, so an allowance that is spent is free again at the top of the next minute. The per-scope numbers are on the Billing and limits page, printed from the same values the authorizer enforces.

Note Over the allowance the answer is 429 with API_RATE_LIMITED. No Retry-After header is sent on that code today and no X-RateLimit-* headers are published — waiting for the next clock minute is sufficient by construction, and documenting a header we do not send would be worse than documenting the window. The separate hourly allowance on World activation, rollback and retrieval-index rebuild answers ACTIVATION_RATE_LIMITED and does carry Retry-After.

Rotating a key, and reading the audit trail

Rotation is atomic: a replacement key is created, the source key is revoked and an audit event is written, or none of the three happened. There is no window in which the old key is dead and no replacement exists. Both operations take a signed-in browser session — a developer API key cannot call them, which is the same boundary activation sits behind.

POST/developer/keys/{id}/rotate

Atomically creates a replacement key, revokes the source key and writes an audit event. Plaintext is returned once and is not recoverable afterwards. Either all three happened or none did — there is no state where the old key is revoked and no replacement exists.

# Browser session only. A developer API key is refused on this route.
curl -sS -X POST https://tavonel.com/api/v1/developer/keys/{id}/rotate \
  -H "Authorization: Bearer $TAVONEL_SESSION_JWT" \
  -H "content-type: application/json" \
  -d '{ "name": "<name>", "scopes": [ "documents:read" ], "expiresInDays": "<expiresInDays>" }'
Request body
{
  "name": "<name>",
  "scopes": [
    "documents:read"
  ],
  "expiresInDays": "<expiresInDays>"
}
StatusResponse
201The replacement key's record, its one-time plaintext token, and replacedKeyId, the key now revoked. Store the token now; it is not shown again.
400API_KEY_ID_INVALID — The key id was not a UUID. API_KEY_INPUT_INVALID — The rotation body did not validate. INVALID_JSON — The body was not parseable JSON.
401AUTH_REQUIRED — No credential was presented, or the bearer token is not a key TAVONEL issued. This is what an unauthenticated request to any scoped route returns.
402TRIAL_FEATURE_NOT_INCLUDED — The operation is not in the free evaluation: creating, rotating or revoking an API key, and approving a remote MCP connection (which mints a key), among them. TRIAL_LIMIT_REACHED — A free-evaluation bound is spent: its AI-access window, page, World or daily query bound, which Ask in the browser and World activation also read, or, with trial AI access enabled, its one live API key (hand-made, or minted by approving a remote MCP connection).
403PILOT_ACCESS_REQUIRED — The credential is valid and the workspace it names is not admitted to TAVONEL. AUTHORIZATION_CHANGED_RETRY — The caller's authorization changed while the request was in flight, so the request was abandoned rather than finished under a permission that may no longer hold.
404API_KEY_NOT_FOUND — No such key in this workspace.
413REQUEST_TOO_LARGE — The JSON body exceeded the route's bound.
503API_KEY_ROTATE_FAILED — The rotation could not be completed. DEVELOPER_STORE_NOT_CONFIGURED — The developer store is not configured. DEVELOPER_STORE_BINDING_INVALID — A stored row did not validate, so it was refused rather than returned partially.
GET/developer/audit

The tenant-scoped developer and connector audit trail, newest first, bounded by `limit`. Every key create, rotate and revoke writes a row here or does not happen.

# Browser session only. A developer API key is refused on this route.
curl -sS -X GET https://tavonel.com/api/v1/developer/audit \
  -H "Authorization: Bearer $TAVONEL_SESSION_JWT"
StatusResponse
200{ code: OK, apiVersion, events }, newest first.
400AUDIT_LIMIT_INVALID — The audit limit was outside its range.
401AUTH_REQUIRED — No credential was presented, or the bearer token is not a key TAVONEL issued. This is what an unauthenticated request to any scoped route returns.
403PILOT_ACCESS_REQUIRED — The credential is valid and the workspace it names is not admitted to TAVONEL. AUTHORIZATION_CHANGED_RETRY — The caller's authorization changed while the request was in flight, so the request was abandoned rather than finished under a permission that may no longer hold.
503DEVELOPER_AUDIT_READ_FAILED — The audit trail could not be read. DEVELOPER_STORE_NOT_CONFIGURED — The developer store is not configured. DEVELOPER_STORE_BINDING_INVALID — A stored row did not validate, so it was refused rather than returned partially.

What no key can do

Note Activation, rollback and destructive workspace actions are human-session-only. There is no scope that grants them, which is why you will not find one in this table.

API version 2026-09-02.1 · reviewed 11 September 2026

Something here out of date or wrong? Report an issue with this page.