Authentication
Every request to /v1/chat/completions and /v1/messages carries an API key. GET /v1/models does not need one.
Key format#
A key is sk-sator-v1- followed by 24 characters from A–Z, a–z and 0–9:
sk-sator-v1-XXXXXXXXXXXXXXXXXXXXXXXXTreat it as a password. Sator stores only a SHA-256 hash of it and its last four characters, so the full key exists in exactly one place after creation: wherever you put it.
Headers#
Both endpoints accept the key in either of two headers, and both headers work on both endpoints:
| Header | Who sends it |
|---|---|
Authorization: Bearer sk-sator-v1-… | OpenAI SDKs, Claude Code with ANTHROPIC_AUTH_TOKEN, most tools |
x-api-key: sk-sator-v1-… | Anthropic SDKs, Claude Code with ANTHROPIC_API_KEY |
If both are present, Authorization is read first. There is nothing to configure: whichever your client sends is fine.
The Anthropic wire also reads anthropic-version; if your client sends none, 2023-06-01 is assumed. See Messages.
Key lifecycle#
- Create a key in the dashboard. No balance is needed — keys are free and only calls cost money.
- Shown once. The full key is in the response that created it and nowhere else. The dashboard shows the last four characters afterwards.
- Up to 20 live keys per account. Revoked keys do not count against the limit.
- Revoke from the dashboard. Revocation is immediate: every key lookup reads the database directly and nothing is cached, so a revoked key fails on the very next request.
- Rotate by creating the new key first and revoking the old one after your tools have switched. Per-key usage attribution outlives the key, so the dashboard's spend-by-key history stays intact.
- Name keys (up to 64 characters). One key per tool or machine makes the by-key usage table meaningful and makes a revocation surgical.
What a bad key looks like#
A missing, unknown or revoked key gets the same 401 with code invalid_api_key, deliberately — which of the three it was would tell a guesser how close they got:
{"error": {"message": "Incorrect API key provided. You can find your API key at https://sator.princep.org/dashboard.", "type": "invalid_request_error", "param": null, "code": "invalid_api_key"}}On the Anthropic wire the same failure is an authentication_error. Ten failed authentications in a minute from one IP address are answered 429 with code too_many_failed_auth and a retry-after header. See Errors.
Browsers#
CORS is open (access-control-allow-origin: *, no credentials), since the key is always an explicit header and never a cookie. authorization, x-api-key, content-type, anthropic-version, anthropic-beta, anthropic-dangerous-direct-browser-access, x-session-id and the headers the official SDKs add are all allowed; x-request-id and retry-after are exposed on responses. A key in a browser is a key anyone with the page can read, so use one there only for something you would be happy to revoke.