Docs
Overview
The TOKENWERK API is compatible with the OpenAI and Anthropic APIs: you use the official SDKs and tools, only the base URL and the key change.
Quickstart
- Sign in to the TOKENWERK app and create a key under API keys. It starts with
tw-and is only shown once. - Store it as an environment variable; every example in these docs reads it from there.
- Fetch the model list and make your first request.
export TOKENWERK_API_KEY="tw-..."
curl https://api.tokenwerk.ai/v1/models -H "Authorization: Bearer $TOKENWERK_API_KEY"
curl https://api.tokenwerk.ai/v1/chat/completions \
-H "Authorization: Bearer $TOKENWERK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL",
"messages": [{"role": "user", "content": "Hello"}]
}'
You will find a model's name (the model field) under Models or via
GET /v1/models.
Base URLs
TOKENWERK speaks two formats at the same address. Your SDK or tool decides which one you use.
| Format | Base URL | Example |
|---|---|---|
| OpenAI (Chat Completions, Responses, Embeddings) | https://api.tokenwerk.ai/v1 |
https://api.tokenwerk.ai/v1/chat/completions |
| Anthropic (Messages) | https://api.tokenwerk.ai |
https://api.tokenwerk.ai/v1/messages – the SDK appends
/v1/messages itself |
Authentication
Every request needs an API key of your organization, in one of these two headers:
Authorization: Bearer tw-...
x-api-key: tw-...
- OpenAI SDKs send
Authorization: Bearer, Anthropic SDKsx-api-key; both work on every endpoint. - Keys belong to your organization, optionally to a team, and can have an expiry date and budget limits.
Revoked or expired keys are rejected with
401. - Only use keys on the server, never in a browser or in an app you ship.
Endpoints
| Method and path | Format | Billing |
|---|---|---|
POST /v1/chat/completions |
OpenAI | per token |
POST /v1/responses |
OpenAI | per token |
POST /v1/completions |
OpenAI | per token |
POST /v1/embeddings |
OpenAI | per token |
POST /v1/messages |
Anthropic | per token |
POST /v1/messages/count_tokens |
Anthropic | free |
GET /v1/models, GET /v1/models/{model} |
OpenAI | free |
All other paths under /v1 (images, audio, files, batches, …) answer 404. Which
endpoints a model actually supports depends on the model: embeddings, for example, only work with embedding
models.
Models
GET /v1/models lists the models currently available with their context window and maximum
output; prices and descriptions are under Models.
{
"object": "list",
"data": [
{
"id": "MODEL",
"object": "model",
"created": 0,
"owned_by": "tokenwerk",
"context_window": 131072,
"max_output_tokens": 32768
}
]
}
Auto models (kind “Auto”) will pick a suitable model per request. Routing is not available yet, so such
requests are rejected with 503 for now.
Streaming
With "stream": true the response arrives as server-sent events, in the format of the API you
call. In the OpenAI format, "stream_options": {"include_usage": true} adds a final chunk with
the token usage.
curl -N https://api.tokenwerk.ai/v1/chat/completions \
-H "Authorization: Bearer $TOKENWERK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL",
"stream": true,
"stream_options": {"include_usage": true},
"messages": [{"role": "user", "content": "Hello"}]
}'
curl -N https://api.tokenwerk.ai/v1/messages \
-H "x-api-key: $TOKENWERK_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "MODEL",
"max_tokens": 1024,
"stream": true,
"messages": [{"role": "user", "content": "Hello"}]
}'
If your client stops a stream, the request to the model is ended right away; you only pay for the tokens processed until then.
Tools & images
Requests are passed to the model unchanged, only the model name is translated. Tool and function calling
(tools, tool_choice), structured output (response_format) and image
input (image_url or image blocks) therefore work whenever the chosen model
supports them. Coding agents need a model with tool calling.
Errors
Errors come in the format of the API you call: in the OpenAI format as
{"error": {"message", "type", …}}, in the Anthropic format as
{"type": "error", "error": {"type", "message"}}.
| Status | OpenAI type | Anthropic type | Meaning |
|---|---|---|---|
400 |
invalid_request_error |
invalid_request_error |
Invalid request, e.g. without model or with max_tokens too high |
401 |
authentication_error |
authentication_error |
Key missing, invalid, revoked or expired |
402 |
insufficient_quota |
billing_error |
The organization's balance is used up |
403 |
permission_error |
permission_error |
Organization blocked |
404 |
not_found_error |
not_found_error |
The model or endpoint does not exist |
429 |
rate_limit_error |
rate_limit_error |
Budget limit of the key or team reached, or the model is busy (with Retry-After) |
502, 503 |
api_error |
api_error |
The model is not reachable right now, please try again later |
Limits & billing
- There are no request rate limits per key. Spending is limited by budgets: per key or team for a day,
week and month (UTC). Once a budget is reached, further requests answer
429. At a configurable percentage of a budget the organization's admins receive a warning email. - Billing is per request by tokens: input, cached input and output, each at the model's price per 1 million tokens. The prices at the start of the request apply.
- Rejected requests cost nothing. Once the balance is used up, requests answer
402. - Prompts and responses are not stored, only metadata such as tokens, duration and price.
API references
TOKENWERK is compatible with the OpenAI and Anthropic APIs. You will find every parameter in their references:
Next: SDKs with examples for many languages and agents such as Claude Code or opencode.