Curated models for your best work
Join the waitlistRouter docs
Requests and auth
How to authenticate against the rail and what a request may carry.
Authentication
Use a rail key (tsr_...) from Router. Either header form works.
x-api-key: tsr_... # or Authorization: Bearer tsr_...
Keys are stored hashed, shown once at creation, and revoke instantly (no cache in the auth path).
Use only a TokenSpend rail key, not a provider, Capture, or admin credential. Keep keys server-side and out of source control. Your workspace needs an eligible connected provider key or managed credits.
Endpoints
Base URL https://api.tokenspend.dev
POST /v1/chat/completions: OpenAI Chat CompletionsPOST /v1/responses: Responses, with native Astra toolsPOST /v1/messages: Anthropic MessagesPOST /v1/messages/count_tokens: supported Messages modelsGET /v1/healthGET /v1/models: canonical model contractsGET /v1/receipts: receipts of the calling key
Chat Completions and Messages support text, system prompts, streaming, function tools, and model-approved images. Validated structured output is available only where the registry marks the selected protocol. A field that cannot survive translation returns 400 with its exact path.
Request contract
Standard fields pass through when the selected model can honor them. Cross-format requests support the shared text, sampling, stop, stream, and function-tool controls. Inexact controls are rejected, never discarded.
- The
providerobject chooses a provider (below). Other routing blocks are unsupported. - Unproven translated reasoning and structured-output controls return 400.
- Cross-format requests without a token limit use a 4,096-token maximum.
- Unknown consequential fields return 400 with
error.param. - Malformed JSON and request shapes return 400 before routing.
Choosing a provider
By default TokenSpend picks the cheapest working provider for you, and tries one more if the first returns an error or stalls. To choose instead, add a provider object. Each model page lists the providers that can run it, with the slug to use.
curl https://api.tokenspend.dev/v1/chat/completions \
-H "Authorization: Bearer $TOKENSPEND_API_KEY" \
-H "content-type: application/json" \
-d '{
"model": "moonshot/kimi-k3",
"messages": [{"role": "user", "content": "Hello"}],
"provider": {"only": ["novita"], "allow_fallbacks": false}
}'onlyruns the request on these providers and no others.ordertries these first, in this order. The rest stay as fallbacks.allow_fallbacks: falsemakes one attempt: no second provider and no model fallback. A failure comes back as a TokenSpend error. Withorder, the providers you did not list are dropped.
Where adding a body field is awkward, send the header x-tokenspend-provider: novita,baseten, which means only. Choosing any provider also turns off a configured model fallback for that request. Both TokenSpend SDKs take a provider option, where a string or a list means only.
An unknown slug, an unsupported key or a wrong type returns 400 with code: "invalid_provider" and the parameter. A provider that cannot run the model for your workspace returns 404 provider_not_available, naming the ones you can use. A provider takes tool calls or JSON schema only once it has passed our tests for them, so pinning one that has not returns 400 for those requests; model pages show which providers have passed.
The price is the model's list price unless its model page shows a provider's own price. Receipts do not show which provider served a request.