Build with the AuraRoute API

One OpenAI-compatible endpoint. Pick a workload, we pick the model.

Try it

Send a real request from your browser before writing any code. Pick a workload, paste a key and chat — answers stream live and the model's thinking appears as it is produced. Your conversations are saved in this browser only.

Quick start

AuraRoute speaks the OpenAI API. Point any OpenAI SDK at the base URL below, use your AuraRoute key, and set model to a workload — you never name a model; we pick the right one.

Base URLhttps://auraroute.dev/api
EndpointPOST /chat/completions
AuthAuthorization: Bearer <your key>

1. Create a key

Create a free account, then create a key under API keys. It is shown once.

2. Keep it in an environment variable

macOS / Linux
export AURAROUTE_API_KEY=az_live_…
Windows (PowerShell)
$env:AURAROUTE_API_KEY = "az_live_…"

3. Send a request

curl
curl https://auraroute.dev/api/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AURAROUTE_API_KEY" \
  -d '{
    "model": "auto",
    "messages": [{ "role": "user", "content": "Say hello in one sentence." }]
  }'
JavaScript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://auraroute.dev/api',
  apiKey: process.env.AURAROUTE_API_KEY,
});

const res = await client.chat.completions.create({
  model: 'auto',
  messages: [{ role: 'user', content: 'Say hello in one sentence.' }],
});

console.log(res.choices[0].message.content);
Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://auraroute.dev/api",
    api_key=os.environ["AURAROUTE_API_KEY"],
)

res = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "Say hello in one sentence."}],
)

print(res.choices[0].message.content)

Agents

Hermes and OpenClaw use the same three values as any other client: base URL https://auraroute.dev/api, your key, and model set to agent. Each guide is the commands in order, then one bash script that installs the agent and writes the config.

Hermes setup · OpenClaw setup · How a request gets there

Authentication

Send your key as a bearer token. Keys look like az_live_<id>_<secret>. You can hold several, and revoke any of them from the dashboard — a revoked key stops working within seconds.

Only a hash of each key is stored, so it cannot be shown again after creation. If you lose it, revoke it and make a new one.

Choosing a workload

The model field takes a workload, not a model name. AuraRoute routes each request to the best available model for it, and falls back automatically if a provider is down — you never need to pick or change a model. Anything else (for example gpt-4o) is rejected with a list of valid values.

modelUse it for
autoNot sure? We look at the request and pick: tools → agent, code → coding, very long or research-style → research, otherwise chat.
chatEveryday conversation, questions, writing and summarising.
codingWriting, explaining, reviewing and debugging code.
researchLong inputs and in-depth analysis, where reasoning over a lot of text matters.
agentTool calling and multi-step tasks. Any request with `tools` is routed here.

List them any time with GET /models.

curl
curl https://auraroute.dev/api/models \
  -H "Authorization: Bearer $AURAROUTE_API_KEY"
JavaScript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://auraroute.dev/api',
  apiKey: process.env.AURAROUTE_API_KEY,
});

const models = await client.models.list();
console.log(models.data.map((m) => m.id));
Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://auraroute.dev/api",
    api_key=os.environ["AURAROUTE_API_KEY"],
)

print([m.id for m in client.models.list().data])

Chat completions

POST /chat/completions follows the OpenAI request and response shape. Parameters such as temperature, top_p and stop are passed through.

FieldNotes
modelOne of auto, chat, coding, research, agent. Defaults to auto.
messagesRequired. Array of { role, content }. Images as image_url parts are supported by vision-capable models.
streamtrue streams the answer as server-sent events. See Streaming.
stream_options.include_usagetrue adds a final chunk with token counts.
max_tokens / max_completion_tokensCapped at the platform limit; if omitted, the cap is used.
toolsFunction tools. Their presence routes the request to agent models. See Tools.
nMust be 1.

Fields that would steer the upstream — models, provider, route, plugins, preset, transforms — are removed. In responses, id is ours and model echoes the workload you sent.

Streaming & thinking

Set stream: true to receive the answer as it is generated. Models that think before answering send that thinking first, in delta.reasoning_content or delta.reasoning (we pass along whichever the model uses), followed by the answer in delta.content. Some models instead wrap thinking in <think>…</think> inside the content. Show or hide it as you like; do not send it back in your next request.

curl
curl -N https://auraroute.dev/api/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AURAROUTE_API_KEY" \
  -d '{
    "model": "chat",
    "stream": true,
    "stream_options": { "include_usage": true },
    "messages": [{ "role": "user", "content": "Explain recursion briefly." }]
  }'
JavaScript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://auraroute.dev/api',
  apiKey: process.env.AURAROUTE_API_KEY,
});

