Sign inSign up
DocsAPI reference

API reference

The Tokener CA API reference — every endpoint, the accepted authentication headers, required request fields, streaming formats, usage fields and error codes for all three protocols.

Updated:

What the API is

Tokener CA is one API you reach with one key over three protocols: OpenAI-compatible (Chat Completions), OpenAI Responses and Anthropic-compatible (Messages). OpenAI clients point at https://a.tokener.ca/v1; the Anthropic SDKs point at https://a.tokener.ca (no /v1 — the SDK appends it). To get a key, follow the Quickstart; the tool-by-tool guides are linked from each row below.

This page states what every endpoint accepts and returns. For step-by-step setup, use the Developer Onboarding, OpenAI Responses API and Anthropic SDK guides.

Endpoints

Method and pathProtocolWhat it doesGuide
POST https://a.tokener.ca/v1/chat/completionsOpenAI-compatible (Chat Completions)Create a chat completionDeveloper Onboarding
POST https://a.tokener.ca/v1/responsesOpenAI ResponsesCreate a response, sending the whole conversation each timeOpenAI Responses API
POST https://a.tokener.ca/v1/messagesAnthropic-compatible (Messages)Create a messageAnthropic SDK
POST https://a.tokener.ca/v1/messages/count_tokensAnthropic-compatible (Messages)Count a request's input tokens (free; see availability below)Anthropic SDK
GET https://a.tokener.ca/v1/models—List the models you can callDeveloper Onboarding

POST https://a.tokener.ca/v1/messages/count_tokens returns { "input_tokens": <n> } for a Messages request. It is free — not charged and not recorded — but needs a valid key on an account with a positive balance; model must be a current model and messages non-empty. Token counting is available only on accounts that have turned on Also allow suppliers without that commitment under Account settings → Data handling; on other accounts this endpoint answers 404 not_found_error with the message "Token counting is not available on this API."

Authentication

Every request needs your Tokener API key, which begins with tok-.

  • OpenAI-compatible (Chat Completions), OpenAI Responses and GET /models: send Authorization: Bearer <your key>.
  • Anthropic-compatible (Messages): send x-api-key: <your key> (the Anthropic SDK default) or Authorization: Bearer <your key>. If both are present, x-api-key is used.

A missing or invalid key is answered with 401. A revoked key is treated exactly like an invalid one — revoking takes effect immediately, so create a new key on the API keys page. A request from a deactivated account is answered with 403, before any billing.

Requests

Tokener validates only a few fields and passes everything else through to the model unchanged.

OpenAI-compatible (Chat Completions)

Requires model (a non-empty string) and a non-empty messages array.

Bash
curl https://a.tokener.ca/v1/chat/completions \  -H "Authorization: Bearer $TOKENER_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "model": "glm-5.3:flash",    "messages": [{ "role": "user", "content": "Hello" }]  }'

OpenAI Responses

Requires model and a non-empty input (a string or an array). This endpoint is stateless: previous_response_id, conversation, store: true and background: true are rejected — send the whole conversation in input.

Bash
curl https://a.tokener.ca/v1/responses \  -H "Authorization: Bearer $TOKENER_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "model": "glm-5.3:flash",    "input": "Hello"  }'

Anthropic-compatible (Messages)

Requires model, a non-empty messages array, and max_tokens (a positive integer).

Bash
curl https://a.tokener.ca/v1/messages \  -H "x-api-key: $TOKENER_API_KEY" \  -H "anthropic-version: 2023-06-01" \  -H "Content-Type: application/json" \  -d '{    "model": "glm-5.3:flash",    "max_tokens": 128,    "messages": [{ "role": "user", "content": "Hello" }]  }'

How do I send an image?

