Docs menu

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-XXXXXXXXXXXXXXXXXXXXXXXX

Treat 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:

HeaderWho 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:

json
{"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.