API key format, scopes, and key management endpoints

Authentication


9thSense uses API key authentication. Every request (except open paths) must include the X-Api-Key header.

X-Api-Key: zk_a1b2c3d4_e5f6a7b8c9d0e1f2a3b4c5d6

Key Format

New keys follow the split-key pattern:

zk_<prefix>_<secret>
  • zk — fixed literal prefix
  • <prefix> — 12-character hex token stored in plaintext for fast index lookup
  • <secret> — 32-character hex token; the full key zk_<prefix>_<secret> is verified with bcrypt

This approach allows O(1) DB lookup by prefix while never storing the secret in recoverable form.

Legacy keys (SHA-256 hashed, no prefix) are still accepted for backward compatibility. New keys should always use the split-key format.

Scopes

Each key is granted one or more scopes that control which endpoints it can call:

ScopeDescription
readRead-only access: list, get, search, export, analytics
writeMutation access: create, update, delete, deploy, run pipelines
adminKey management: create, list, revoke API keys

Most production integrations need read + write. Admin access is restricted to key management endpoints only.

Key Management

Create API Key

POST /v1/admin/keysendpoint

Requires scope: admin

Request body:

tenant_idstringrequired

The tenant this key will authenticate as.

namestringrequired

Human-readable label for the key (e.g. "Production Integration").

scopesstring[]required

List of scopes to grant. Values: "read", "write", "admin".

Example request:

{
  "tenant_id": "acme-corp",
  "name": "Production Integration",
  "scopes": ["read", "write"]
}

Example response (201):

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "tenant_id": "acme-corp",
  "name": "Production Integration",
  "scopes": ["read", "write"],
  "raw_key": "zk_a1b2c3_d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9",
  "last_used": null,
  "revoked": false,
  "created_at": "2026-03-25T10:00:00Z"
}

The raw_key field is returned only once at creation time. Store it securely — it cannot be retrieved again.


List API Keys

GET /v1/admin/keysendpoint

Requires scope: admin

Query parameters:

tenant_idstring

Filter keys by tenant. Defaults to the authenticated tenant.

Example response (200):

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "tenant_id": "acme-corp",
    "name": "Production Integration",
    "scopes": ["read", "write"],
    "last_used": "2026-03-24T18:30:00Z",
    "revoked": false,
    "created_at": "2026-03-20T09:00:00Z"
  }
]

The raw_key is never included in list responses.


Revoke API Key

DELETE /v1/admin/keys/{key_id}endpoint

Requires scope: admin

Path parameters:

key_idstringrequired

UUID of the key to revoke.

Returns 204 No Content on success. Returns 404 if the key does not exist or is already revoked.


Error Responses

StatusDetail
401 Missing X-Api-Key headerNo key provided
401 API key invalidKey not found in database
401 API key revokedKey has been revoked
403 Insufficient scopeKey lacks the required scope for the endpoint