Image parts must be inline base64 data URLs — data:image/<type>;base64,<data> — on every protocol. Tokener does not fetch remote images: a part that points at an http:// or https:// URL is rejected with 400 invalid_request_error ("Image parts must be inline data URLs (base64); remote image URLs are not fetched.") before the request reaches a model, and nothing is charged. Download the image yourself and encode it — see Developer Onboarding.

  • OpenAI-compatible (Chat Completions): { "type": "image_url", "image_url": { "url": "data:image/png;base64,…" } }
  • OpenAI Responses: { "type": "input_image", "image_url": "data:image/png;base64,…" }
  • Anthropic-compatible (Messages): { "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "…" } } — a source of type url is rejected.

Which models accept images is shown per model on /models under its input modalities.

Streaming

Each protocol streams over server-sent events; turn it on with "stream": true.

  • OpenAI-compatible (Chat Completions): each data: line is a chunk whose choices[0].delta carries the next piece of text; the stream ends with data: [DONE].
  • OpenAI Responses: typed events, where response.output_text.delta carries text; the stream ends with a response.completed event. See the OpenAI Responses API guide.
  • Anthropic-compatible (Messages): Anthropic SSE with paired event:/data: lines — message_start, then content_block_delta events with the text, then message_delta and message_stop. See the Anthropic SDK guide.

Once a streamed response has started (HTTP 200), a later failure arrives as an event inside the stream and the connection closes, rather than as a new status code.

Usage and billing fields

Every non-streamed response carries a usage object; on a stream the final counts arrive in the last event (the final chunk, the response.completed event, or the closing message_delta). See How the numbers are counted and billed below, and Pricing for the live price list.

ProtocolToken-count fields on usage
OpenAI-compatible (Chat Completions)prompt_tokens, completion_tokens, total_tokens, prompt_tokens_details.cached_tokens
OpenAI Responsesinput_tokens, output_tokens, total_tokens, input_tokens_details.cached_tokens
Anthropic-compatible (Messages)input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens

How the numbers are counted and billed

  • OpenAI-compatible (Chat Completions) and OpenAI Responses: the input count (prompt_tokens / input_tokens) is the total input of the request. The cached count (prompt_tokens_details.cached_tokens / input_tokens_details.cached_tokens) is a part of that total — it is already included in it, so never add it on top.

  • Anthropic-compatible (Messages): the native fields can report cached input either inside input_tokens or next to it (cache_read_input_tokens, cache_creation_input_tokens), depending on how the request was served, and the response does not say which. Tokener therefore bills this protocol from the request's input total, which it determines on the server; when that total cannot be confirmed it bills the lower reading. Do not reconstruct a bill from these three fields — the Usage page is authoritative.

  • What you are charged. The charge for a request is:

    charge = (input total − cached input) × input rate + cached input × cache-read rate + output × output rate

    A model that has no cache-read rate bills cached input at its input rate. Rates are per 1,000,000 tokens and are listed on /models. Cache creation is billed as ordinary input — there is no separate write surcharge.

  • Cache hits are never guaranteed. Reusing a conversation does not imply a cache hit; whether any input was cached is decided per request and is reflected in the usage of that response.

  • Streaming. The final usage arrives at the end of the stream, per protocol, as described under Streaming above. A stream you stop early may end without a final usage.

  • Counting before you send. On the Anthropic-compatible (Messages) protocol, POST https://a.tokener.ca/v1/messages/count_tokens returns a request's input total before you send it, and is free — on accounts that allow all model suppliers in their Data handling settings; see Anthropic SDK.

  • Where to check. Every request is listed on the Usage page with the columns In, Out, Total, Cost (US$), Status, Protocol, Error and Key. When part of the input was cached, the cached count is shown in parentheses beside the In value (for example "1,200 (800 cached)"); there is no separate cached column.

What is a limited-time price?

Some models may be on a limited-time price: a lower price for a set period. While it runs, the model's card on /models, its own page, the home page and Pricing show the regular price struck through with the limited-time price under it, how much is off (for example "26% off", or "Limited-time price"), and when it ends, in Toronto time (ET). The Playground shows the same next to the model's rates.

  • A request is billed at the price in effect when it starts, even if it finishes after the end.
  • When the end passes, the regular price applies again by itself.
  • If your account allows all model suppliers in its Data handling settings, that discount applies on top of the limited-time price.

Errors

Errors on the OpenAI-shaped endpoints (OpenAI-compatible (Chat Completions), OpenAI Responses, GET /models) use the body { "error": { "message", "type", "code", "param" } }.

StatustypecodeWhenWhat to do
400invalid_request_errorinvalid_request_errorA required field is missing or malformedFix the request body
400invalid_request_errormodel_not_foundThe model is unknown or not availablePick a model from /models
401invalid_request_errorinvalid_api_keyThe key is missing, invalid or revokedCheck the Authorization header or create a new key
402insufficient_quotainsufficient_quotaYour balance is used upAdd funds — see Pricing
402insufficient_quotaplan_limit_reachedYour Agent plan reached its 5-hour or weekly limit and "continue on my balance" is offWait for Retry-After seconds, turn the setting on, or add funds
402insufficient_quotaoverflow_cap_reachedYour Agent plan is at a limit and your own limit on balance use beyond the plan for this billing period is reachedWait for Retry-After seconds, or raise the limit on the Plan page
403invalid_request_erroraccount_deactivatedThe account is deactivatedContact support
413invalid_request_errorrequest_too_largeThe request body is too large for this modelSend less context or smaller attachments
429rate_limit_errorrate_limit_exceededThe request was rate-limitedSlow down and try again
502api_errorupstream_errorA temporary upstream failureTry again
503api_errormodel_limited_by_data_handlingThe model is temporarily available only from suppliers your Data handling setting does not allow, and the request failed (details)Turn on the setting or pick another model
500api_errorinternal_errorAn unexpected server errorTry again, then contact support

Errors on the Anthropic-compatible (Messages) endpoint use the Anthropic body { "type": "error", "error": { "type", "message" } }.

StatustypeWhenWhat to do
400invalid_request_errorThe request body is invalidFix the request body
401authentication_errorThe key is missing, invalid or revokedCheck x-api-key or create a new key
402billing_errorYour balance is used up, or your Agent plan reached a limit, or your limit on balance use beyond the plan is reached (then Retry-After is set; the message tells them apart)Add funds — see Pricing, wait for Retry-After seconds, or raise the limit on the Plan page
403permission_errorThe account is deactivatedContact support
404not_found_errorThe model is unknown or not available (or, on count_tokens, token counting is not available for the account)Pick a model from /models
413request_too_largeThe request body is too large for this modelSend less context or smaller attachments
429rate_limit_errorThe request was rate-limitedSlow down and try again
502api_errorA temporary upstream failureTry again
503api_errorThe model is temporarily available only from suppliers your Data handling setting does not allow, and the request failed (the message says so)Turn on the setting or pick another model
500api_errorAn unexpected server errorTry again, then contact support

If the model itself rejects a request — for example a parameter it does not accept — Tokener returns a 400 in the shape above asking you to check your parameters.

What if a model is marked Temporarily unavailable?

The Models pages mark a model Temporarily unavailable when our automatic checks cannot reach it. The API still accepts requests for it, and a request that fails is not billed. Pick another model, or retry later — the mark goes away by itself as soon as a check succeeds.

Why did my request fail with model_limited_by_data_handling?

By default your requests go only to model suppliers that commit to not storing request content and not using it for training. Sometimes a model is temporarily available only from suppliers without that commitment. If a request for that model then fails, the answer is a 503 with the code model_limited_by_data_handling (on the Anthropic-compatible (Messages) endpoint: a 503 api_error with the same message) instead of the usual failure, so you know why. The request was not billed. To use the model now, turn on "Also allow suppliers without that commitment" in Settings → Data handling, or choose another model. Accounts that already allow those suppliers never get this error.