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.
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.
Request upload capabilities and register document versions.
collections:read
Read compile jobs, corpora and compiled packages.
collections:compile
Start compiles, answer blockers, cancel a run.
collections:download
Download the signed knowledge package.
worlds:read
Read the active World, its objects, relations and evidence.
ask:read
Grounded answers and hybrid retrieval over the active World.
connections:read
Read connection state and cursors.
connections:write
Create and revoke connections.
connections:sync
Advance 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.
NoteOver 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"
# Browser session only. A developer API key is refused on this route.
import os
import requests
response = requests.request(
"POST",
"https://tavonel.com/api/v1/developer/keys/{id}/rotate",
headers={"Authorization": "Bearer " + os.environ["TAVONEL_SESSION_JWT"]},
timeout=30,
)
response.raise_for_status()
print(response.json())
// Browser session only. A developer API key is refused on this route.
const response = await fetch("https://tavonel.com/api/v1/developer/keys/{id}/rotate", {
method: "POST",
headers: { authorization: `Bearer ${process.env.TAVONEL_SESSION_JWT}` },
});
if (!response.ok) throw new Error(`${response.status} ${(await response.json()).code}`);
console.log(await response.json());
Status
Response
201
The one-time replacement credential. Store it now; it is not shown again.
400
API_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.
401
AUTH_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.
402
TRIAL_FEATURE_NOT_INCLUDED — The operation — key rotation among them — is not in the free evaluation.
404
API_KEY_NOT_FOUND — No such key in this workspace.
413
REQUEST_TOO_LARGE — The JSON body exceeded the route's bound.
503
API_KEY_ROTATE_FAILED — The rotation could not be completed. API_KEY_CREATE_FAILED — The replacement key could not be written, so nothing was revoked either. DEVELOPER_AUDIT_WRITE_FAILED — An audit event could not be written, so the action it describes was refused. Every key create, rotate and revoke writes an audit row or does not happen.
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"
# Browser session only. A developer API key is refused on this route.
import os
import requests
response = requests.request(
"GET",
"https://tavonel.com/api/v1/developer/audit",
headers={"Authorization": "Bearer " + os.environ["TAVONEL_SESSION_JWT"]},
timeout=30,
)
response.raise_for_status()
print(response.json())
// Browser session only. A developer API key is refused on this route.
const response = await fetch("https://tavonel.com/api/v1/developer/audit", {
method: "GET",
headers: { authorization: `Bearer ${process.env.TAVONEL_SESSION_JWT}` },
});
if (!response.ok) throw new Error(`${response.status} ${(await response.json()).code}`);
console.log(await response.json());
Status
Response
200
{ code: OK, events }, newest first.
400
AUDIT_LIMIT_INVALID — The audit limit was outside its range.
401
AUTH_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.
503
DEVELOPER_AUDIT_READ_FAILED — The audit trail could not be read. DEVELOPER_STORE_NOT_CONFIGURED — The developer store is not configured.
What no key can do
NoteActivation, 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