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 stringOne 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.