Skip to content

API key management

API keys give programmatic clients long-lived credentials to authenticate against the Arbitex API. This guide covers the full key lifecycle: creation, use, rotation, temporary suspension, revocation, and org-level governance patterns for multi-team deployments.

For interactive user sessions authenticated via a login flow, use JWT access tokens rather than API keys. API keys are intended for service accounts, CI/CD pipelines, and any non-interactive client that cannot complete an OAuth flow.


Pass the API key in the Authorization header as a Bearer token:

Authorization: Bearer arb_a1b2c3d4e5f6...

The key is validated against a stored hash. The plaintext key is never stored after the creation response is returned. If you lose a key, revoke it and generate a replacement — there is no retrieval path.


Terminal window
curl -X POST https://api.arbitex.ai/api/auth/api-keys \
-H "Authorization: Bearer <your_session_token>" \
-H "Content-Type: application/json" \
-d '{
"description": "data-pipeline-prod",
"expires_in_days": 90
}'

Request body fields:

FieldRequiredDescription
descriptionNoHuman-readable label for identifying this key (e.g., "ci-pipeline-staging")
expires_in_daysNoDays until expiry. Omit for a non-expiring key.

Response (201 Created):

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"key_prefix": "arb_a1b2",
"description": "data-pipeline-prod",
"created_at": "2026-03-11T00:00:00Z",
"last_used": null,
"expires_at": "2026-06-09T00:00:00Z",
"is_enabled": true,
"api_key": "arb_a1b2c3d4e5f6g7h8..."
}

The api_key field is the only time the plaintext key is returned. Store it in your secrets manager immediately — it cannot be retrieved again.

Navigate to Settings → API Keys → New API Key. Enter a description and optional expiry. The generated key is shown once after creation.


Each key has an 8-character prefix (key_prefix) derived from the first 8 characters of the plaintext key. The prefix is stored in the database and shown in key listings.

Full key: arb_a1b2c3d4e5f6g7h8...
Prefix: arb_a1b2 ← stored, shown in listings

Use the prefix to match a credential you find in a log or config file to the corresponding key record without exposing the full value.


Returns metadata for all keys owned by the authenticated user. The plaintext key and hash are never included.

Terminal window
curl https://api.arbitex.ai/api/auth/api-keys \
-H "Authorization: Bearer <your_session_token>"

Response:

[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"key_prefix": "arb_a1b2",
"description": "data-pipeline-prod",
"created_at": "2026-03-11T00:00:00Z",
"last_used": "2026-03-11T08:30:00Z",
"expires_at": "2026-06-09T00:00:00Z",
"is_enabled": true
}
]

last_used is updated each time the key successfully authenticates a request. Keys with a last_used value more than 30 days in the past are candidates for rotation or revocation.


Pass expires_in_days at creation to set an expiry date. Once set, expiry cannot be changed — to modify the expiry of an existing key, revoke it and create a replacement.

Terminal window
# Expires in 30 days
curl -X POST https://api.arbitex.ai/api/auth/api-keys \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"description": "short-lived-script", "expires_in_days": 30}'
# Non-expiring (omit expires_in_days)
curl -X POST https://api.arbitex.ai/api/auth/api-keys \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"description": "long-running-service"}'

A key with expires_at set will return 401 Unauthorized after that timestamp regardless of its is_enabled state.


Disabling (PATCH with is_enabled: false) prevents the key from authenticating without deleting it. The key can be re-enabled. Use this to temporarily block access while investigating a suspected compromise, before deciding whether to revoke.

Terminal window
# Disable
curl -X PATCH https://api.arbitex.ai/api/auth/api-keys/{key_id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"is_enabled": false}'
# Re-enable
curl -X PATCH https://api.arbitex.ai/api/auth/api-keys/{key_id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"is_enabled": true}'

Revoking (DELETE) permanently removes the key record. The key is immediately invalid. Deletion is not reversible and has no soft-delete state.

Terminal window
curl -X DELETE https://api.arbitex.ai/api/auth/api-keys/{key_id} \
-H "Authorization: Bearer <token>"

Returns 204 No Content on success.

ActionReversibleRemoves from DBWhen to use
DisableYesNoTemporary suspension, active investigation
Revoke (DELETE)NoYesConfirmed compromise, decommissioning

