Skip to main content
All requests to the DecimalAI API authenticate with an API key. Pass it either as a standard Authorization: Bearer <key> header or as an x-api-key: <key> header — both are accepted and equivalent. Pick one; if both are present, the Authorization header wins.
curl https://api.decimal.ai/api/v1/traces \
  -H "Authorization: Bearer dai_sk_..."
Every key starts with the prefix dai_sk_. The dashboard’s session cookie auth (/api/v1/auth/me, /api/v1/auth/verify) is for the web UI only — programmatic access always uses API keys.

Key scopes

Scope controls what data a key can see. It’s set at creation time and is immutable.
ScopeWhat it seesWhen to use
globalEverything in the orgSDK init for an app that spans multiple workspaces; the only scope that can create or revoke other keys
workspaceOne workspace (specified at create time)CI key for one team’s repo
projectOne project under a workspacePer-environment keys (dev / staging / prod)
A key cannot escalate to a wider scope. To widen access, create a new key.

Key permissions

Permissions control what actions a key can take, orthogonal to scope. Default is admin for backwards compatibility.
PermissionAllowed methods
readGET only
writeGET + POST / PUT / PATCH (ingest, register, attach)
adminAll of the above + DELETE / destructive ops
A CI key that only ingests traces should be write. An SRE read-only on-call key should be read. Use admin only for keys that need to delete data.

Expiration

Keys can optionally expire. Pass an ISO-8601 expires_at when creating; omit for a non-expiring key (the historical default). Once expired, requests return 401 with the response body {"detail": "API key has expired"} — a distinct detail string from the revoked-key case (also 401, {"detail": "API key has been revoked"}), so callers can prompt regeneration without a generic “auth failed” branch. Both are authentication failures, so they share the 401 status with a missing or malformed key; the detail string is what distinguishes them.

Creating a key

From the dashboard

  1. Sign in to the DecimalAI Dashboard
  2. Go to Settings → API Keys
  3. Click Create API Key, choose scope, permissions, and optional expiry
  4. Copy the key — it’s shown only once and stored as a SHA-256 hash on the server

Programmatically

Requires an existing global-scoped key with admin role (only global keys can mint other keys):
curl -X POST https://api.decimal.ai/api/v1/api-keys \
  -H "Authorization: Bearer dai_sk_<your_global_admin_key>" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "ci-staging",
    "scope": "workspace",
    "workspace_id": "ws_abc123",
    "permissions": "write",
    "expires_at": "2027-01-01T00:00:00Z"
  }'
Response (the raw key is returned once; the server keeps only the hash):
{
  "id": "key_abc123",
  "raw_key": "dai_sk_...",
  "key_prefix": "dai_sk_xxxxxxxx...",
  "label": "ci-staging",
  "scope": "workspace",
  "permissions": "write",
  "expires_at": "2027-01-01T00:00:00Z",
  "created_at": "2026-05-28T18:00:00Z"
}
A security-alert email goes to the org’s billing contact when a new key is created. If you didn’t expect it, revoke immediately.

Listing keys

curl https://api.decimal.ai/api/v1/api-keys \
  -H "Authorization: Bearer dai_sk_..."
Returns prefix, label, scope, permissions, created_at, and last_used_at for each key. Raw keys are never returned. Only global-scoped keys can list. last_used_at is updated as a fire-and-forget UPDATE on every successful auth — use it to surface stale-but-not-revoked keys for cleanup.

Rotating a key

There’s no in-place rotation. To rotate:
1

Create a new key

Mint a new key with the same scope and permissions as the one you’re replacing.
2

Roll it out

Deploy the new key to your callers (env vars, secret manager) and let them pick it up.
3

Revoke the old key

Revoke the old key once last_used_at on it stops advancing.
The last step is the only way to know rotation is complete — if last_used_at is still climbing, something still has the old key.

Revoking a key

curl -X DELETE https://api.decimal.ai/api/v1/api-keys/{key_id} \
  -H "Authorization: Bearer dai_sk_<your_global_admin_key>"
Revocation is immediate — in-flight requests authenticated with the revoked key will fail on the next handler invocation. Only global-scoped keys can revoke. A revoked key is soft-deleted (the row stays for audit); re-creation requires a new POST.

Security checklist

  • Never commit keys to source control. Use environment variables or a secret manager.
  • Use the narrowest scope and permissions that work. A CI key that only sends traces should be workspace/write, not global/admin.
  • Set expires_at on keys handed to humans. Long-lived keys without expiry should belong to automated systems with rotation procedures.
  • Audit last_used_at quarterly. Revoke anything that hasn’t been used in 90 days.
  • Lost a key? Revoke first, regenerate second. The new key won’t have the old key’s id — update any infra that pins to it.