AuralisDocs
OperationsAPI keys

Mint an API key, and read its secret the only time it is shown

Create a key for a programmatic caller and return its secret once.

/v1/api-keysAdmin
Operation id
create_api_key
Access
An editor or a viewer is refused.
POST/v1/api-keys

Create a key for a programmatic caller and return its secret once.

Read secret out of this response and store it now. It is the only time any route returns it. Nothing can recover it afterwards, and a lost secret means minting a replacement and revoking this key.

The secret starts with sk_zr_ and is presented as Authorization: Bearer sk_zr_..., on the same header a user's access token travels on. The prefix is what tells the two apart, so a caller never picks a header, only a credential.

Scopes decide what the key reaches, and a key with none reaches nothing. Send scopes or the key is minted with an empty set and is refused at every operation. A scope is <tag>:read, <tag>:write, <tag>:* or *, where the tag is the one the operation is grouped under in this document: tickets:read covers the ticket reads, tickets:write covers those and the ticket writes, * covers everything including operations added later. Scopes are checked here against what this deployment can actually grant, so a value like tickets:delete, which no operation could ever require, is refused with 422 rather than stored as a key that fails everywhere for a reason nobody can see.

Scopes narrow, they never widen. The key acts as the admin who created it and cannot do more than that member's current role allows, so changing or removing their membership changes what the key can do with no key administration at all. The key is also minted into the workspace this call was made against and is bound to it: it cannot be pointed at another workspace.

agent_id pins the key to one agent by adding an agent:<uuid> scope. It names a resource and no action, so it grants nothing by itself, it only narrows a key that also carries action scopes.

expires_in_days is optional and absent means the key never expires on its own. Set one. An expiry is the only thing that limits a leaked secret without someone noticing and revoking it.

Tenancy: the request is scoped to one workspace, and the credential presented is what selects it. A caller with no membership in that workspace is refused with 404, which is indistinguishable from a workspace that does not exist.

Authorisation: admin or owner. An editor or viewer receives 403 insufficient_role.

Access: Authorization: Bearer carrying either a realm access token or an API key. A key must hold the admin-resources:write scope, and the workspace role of the person who owns it must meet the floor above.

Authorization

AuthorizationBearer <token>

A realm-issued access token, presented as Authorization: Bearer <token>. It acts as the person who signed in, and every operation resolves their workspace role live from the membership record.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/v1/api-keys" \  -H "Content-Type: application/json" \  -d '{    "name": "Billing sync",    "expires_in_days": 90,    "scopes": [      "tickets:read",      "customers:read"    ]  }'
{  "id": "8f14e45f-ceea-4f4e-9c1f-2b0b2b7d4a11",  "name": "Billing sync",  "prefix": "sk_zr_7Qd2K",  "scopes": [    "tickets:read",    "customers:read"  ],  "expires_at": "2026-11-12T09:15:00+00:00",  "created_at": "2026-08-14T09:15:00+00:00",  "secret": "sk_zr_7Qd2KcW1nJqR0sYb4tVx9mAe6ZpH3uLgN8fD5kSc2rT"}