WorldRouter

Skip to Content
API reference

API reference

WorldRouter exposes an OpenAI-compatible /chat/completions endpoint. Any SDK or HTTP client that accepts a custom base URL can call it with no code changes. For image and video generation, see Media Generation.

Tip:

New to WorldRouter? Run through the Quickstart first for an API key, the base URL, and a connection test. This page assumes you already have both.

Chat completions

Endpoint

Endpoint
POST https://inference-api-pre-d80ca3.worldrouter.ai/v1/chat/completions

Authentication

Pass your API key as a Bearer token in the Authorization header:

Authorization: Bearer your_api_key

Keys are scoped to your account. Create and rotate them in the API Keys dashboard.

Request body

FieldRequiredDescription
modelyesModel ID to route to, e.g. gpt-5.4. See the Models catalog.
messagesyesArray of chat messages. Must contain at least one entry.
temperaturenoSampling temperature. Defaults depend on the model.
max_tokensnoUpper bound on output tokens. On reasoning models the budget can be fully consumed by hidden reasoning tokens, which returns an empty content with finish_reason: "length".
streamnoWhen true, the response is a Server-Sent Events stream of deltas.
tools / tool_choicenoFunction calling, same schema as OpenAI. Add a {"type":"worldrouter:web_search"} tool — or the :online model suffix — to ground answers in live web results. See Web search.

Any other field in the OpenAI /chat/completions schema (top_p, stop, seed, response_format, …) is accepted unchanged.

WorldRouter can ground any model’s answer in live web results. There is no account-level toggle: search runs only when a request asks for it, and a request that doesn’t ask never incurs a search fee.

The simplest way to enable it is the :online model suffix:

{ "model": "qwen3.5-flash:online", "messages": [ { "role": "user", "content": "What changed in the latest release?" } ] }

For control over how searching behaves, add the tool explicitly instead:

{ "model": "qwen3.5-flash", "messages": [ { "role": "user", "content": "What changed in the latest release?" } ], "tools": [ { "type": "worldrouter:web_search", "parameters": { "max_uses": 3, "max_results": 5, "allowed_domains": ["worldrouter.ai"], "excluded_domains": ["example.com"] } } ] }

The model decides when and how often to search: it may search, read the results, refine the query and search again, or answer without searching at all. Sources are cited as [1], [2], and so on.

ParameterDefaultDescription
engineautoWhich engine serves the search. auto uses the provider’s native search on models that have one (OpenAI models today) and WorldRouter’s search everywhere else. exa always uses WorldRouter’s search. native always uses the provider’s, and fails on models without one.
max_uses3Most searches one request may run. Values above the server ceiling are lowered, not rejected.
max_results5Results returned per search, up to 25.
max_total_resultsCumulative cap on results across all searches in the request.
allowed_domains / excluded_domainsRestrict results to, or keep them away from, up to 20 domains each.
search_context_sizeHow much excerpt each result carries: low, medium, or high.
max_charactersExact per-result excerpt length; takes precedence over search_context_size.
Tip:

Migrating from OpenRouter? Requests written for its web search work here with the tool type changed to worldrouter:web_search — the :online suffix, the parameter names, and the plugins: [{ "id": "web" }] form are all accepted.

Pricing

WorldRouter searches cost $0.007 each, covering the first 10 results; results beyond 10 add $0.001 apiece. Fees appear in your usage history alongside the model call that used them — a multi-hop answer shows one row per search round, each labelled with its round number. That is itemization, not duplicate billing. When engine resolves to a provider’s native search, the provider’s own search pricing applies instead.

If your balance cannot cover the request’s worst case (max_uses × the per-search fee), the request is rejected with 402 before anything runs.

Citations

When WorldRouter’s search ran, the response carries the sources it used — annotations on the message, in the same url_citation shape OpenAI uses, and a search counter under usage:

{
"choices": [
  {
    "message": {
      "content": "The latest release added ... [1]",
      "annotations": [
        {
          "type": "url_citation",
          "url_citation": {
            "url": "https://worldrouter.ai/changelog",
            "title": "Changelog",
            "content": "…excerpt from the page…",
            "start_index": 30,
            "end_index": 33
          }
        }
      ]
    }
  }
],
"usage": {
  "server_tool_use": { "web_search_requests": 1 }
}
}

Response

A non-streaming response matches the OpenAI shape:

{
"id": "chatcmpl-...",
"object": "chat.completion",
"created": 1738960610,
"model": "gpt-5.4",
"choices": [
  {
    "index": 0,
    "message": { "role": "assistant", "content": "Hello! How can I help you today?" },
    "finish_reason": "stop"
  }
],
"usage": {
  "prompt_tokens": 13,
  "completion_tokens": 9,
  "total_tokens": 22
}
}

Examples

curl
curl https://inference-api-pre-d80ca3.worldrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "messages": [{ "role": "user", "content": "Hello" }]
  }'
python
from openai import OpenAI

client = OpenAI(
    api_key="your_api_key",
    base_url="https://inference-api-pre-d80ca3.worldrouter.ai/v1",
)

response = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "Hello"}],
)

print(response.choices[0].message.content)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "your_api_key",
  baseURL: "https://inference-api-pre-d80ca3.worldrouter.ai/v1",
});

const response = await client.chat.completions.create({
  model: "gpt-5.4",
  messages: [{ role: "user", content: "Hello" }],
});

console.log(response.choices[0].message.content);

Streaming

Set stream: true in the request body. The response becomes a Server-Sent Events stream. Each chunk follows the OpenAI chat.completion.chunk shape, and the stream terminates with a data: [DONE] line:

curl
curl https://inference-api-pre-d80ca3.worldrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-5.4",
    "stream": true,
    "messages": [{ "role": "user", "content": "Hello" }]
  }'
python
from openai import OpenAI

client = OpenAI(
    api_key="your_api_key",
    base_url="https://inference-api-pre-d80ca3.worldrouter.ai/v1",
)

stream = client.chat.completions.create(
    model="gpt-5.4",
    messages=[{"role": "user", "content": "Hello"}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
javascript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "your_api_key",
  baseURL: "https://inference-api-pre-d80ca3.worldrouter.ai/v1",
});

const stream = await client.chat.completions.create({
  model: "gpt-5.4",
  messages: [{ role: "user", content: "Hello" }],
  stream: true,
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) process.stdout.write(delta);
}

Error codes

CodeMeaningFix
400Invalid request (unknown model, malformed body, unsupported parameter)Verify the model ID matches the Models page (IDs are case-sensitive) and check the request body against the field table above.
401Invalid or missing API keyCheck that your key is set correctly and has not been revoked in the dashboard.
402Insufficient creditsTop up on the Credits page, then retry.
429Rate limitedBack off and retry with exponential delay. Consider spreading load across models.
500Server errorRetry the request. If it persists, try a different model or contact support.

See also