- API reference
API reference
One gateway for OpenAI-compatible, Anthropic-compatible, and Responses API traffic. Point your SDK at routr.cloud and keep the code you already wrote.
Connecting for the first time? Start with the application quickstart for account, balance, model selection, and first-request verification.
Quickstart
Three values get you live: an API key, the base URL, and a model id. From there it's the OpenAI surface you already know.
1. Your key
Keys are created in your workspace, use the sk-user-… prefix, and travel in requests as a bearer token.
2. List models
curl https://api.routr.cloud/v1/models \
-H "Authorization: Bearer $ROUTR_KEY"3. First completion
curl https://api.routr.cloud/v1/chat/completions \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"messages": [
{ "role": "user", "content": "Explain PKCE in two sentences." }
]
}'Authentication
Pass your key as a bearer token in the Authorization header (OpenAI style) or in the x-api-key header (Anthropic style). Both headers are accepted on every endpoint.
Authorization: Bearer $ROUTR_KEYTreat a key like a password: it proves who you are and controls your spending. Rotate it from the workspace the moment it leaks.
Endpoints
All routes hang off https://api.routr.cloud/v1. Bodies and responses are JSON; streaming endpoints switch to SSE.
| Method | Path | Description |
|---|---|---|
| POST | /v1/chat/completions | OpenAI Chat Completions: chat, tools, stream. |
| POST | /v1/responses | OpenAI Responses API: stateless text and tools. |
| POST | /v1/messages | Anthropic Messages API for the Claude SDK and Claude Code. |
| GET | /v1/models | List available customer-facing models. |
| GET | /v1/models/{id} | Retrieve one model by id. |
| GET | /manifest | Public catalog, context, pricing, and billing formula. |
| GET | /health | Liveness probe. |
| GET | /health/ready | Readiness probe (DB and rate card). |
SDK examples
The OpenAI Python and Node SDKs connect with no code changes. Swap in the base URL and key, and your existing calls keep working.
curl https://api.routr.cloud/v1/chat/completions \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"messages": [{ "role": "user", "content": "Hello" }]
}'Streaming
Add "stream": true to receive the reply as SSE (text/event-stream): a series of data: events closed by data: [DONE].
curl https://api.routr.cloud/v1/chat/completions \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"stream": true,
"messages": [
{ "role": "user", "content": "Count 1 to 5." }
]
}'The last SSE event carries usage with prompt_tokens, completion_tokens, and prompt_tokens_details.cached_tokens whenever the prompt hit the cache.
Tool calling vs browser access
Tool calling forwards your schema and relays the model's request to call a function. The gateway never runs that function: no code execution, no browser, no device access, no outbound internet on your behalf.
To give a model browser access, supply the tool yourself (a web_search or open_url function), run it in your own trusted backend or tool runner, and return the outcome as a tool message. Only execute model-supplied URLs or commands inside a sandbox behind an allowlist.
curl https://api.routr.cloud/v1/chat/completions \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"messages": [
{ "role": "user", "content": "What is the weather in Jakarta?" }
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": { "type": "string", "description": "City name" }
},
"required": ["city"]
}
}
}],
"tool_choice": "auto"
}'A model can only request tools you declared; it can't invent new ones. Chat Completions surfaces these as tool_calls, while Responses clients see a function_call item.
Responses API
/v1/responses implements the OpenAI Responses API. Prompts go in input instead of messages, and replies return an output list of text and function calls.
curl https://api.routr.cloud/v1/responses \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"input": "Explain async/await in three sentences."
}'Streaming (Responses)
With "stream": true the stream walks through response.created → output_text.delta → response.completed → [DONE].
curl https://api.routr.cloud/v1/responses \
-H "Authorization: Bearer $ROUTR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"stream": true,
"input": "Write a haiku about servers."
}'Anthropic Messages
/v1/messages speaks the Anthropic Messages protocol, so Claude Code and the Anthropic SDK connect unchanged. Authenticate with x-api-key and include anthropic-version.
curl https://api.routr.cloud/v1/messages \
-H "x-api-key: $ROUTR_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-pro",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "Hello" }
]
}'Claude Code / Anthropic SDK
# Claude Code / Anthropic SDK — same base URL & key
export ANTHROPIC_BASE_URL="https://api.routr.cloud"
export ANTHROPIC_AUTH_TOKEN="$ROUTR_KEY"
# or via the SDK
# Anthropic({ baseURL: "https://api.routr.cloud", apiKey })Parameters
Requests pass through to the upstream unchanged, so the full OpenAI parameter set works. The fields below are the ones you'll reach for most often.
| Field | Type | Scope | Description |
|---|---|---|---|
| model | string | required | Model id from /v1/models (e.g. deepseek-v4-pro). |
| messages | array | chat | Conversation turns: {role, content}. |
| input | string | responses | Prompt text (Responses API). |
| stream | boolean | optional | Stream tokens via SSE. Default false. |
| max_tokens | integer | optional | Max output tokens. Default 4096. |
| temperature | number | optional | 0–2. Higher = more random. Default 1. |
| top_p | number | optional | Nucleus sampling. Default 1. |
| tools | array | optional | Function-calling tool definitions. |
| tool_choice | string | optional | 'auto', 'none', or a specific tool. |
| stop | string | optional | Stop sequence (up to 4). |
| system | string | messages | System prompt (Anthropic format). |
| response_format | object | optional | JSON mode: {type: 'json_object'}. |
Errors
Failures come back as { "error": { "type", "code", "message" } }. The most common codes are listed below.
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed body or missing required field. |
| 401 | invalid_api_key | Missing, malformed, or revoked key. |
| 402 | insufficient_balance | Balance too low for the request. Top up to continue. |
| 403 | policy_forbidden | Key scope does not include this model. |
| 404 | model_not_found | Model not in the catalog, or retired. |
| 429 | rate_limit_exceeded | RPM or concurrency limit reached. Retry with backoff. |
| 500 | internal_error | Gateway-side failure. Retry shortly. |
| 502 | upstream_error | Upstream returned an error after retry. |
| 503 | service_unavailable | No healthy upstream for this model right now. |
Rate limits
Every key in an account draws from the same shared budget, so adding keys doesn't raise the ceiling.
| Limit | Default | Response |
|---|---|---|
| Requests per minute | per plan | 429 rate_limit_exceeded |
| Concurrency | per plan | 429 rate_limit_exceeded |
| Context window | per model | 400 invalid_request |
Credit billing
Each completed request settles in credits. The charge is:
credits = max(
ceil(
uncached_input_tokens × multiplier
+ cached_input_tokens × multiplier × cache_weight
+ output_tokens × multiplier × output_weight × surge_multiplier
),
floor_credits
)Cached input costs cache_weight of the input rate, and output costs output_weight. A temporary surge multiplier can apply under peak load; the Models page shows current per-model rates. A floor_credits minimum applies per request, and nothing is billed when the upstream fails before returning a usable response.
Management API
Programmatic access to your account, keys, usage, and wallet. Everything is authenticated with your API key (the same Authorization: Bearer sk-ngw_… header), and responses only ever contain data from your own organization.
| Method | Path | Description |
|---|---|---|
| GET | /api/me | Account info: org_id, key details, wallet and rate limits in one call. |
| GET | /api/me/keys | List your active API keys (prefix, scopes, status). |
| POST | /api/me/keys/rotate | Rotate key. The old key is revoked and the new raw key is returned once. |
| DELETE | /api/me/keys/{id} | Revoke a specific key by id. |
| GET | /api/me/usage | Usage log: recent requests with tokens, charges and outcome. |
| GET | /api/me/usage/logs | Alias for /api/me/usage. |
| GET | /api/me/wallet | Wallet balance: balance, reserved and available credits. |
| GET | /api/me/pricing | Model pricing: input, cache and output rates, and floors. |
| GET | /api/me/cache-savings | Cache savings: how much prompt caching saved. |
A single request returns the essentials a dashboard needs: org id, the calling key's prefix, scopes, and tier, the wallet balances, and the active rate limits.
curl https://api.routr.cloud/api/me \
-H "Authorization: Bearer sk-ngw_…"
# 200 OK
{
"org_id": "org-abc123",
"key": {
"id": 42,
"prefix": "I_raqEg4",
"scopes": ["model:*"],
"status": "active",
"tier": "free",
"created_at": 1788624646,
"expires_at": null
},
"wallet": {
"wallet_id": 181,
"balance_credits": 5000,
"reserved_credits": 0,
"available_credits": 5000
},
"limits": {
"rpm": null,
"tpm": null,
"concurrency": null
}
}Lists the active keys on your account. The secret is never returned, only an 8-character prefix that is enough to tell your keys apart.
curl https://api.routr.cloud/api/me/keys \
-H "Authorization: Bearer sk-ngw_…"
# 200 OK
{
"keys": [
{
"id": "42",
"name": "production",
"prefix": "I_raqEg4",
"scopes": ["model:*"],
"status": "active",
"created_at": 1788624646,
"expires_at": null,
"last_used_at": 1788624700
}
],
"count": 1
}Recent requests with their token counts and charges. Narrow the list with ?model= and set the page size with ?limit=50 (up to 200).
curl "https://api.routr.cloud/api/me/usage/logs?limit=5" \
-H "Authorization: Bearer sk-ngw_…"
# 200 OK
{
"items": [
{
"request_id": "req_abc",
"attempt_no": 1,
"key_name": "production",
"key_name_status": "snapshot",
"model": "deepseek-v4-pro",
"upstream_status": 200,
"outcome": "success",
"input_tokens": 2323,
"output_tokens": 156,
"cache_read_tokens": 198000,
"charged_credits": 12.5,
"usage_source": "actual",
"streamed": true,
"created_at": 1788624700
}
],
"summary": {
"requests": 1,
"attempts": 1,
"charged_credits": 12.5
},
"next_cursor": null,
"from": "2026-09-06T00:00:00+00:00",
"to": "2026-10-06T00:00:00+00:00"
}curl https://api.routr.cloud/api/me/wallet \
-H "Authorization: Bearer sk-ngw_…"
# 200 OK
{
"wallet_id": 181,
"balance_credits": 5000,
"reserved_credits": 0,
"available_credits": 5000
}The active rate card lists each model's input, cache, and output rates plus per-request floors. Rates are credits per token. Cache costs cache_weight×input, output costs output_weight×input.
curl https://api.routr.cloud/api/me/pricing \
-H "Authorization: Bearer sk-ngw_…"
# 200 OK
{
"billing": "credit",
"rate_card_version": 294,
"models": [
{
"id": "deepseek-v4-pro",
"context_limit": 1000000,
"vision": true,
"input_rate": 2.5,
"cache_rate": 1.25,
"output_rate": 10,
"min_charge_credits": 1000,
"per_request_floor_credits": null,
"rate_card_version": 294
}
],
"note": "Rates are credits per token. Cache costs cache_weight×input, output costs output_weight×input."
}