const stream = await client.chat.completions.create({
  model: 'chat',
  stream: true,
  stream_options: { include_usage: true },
  messages: [{ role: 'user', content: 'Explain recursion briefly.' }],
});

for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta;
  // Thinking arrives first, in a field the OpenAI types do not declare.
  const thinking = delta?.reasoning_content ?? delta?.reasoning;
  if (thinking) process.stderr.write(thinking);
  if (delta?.content) process.stdout.write(delta.content);
}
Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://auraroute.dev/api",
    api_key=os.environ["AURAROUTE_API_KEY"],
)

stream = client.chat.completions.create(
    model="chat",
    stream=True,
    stream_options={"include_usage": True},
    messages=[{"role": "user", "content": "Explain recursion briefly."}],
)

for chunk in stream:
    if not chunk.choices:
        continue  # the final usage chunk has no choices
    delta = chunk.choices[0].delta
    # Thinking arrives first, in a field the OpenAI types do not declare.
    thinking = getattr(delta, "reasoning_content", None) or getattr(delta, "reasoning", None)
    if thinking:
        print(thinking, end="", flush=True)
    if delta.content:
        print(delta.content, end="", flush=True)

If a provider fails before the first token, the request moves to another provider and you only see a slightly later first token. After the first token the stream cannot switch; a failure then ends the stream with an error event, shaped like the errors below.

Tools & images

Pass tools as you would to OpenAI. Requests with tools are served by models that support them, and the model replies with tool_calls for you to run and answer. Requests containing images go only to vision-capable models. If nothing capable is available you get a 503 rather than a silently degraded answer.

curl
curl https://auraroute.dev/api/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AURAROUTE_API_KEY" \
  -d '{
    "model": "agent",
    "messages": [{ "role": "user", "content": "What is the weather in Dhaka?" }],
    "tools": [{
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Current weather for a city",
        "parameters": {
          "type": "object",
          "properties": { "city": { "type": "string" } },
          "required": ["city"]
        }
      }
    }]
  }'
JavaScript
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://auraroute.dev/api',
  apiKey: process.env.AURAROUTE_API_KEY,
});

const res = await client.chat.completions.create({
  model: 'agent',
  messages: [{ role: 'user', content: 'What is the weather in Dhaka?' }],
  tools: [{
    type: 'function',
    function: {
      name: 'get_weather',
      description: 'Current weather for a city',
      parameters: {
        type: 'object',
        properties: { city: { type: 'string' } },
        required: ['city'],
      },
    },
  }],
});

console.log(res.choices[0].message.tool_calls);
Python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://auraroute.dev/api",
    api_key=os.environ["AURAROUTE_API_KEY"],
)

res = client.chat.completions.create(
    model="agent",
    messages=[{"role": "user", "content": "What is the weather in Dhaka?"}],
    tools=[{
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        },
    }],
)

print(res.choices[0].message.tool_calls)

Response headers

Every response says how it was served. These are for observability — they are never inputs.

HeaderMeaning
X-Request-IdQuote this when asking for help.
X-AuraRoute-WorkloadThe pool that answered. Differs from your workload after a fallback.
X-AuraRoute-Routed-ModelThe model that actually answered.
X-AuraRoute-AttemptsMore than 1 means a provider failed and the request was retried elsewhere.

Limits

LimitDetail
ConcurrencyEach key can have a few requests in flight at once. Beyond that you get 429 concurrency_limit_exceeded; wait for one to finish.
Daily tokensEach account has a daily input cap and a daily output cap, shared by every key and the web chat. They reset at 00:00 UTC. Past either one you get 429 daily_quota_exceeded. An administrator can change both caps. Your usage is on the dashboard.
Output lengthmax_tokens is capped at a platform limit.
Request sizeBodies above the size limit are rejected with 413 request_too_large.

Errors

Errors use the OpenAI shape: { "error": { "type", "code", "message", "param" } }. Match on code, not on the message.

StatuscodeWhat to do
400model_not_foundmodel is not a workload. The message lists the valid ones.
400invalid_valueA parameter is wrong; param says which.
400invalid_json / invalid_bodyThe body is not valid JSON.
401invalid_api_keyThe key is missing, malformed or revoked.
413request_too_largeShorten the input.
429concurrency_limit_exceededToo many requests at once on this key. Retry when one finishes.
429daily_quota_exceededQuota used up. It resets at 00:00 UTC.
503capacity_busy / upstream_unavailable / no_provider_availableRetry shortly with backoff; honour Retry-After.
504timeoutThe request took too long. Retry, or shorten it.