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
- Create the new key first. Both keys work at the same time.
- Deploy the new key to your application.
- 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
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-stagingtells 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
- Revoke it immediately. Calls stop at once.
- Create a replacement and deploy it.
- 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.