Rotate on a fixed schedule (quarterly minimum) or immediately after any suspected exposure. The procedure below avoids downtime by running the old and new keys in parallel briefly.

  1. Generate the replacement key under the same service account, with a description that identifies it as the new key:

    Terminal window
    curl -X POST https://api.arbitex.ai/api/auth/api-keys \
    -H "Authorization: Bearer <session_token>" \
    -H "Content-Type: application/json" \
    -d '{
    "description": "data-pipeline-prod-2026-06",
    "expires_in_days": 90
    }'
  2. Copy the api_key value from the response and store it in your secrets manager.

  3. Update all consumers — environment variables, CI/CD secrets, Kubernetes secrets — to use the new key. Verify that each service authenticates successfully before proceeding.

  4. Revoke the old key:

    Terminal window
    curl -X DELETE https://api.arbitex.ai/api/auth/api-keys/{old_key_id} \
    -H "Authorization: Bearer <session_token>"

Do not revoke the old key until all clients are confirmed to be using the new one. Running both keys briefly in parallel is safe — they are independent credentials.


Scoping keys to teams via service accounts

Section titled “Scoping keys to teams via service accounts”

API keys carry the permissions of the user account that created them. There is no mechanism to scope a key to a subset of the creator’s permissions. To achieve least-privilege access across teams:

  1. Create a dedicated service account for each team or service (e.g., svc-data-pipeline, svc-ci-prod). Assign that account the minimum required role (user for most integrations, admin only if admin endpoints are required).

  2. Generate keys under the service account rather than personal user accounts. This ties the key’s lifecycle to the service account, not to an individual’s employment status.

  3. Provision one key per deployment environment (staging, prod) with distinct descriptions. This makes it possible to rotate the staging key without affecting production.

Service AccountKeysPurpose
svc-pipeline-prodpipeline-prod-2026-06Production data pipeline
svc-pipeline-stagingpipeline-staging-2026-06Staging data pipeline
svc-cici-prod-2026-06CI/CD integration tests
svc-analyticsanalytics-2026-06Read-only analytics queries

When a service account is decommissioned or a team member leaves, an admin can revoke all keys owned by that account via the admin endpoint:

Terminal window
# List all keys across all users
curl https://api.arbitex.ai/api/admin/api-keys \
-H "Authorization: Bearer <admin_token>"
# Revoke a specific key (admin can revoke any user's key)
curl -X DELETE https://api.arbitex.ai/api/admin/api-keys/{key_id} \
-H "Authorization: Bearer <admin_token>"

Admins (users with the admin role) can list and revoke API keys across all user accounts.

Terminal window
curl https://api.arbitex.ai/api/admin/api-keys \
-H "Authorization: Bearer <admin_token>"

Returns metadata for all keys across all user accounts. Use this for periodic audits: identify stale keys (no last_used in 30+ days), keys missing descriptions, or keys without expiry dates on accounts that should have them.

Terminal window
curl -X DELETE https://api.arbitex.ai/api/admin/api-keys/{key_id} \
-H "Authorization: Bearer <admin_token>"

Used during incident response to immediately invalidate a compromised credential without requiring access to the key owner’s account. Returns 204 No Content on success.


Store keys in a secrets manager. Do not embed API keys in source code, committed .env files, or CI/CD configuration in plaintext. Use Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, or your platform’s native secrets store. Inject the value at runtime.

Set expiry on all keys. Reserve non-expiring keys for cases where automated rotation is not feasible. For most use cases, 30–90 days is appropriate.

Use service accounts, not personal accounts. Keys generated under personal accounts lose access when the user’s account is deprovisioned. Service accounts have an independent lifecycle.

Monitor last_used. Keys unused for 30 or more days are candidates for revocation. Run a monthly audit via the admin list endpoint to clean up stale credentials.

Revoke immediately on exposure. If a key appears in a log, a public repository, or a compromised system, revoke it immediately using DELETE. Do not rely on disabling alone — a disabled key can be re-enabled. After revoking, review audit logs to assess unauthorized use.

Rotate on a fixed schedule. Quarterly rotation is the minimum. Automate rotation where possible: generate a replacement, update consumers, revoke the old key.


MethodEndpointAuthDescription
POST/api/auth/api-keysSession tokenCreate a key for the authenticated user
GET/api/auth/api-keysSession tokenList the authenticated user’s keys
PATCH/api/auth/api-keys/{key_id}Session tokenEnable or disable a key
DELETE/api/auth/api-keys/{key_id}Session tokenRevoke a key owned by the authenticated user
GET/api/admin/api-keysAdmin session tokenList all keys across all users
DELETE/api/admin/api-keys/{key_id}Admin session tokenRevoke any user’s key