Ada AI

API Keys

Proxy keys (sk-rc-…) authenticate /v1/* traffic. Each key is scoped to exactly one owner — you, or one organization — fixed at mint time.

A proxy key (sk-rc-…) authenticates all traffic on /v1/*. Each key is scoped to exactly one owner — your personal account, or one organization — chosen when the key is minted and fixed thereafter.

Three credential types — don't mix them

The API accepts three kinds of credentials, and each route accepts exactly one.

KindHeaderWhat it grants
Proxy key (sk-rc-…)Authorization: Bearer sk-rc-… or X-API-Key: sk-rc-…Forwarded LLM traffic on /v1/*.
Stytch session JWTAuthorization: Bearer <jwt>Account management under /me/* and /auth/apikeys. Held by the dashboard in a cookie.
Admin tokenX-Admin-Token: <token>/admin/* routes. Out-of-band; not used by the dashboard.

Never authorize /v1/* with a Stytch JWT or admin token. Never put a proxy key on /me/*.

Minting a key

In the dashboard, KeysNew key, then:

  1. Give it a name (for you; any string).
  2. Pick an OwnerPersonal (default), or one of the organizations you belong to.
  3. Click Create.

The full key (sk-rc-…) is shown once. Copy it immediately — the dashboard won't display it again, and there's no way to recover it.

API equivalent

curl -X POST https://api.ada.ai/auth/apikeys \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"name": "Production"}'
# → { "id": 42, "name": "Production", "prefix": "sk-rc-...", "api_key": "sk-rc-<full>", "created_at": "..." }

To scope the key to an organization, include organization_id:

curl -X POST https://api.ada.ai/auth/apikeys \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme prod", "organization_id": 7}'

The caller must already be a member of that org. A non-member and a nonexistent org both return 403 not a member of that organization — deliberately identical, so the response can't be used to probe which org IDs exist.

Key scoping

A key's owner is fixed at mint time. There is no way to change it afterward — mint a new key if you need to switch owners.

  • A personal key resolves only against your personal upstreams.
  • An org key resolves only against that org's upstreams — never your personal ones, and never another org's.
  • A single key uses all of its owner's enabled upstreams. There's no per-upstream scoping in v1: to separate traffic within one owner, mint separate keys — they share the same upstream pool.

See Organizations for team-owned upstreams.

Listing your keys

curl https://api.ada.ai/auth/apikeys \
  -H "Authorization: Bearer $JWT"

Returns metadata only — id, name, prefix, scope, timestamps — never the plaintext or a hash.

Rotating a key

In the dashboard: Keys → the key → Rotate. This generates a new value (shown once) and immediately invalidates the old one — across every pod, with no grace period.

No grace period

Rotate during a deploy window, not mid-traffic. The old key stops working the instant you rotate, so any client still holding it will get 401.

There is no API equivalent that returns the new plaintext to a non-dashboard caller; rotate from the dashboard or mint a fresh key.

Revoking a key

curl -X POST https://api.ada.ai/auth/apikeys/42/revoke \
  -H "Authorization: Bearer $JWT"

Permanent, no grace period — the key's cached auth entry is invalidated immediately on every pod. Organization admins can also revoke a member's org-scoped key from the org's Keys tab.

Building a CLI?

The dashboard's "New key" flow assumes you can copy/paste from a browser. For CLI tools that need to bootstrap a key non-interactively, Ada AI exposes a browser-assisted device flow — see CLI authentication.

On this page