API keys

API keys

A key is a credential that belongs to your account, and every call it makes bills that
account. Treat one like a password.

Creating a key

Dashboard, then API keys, then create. The plaintext is shown once; the server
keeps only a hash, so a lost key cannot be recovered, only replaced.

A key starts with sk- and is sent as a bearer token or as x-api-key. See
Authentication for the header details.

Rotating without downtime

  1. Create the new key first. Both keys work at the same time.
  2. Deploy the new key to your application.
  3. Revoke the old one once you see traffic on the new one.

Revoking is immediate: there is no grace period, so the reverse order breaks your service.

Limits

Limit Behaviour
Active keys per account Capped. Revoking frees a slot.
Expired or revoked keys Do not count against the cap, so rotating does not lock you out
IP allowlist (optional) A caller outside it gets 403 ip_not_allowed

The allowlist is checked on every request rather than only at creation, so narrowing it
takes effect for keys already in use.

What a key can do

Everything on /v1 for its own account, and nothing for anyone else’s. The wallet
endpoints are scoped to the key’s owner: another account’s transaction id answers 404
rather than 403, so the endpoint cannot be used to probe for ids.

When a key stops working

Four situations share one code, 401 invalid_api_key: missing, malformed, revoked and
expired. All four are fixed the same way, so the distinction is not worth a separate code.

{
  "error": {
    "code": "invalid_api_key",
    "message": "Invalid API key (invalid_api_key)",
    "request_id": "01M73N2HP4HDDZH803J1C120HT"
  }
}

Trailing whitespace is not the cause: header values are trimmed before lookup, because a
newline pasted from a dotfile used to produce a confusing 401.

Rules worth following

Never ship a key in a client application

A key in a browser bundle or a mobile binary is published. Proxy through your own backend
and keep the key server-side. Every call bills the key’s owner, so a leaked key spends your
balance, not someone else’s.

  • One key per application. Revoking one then does not break the others.
  • Name them by purpose. A key called ci-staging tells you what to revoke.
  • Do not paste keys into issues or logs. The first characters plus a timestamp are
    enough for support to find one.

If a key leaks

  1. Revoke it immediately. Calls stop at once.
  2. Create a replacement and deploy it.
  3. Read GET /transactions?since=<when> for the exposure window and check for spend you do
    not recognise.

balance_micro_usd before and after that window is the number to look at, and each usage
row names the model and the token counts behind it.