Skip to content
Menu

DEVELOPER DOCS / CONTRACT 0.101.0

Create and manage API keys

Manage organisation keys, their scopes and revocation.

Get started with your AI agent.

Contract snapshot 0.101.0 · Deployment and client release availability follow the integration note for your environment.

Create only the access you need

Choose the minimum scopes required by the workflow and a useful key name. Minting requires the permissions specified by the connected contract. The create response contains the secret; display it only to the authorised caller.

Prepare the first organisation key

An organisation administrator can use POST /v1/keys/first with a session and no body. It makes the first key once, with data:read and usage:read scopes and 90-day expiry. Later calls reuse it with secret:null, even if expired or revoked. Never retry a write automatically or persist its one-time secret.

List without exposing secrets

Use the key listing for metadata and lifecycle state. Do not reconstruct a key from its prefix or store a displayed secret in analytics.

Revoke deliberately

A revoked key can no longer authorise requests. Confirm which workflow uses the key before revoking it, and handle failed writes without automatically repeating them.

Plan a rotation before revocation

Identify the server or workflow using the existing key. Create replacement access through the authorised process, update the server’s secret store and verify a bounded read before retiring the old key. Do not paste the replacement into a client bundle or a support conversation to test it.

Show lifecycle state clearly

A management screen should distinguish a listed key’s metadata from the secret shown at creation. Show scope and revocation state from the server response. If a create request times out, inspect the known key inventory before repeating it; the absence of a visible success message does not prove that no key was created.

POST

/v1/keys/first

Get your organisation's first API key, made once

For the dashboard's Start page (D-1601). The first call for an organisation with no key makes one ("First key", scopes data:read and usage:read, 90 days) and answers with `created: true` and its secret, shown once and never again: only its SHA-256 is stored. Every later call, at the same moment or after, answers with the same key, `created: false` and `secret: null`; if the organisation already had keys (made with createKey), it answers with the oldest of them, `created: false` and `secret: null`, and makes nothing. Always 200: `created` says which. It never makes a second key, even when the first is revoked or expired: use createKey for more. No request body. Organisation admins only, with a session, like createKey: a member or an API key gets `forbidden`. Sent with Cache-Control: no-store.

Response status codes
StatusMeaning
200Success
401Error. The `error.code` is one of: - `session_expired`: retry advice `refresh_credentials` - `unauthenticated`: retry advice `refresh_credentials`
403Error. The `error.code` is one of: - `forbidden`: retry advice `never` - `org_missing`: retry advice `never`
429Error. The `error.code` is one of: - `rate_limited`: retry advice `after_reset`
500Error. The `error.code` is one of: - `internal`: retry advice `bounded`
503Error. The `error.code` is one of: - `unavailable`: retry advice `bounded`

Full response fields and reusable schemas are in the downloadable OpenAPI contract.

POST

/v1/keys

Mint an API key for your organisation

Organisation admins only, signed in with a session (an API key cannot mint keys). The secret is in this response and nowhere else: only its SHA-256 is stored. The response is sent with Cache-Control: no-store.

Request body schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "$ref": "#/components/schemas/CreateKeyRequest"
      },
      "example": {
        "name": "pricing agent",
        "scopes": [
          "data:read"
        ],
        "expiresInDays": 30
      }
    }
  }
}
Response status codes
StatusMeaning
201Success
400Error. The `error.code` is one of: - `invalid_json`: retry advice `fix_request` - `invalid_request`: retry advice `fix_request`
401Error. The `error.code` is one of: - `session_expired`: retry advice `refresh_credentials` - `unauthenticated`: retry advice `refresh_credentials`
403Error. The `error.code` is one of: - `forbidden`: retry advice `never` - `org_missing`: retry advice `never`
413Error. The `error.code` is one of: - `payload_too_large`: retry advice `fix_request`
415Error. The `error.code` is one of: - `unsupported_media_type`: retry advice `fix_request`
429Error. The `error.code` is one of: - `rate_limited`: retry advice `after_reset`
500Error. The `error.code` is one of: - `internal`: retry advice `bounded`
503Error. The `error.code` is one of: - `unavailable`: retry advice `bounded`

Full response fields and reusable schemas are in the downloadable OpenAPI contract.

GET

/v1/keys

List your organisation's API keys

Any signed-in member. Newest first, including expired and revoked keys. Never returns a secret, only its first 12 characters (`prefix`).

Response status codes
StatusMeaning
200Success
401Error. The `error.code` is one of: - `session_expired`: retry advice `refresh_credentials` - `unauthenticated`: retry advice `refresh_credentials`
403Error. The `error.code` is one of: - `forbidden`: retry advice `never` - `org_missing`: retry advice `never`
429Error. The `error.code` is one of: - `rate_limited`: retry advice `after_reset`
500Error. The `error.code` is one of: - `internal`: retry advice `bounded`
503Error. The `error.code` is one of: - `unavailable`: retry advice `bounded`

Full response fields and reusable schemas are in the downloadable OpenAPI contract.

POST

/v1/keys/{id}/revoke

Revoke an API key

Organisation admins only, with a session. Takes effect on the next request. Revoking twice is harmless and keeps the first revocation time. A key of another organisation, or no such key, is `not_found`: the API never confirms that it exists. Keys are never deleted.

Parameters
[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string",
      "format": "uuid"
    }
  }
]
Response status codes
StatusMeaning
200Success
400Error. The `error.code` is one of: - `invalid_request`: retry advice `fix_request`
401Error. The `error.code` is one of: - `session_expired`: retry advice `refresh_credentials` - `unauthenticated`: retry advice `refresh_credentials`
403Error. The `error.code` is one of: - `forbidden`: retry advice `never` - `org_missing`: retry advice `never`
404Error. The `error.code` is one of: - `not_found`: retry advice `fix_request`
429Error. The `error.code` is one of: - `rate_limited`: retry advice `after_reset`
500Error. The `error.code` is one of: - `internal`: retry advice `bounded`
503Error. The `error.code` is one of: - `unavailable`: retry advice `bounded`

Full response fields and reusable schemas are in the downloadable OpenAPI contract.