Authentication
A key from the cabinet, the two accepted headers, and what 401 and 402 actually mean.
There is one authentication scheme for the whole gateway: a key in a header, and nothing else. No request signing, no OAuth, no per-modality secret.
Where a key comes from
A key is created in the cabinet, on the "Keys" page (app.teamtoken.store/keys): shown in full when created, revealable there later. It starts with sk-.
An account may hold several keys — that is how services are separated: a compromised one is deleted, the others keep working. The money stays shared; a spend limit caps the key rather than handing it a wallet.
# Держи ключ в окружении, а не в коде / keep the key in your environment, not in code:
export TEAMTOKEN_KEY="sk-…"Two headers, and both are real
A key is accepted in two forms: Authorization: Bearer sk-… (preferred, every SDK knows it) and x-api-key: sk-… (for clients that cannot send Authorization). No route behaves differently; when both are sent, Authorization wins.
POST requests require Content-Type: application/json; the rest of the rules sit next to the quickstart on /docs.
curl https://api.teamtoken.store/v1/models \
-H "Authorization: Bearer $TEAMTOKEN_KEY"What answers without a key
The catalog and the status are public: /cabinet/api/public/models, /media-models and /model-status all answer anonymously — callable even from a build script, with no key next to them.
A key spends real money
A key is access to the balance, so it belongs neither in a frontend nor in a public repository: code in a browser hands the key over with itself, and a key in the commit history works long after the line was deleted.
If a key leaks, delete it in the cabinet (app.teamtoken.store/keys) and issue a new one. Handing one over — set its spend limit before, not after the incident.
401 — no key, or not our key
On the endpoints that need a key, a 401 means: no key in the request, or the key is not ours. Check Authorization: Bearer or x-api-key.
A malformed header lands here too: "Bearer" without the space, "Token" instead of "Bearer", a key in a query parameter — indistinguishable from a request with no key.
402 — not enough for this request's worst case
A 402 means: the balance does not cover this request's worst-case price. The worst case, not an average: input tokens estimated plus the output ceiling, each at its own rate and with a margin; the ceiling comes from the request (max_tokens), else from the model's catalog row.
Consequence: on a thin balance a ceiling of thousands of tokens gets a 402 while a ceiling of two hundred goes through. The refusal body names the remainder and the request's possible price.
A 402 is about money, not the key: the key works, the balance ran out, a top-up clears the refusal. Media answers 402 the same way — per image or per second of video. One exception: a byte-identical replay inside a short TTL is served from the idempotency cache even on an empty wallet. The cache covers chat, Responses and embeddings; the Anthropic shape (/v1/messages) has none, so a repeat there is billed again.
The key, the balance and each request's cost
Money belongs to the account, not the key: however many keys are issued, they spend one balance. GET /v1/balance returns it behind the same key, in-flight holds included; each answer's own cost is on /docs/getting-started, step 4.