Chat completions
POST /v1/chat/completionsAuthorization: Bearer oxy_sk_...Content-Type: application/jsonCreates a chat completion. The request and response shapes are
OpenAI-compatible. The model field must be a public OxyRouter model ID from
GET /v1/models.
Authentication and scope
Section titled “Authentication and scope”Requires an API key with the inference:write scope. See
Authentication.
Request body
Section titled “Request body”| Field | Type | Required | Notes |
|---|---|---|---|
model |
string | Yes | Public model ID, 1–128 characters |
messages |
array | Yes | 1–500 chat messages |
temperature |
number | No | 0–2 |
top_p |
number | No | 0–1 |
max_tokens |
integer | No | 1–1,000,000; mutually exclusive with max_completion_tokens |
max_completion_tokens |
integer | No | 1–1,000,000; mutually exclusive with max_tokens |
stream |
boolean | No | Defaults to false |
stream_options |
object | No | {"include_usage": true} adds a usage chunk |
stop |
string or string[] | No | Up to the provider’s supported stop sequences |
n |
integer | No | 1–10 completions |
user |
string | No | Opaque end-user identifier, up to 256 characters |
tools |
array | No | Up to 128 function tools |
tool_choice |
string or object | No | none, auto, required, or a named function |
parallel_tool_calls |
boolean | No | Allow multiple tool calls in one turn |
response_format |
object | No | Provider-supported structured output |
presence_penalty |
number | No | -2–2 |
frequency_penalty |
number | No | -2–2 |
seed |
integer | No | Best-effort determinism where supported |
logprobs |
boolean | No | Provider-dependent |
top_logprobs |
integer | No | 0–20 |
Additional unknown fields are accepted and forwarded to the provider. Support varies by model and provider, so prefer the documented fields for portable code.
Messages
Section titled “Messages”Each message has a role and may include name, tool_calls, and
tool_call_id:
| Role | Content |
|---|---|
system, developer |
Instructions for the model |
user |
User input; a string or an array of content parts |
assistant |
Model output; may be null when tool_calls is present |
tool |
Tool result; requires tool_call_id and non-null content |
function |
Legacy function result |
Minimal request
Section titled “Minimal request”curl https://api.oxyrouter.in/v1/chat/completions \ -H "Authorization: Bearer $OXYROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [ {"role": "system", "content": "You are concise."}, {"role": "user", "content": "Explain prepaid billing in one sentence."} ], "temperature": 0.2, "max_tokens": 120 }'Response
Section titled “Response”{ "id": "chatcmpl-abc123", "object": "chat.completion", "created": 1735689600, "model": "gpt-4o-mini", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "You top up a wallet, and each request deducts the metered cost." }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 31, "completion_tokens": 17, "total_tokens": 48 }}model echoes the public OxyRouter model ID you requested, even if the request
is served by another eligible upstream route. Upstream provider names are never
returned.
Response headers
Section titled “Response headers”| Header | Meaning |
|---|---|
X-Request-ID |
Stable identifier for the logical request |
X-RateLimit-Limit |
Requests allowed in the current window |
X-RateLimit-Remaining |
Requests left in the window |
X-RateLimit-Reset |
Seconds until the window resets |
X-Oxy-Idempotent-Replayed |
true when a stored response was replayed |
Streaming
Section titled “Streaming”Set "stream": true to receive text/event-stream chunks. Each event contains
an OpenAI-compatible chat.completion.chunk object, and the stream ends with a
literal [DONE] event.
curl -N https://api.oxyrouter.in/v1/chat/completions \ -H "Authorization: Bearer $OXYROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "Count to three."}], "stream": true, "stream_options": {"include_usage": true} }'data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1735689600,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1735689600,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{"content":"One"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1735689600,"model":"gpt-4o-mini","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1735689600,"model":"gpt-4o-mini","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":4,"total_tokens":16}}
data: [DONE]When stream_options.include_usage is true, the final data chunk carries
usage and an empty choices array.
Tool calling
Section titled “Tool calling”Define tools with JSON Schema parameters. The model may return tool_calls;
send the tool result back as a tool message with the matching tool_call_id.
{ "model": "gpt-4o-mini", "messages": [{"role": "user", "content": "What is the weather in Pune?"}], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get current weather for a city", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } } ], "tool_choice": "auto"}Tool support and parallel tool calls depend on the selected model. If a model
cannot satisfy the request, OxyRouter returns a clear 4xx error rather than
silently dropping the tools.
Vision
Section titled “Vision”Send image content parts alongside text. Remote URLs are fetched by the gateway, subject to size and content-type validation.
{ "model": "gpt-4o-mini", "messages": [ { "role": "user", "content": [ {"type": "text", "text": "Describe this image."}, { "type": "image_url", "image_url": {"url": "https://example.com/image.png"} } ] } ]}The model must advertise vision support in
GET /v1/catalog/models.
Idempotency
Section titled “Idempotency”Send an Idempotency-Key header to make retries safe:
Idempotency-Key: 6f1c2a9e-3b0d-4f7a-9d2c-0f3b6f1c2a9e- The same key and body replay the stored non-streaming response with
X-Oxy-Idempotent-Replayed: true. - A different body with the same key returns
409 idempotency_key_reused. - Streaming responses are not stored; a replay attempt can return
409 duplicate_request.
Billing
Section titled “Billing”Usage is taken from the provider-reported token counts after the request completes. The retail cost is deducted from the prepaid INR wallet. A request fails before inference if the wallet cannot cover the reservation:
402 insufficient_quota402 insufficient_wallet_balance402 daily_spending_limit_exceeded402 monthly_spending_limit_exceeded
Errors
Section titled “Errors”See Errors and limits for the full list. The most common chat errors are:
| Status | Code | Cause |
|---|---|---|
400 |
invalid_request |
Invalid parameter or malformed message |
400 |
max_tokens_exceeded |
Over the configured output-token cap |
401 |
invalid_api_key |
Missing, unknown, or expired key |
403 |
api_key_scope_denied |
Key lacks inference:write |
403 |
model_not_allowed |
Model blocked by an allowlist |
404 |
model_not_found |
Unknown or unavailable model |
429 |
rate_limit_exceeded |
Rate limit exhausted |
429 |
concurrent_request_limit_exceeded |
No concurrency slot available |
502 |
upstream_error |
Provider error |
503 |
pricing_unavailable |
No complete published pricing |
Requests are rejected with 404 model_not_found when the model is unknown,
disabled, or backed only by unavailable providers.