What this API is

One key and one base URL for text, images and video, one account for all of it, and each request's cost inside the answer.

TeamToken is a gateway to text, image and video models: one key, one base URL, one account. The answer carries back the logical model name that was asked for.

The base URL is https://api.teamtoken.store/v1: /v1/chat/completions, /v1/responses, /v1/embeddings (OpenAI shape), /v1/messages (Anthropic shape), /v1/images/generations, /v1/images/edits, /v1/videos, GET /v1/models, GET /v1/balance.

curl https://api.teamtoken.store/v1/chat/completions \
  -H "Authorization: Bearer $TEAMTOKEN_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "gpt-5.6-sol", "messages": [{"role":"user","content":"Hi"}] }'

Compatible means an existing SDK only needs re-pointing

Compatible is literal: the body reaches the upstream as it is, and the gateway reads only the model name, the streaming flag and the output ceiling. Any client with a configurable base_url is re-pointed by two values — base_url and the key; Anthropic clients go to /v1/messages.

Ready-made configs for agents and IDEs (Codex CLI, Claude Code, Cline) are on /docs, under "Connect your tool".

from openai import OpenAI
import os

# Nothing but these two lines is TeamToken-specific.
client = OpenAI(base_url="https://api.teamtoken.store/v1", api_key=os.environ["TEAMTOKEN_KEY"])

r = client.chat.completions.create(
    model="gpt-5.6-sol",
    messages=[{"role": "user", "content": "Hi"}],
)
print(r.choices[0].message.content)
print(r.usage.model_extra["cost_usd"])   # what this call cost, as a string

One account for all of it, and the cost arrives in the answer

There is one account: text, images and video spend the same money. What is left is granted minus text spend minus effective media spend, where "effective" means charged plus held for generations still running — so the balance drops when a job is queued, not when it finishes.

The remainder comes from GET /v1/balance behind the same key; each request's cost is inside the answer (/docs/getting-started, step 4).

Media is a job, not a long answer

Media takes longer than an HTTP connection should be held open, so it has state. POST /v1/images/generations answers 200 with base64 images or 202 with a job id (result: GET /v1/images/jobs/{job_id}); POST /v1/videos answers 202 by default, and with wait: true it waits up to 90 s and hands back the finished clip (result: GET /v1/videos/{job_id}).

What this API does not have

No subscription and no plans: a top-up creates a credit, every request lowers what is left.

No provider keys and no accounts with them: the upstreams are ours, and their names never leave the gateway.

Not one price in the documentation: the catalog is edited without a deploy, so a number in prose would go stale silently. Live numbers: GET /cabinet/api/public/models and /cabinet/api/public/media-models, keyless.

Map of the documentation

Authentication — /docs/auth: where a key comes from, the two headers, 401 and 402.

Your first request — /docs/getting-started: five steps from a key to a cost.

Reference — /docs: a page per route, with fields, examples and a table of failures. Machine-readable — /openapi.public.{ru,en}.json. Availability — GET /cabinet/api/public/model-status.