LowRouterBeta

Run your first completion

This page sends one chat completion through the gateway, walks through what came back, and points at the things you’ll come back to.

Send the request

Set your key in an environment variable so it doesn’t end up in shell history:

Bash
export LOWROUTER_API_KEY="sk-lr-..."

Then call the gateway:

Bash
curl https://api.lowrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer $LOWROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto/mistralai/mistral-large-2512",
    "messages": [
      {"role": "user", "content": "In one sentence, what is a vector database?"}
    ]
  }'

An auto/<creator>/<model> ID names the model you want and leaves the route to us: among the providers and regions serving it, LowRouter prefers EU-sovereign routes, then the lowest-carbon one (modeled from annual grid averages — see the methodology). You get the same model either way — only where it runs is decided for you.

The model field is required. You can name the route yourself instead, for example openai/openai/gpt-4.1/global or anthropic/anthropic/claude-haiku-4.5/global, pinning a region with a UN/LOCODE as the fourth segment (e.g. vertex/anthropic/claude-opus-4.6/sg-sin), or call an alias you can repoint later without changing code. See routing. Custom auto-routing policies (like a per-key carbon budget) are coming soon.

What comes back

The response is OpenAI-shaped. The fields you’ll use most are:

JSON
{
  "id": "chatcmpl-01J9...",
  "object": "chat.completion",
  "created": 1714150000,
  "model": "openai/openai/gpt-4.1",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "A vector database stores …"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 18,
    "completion_tokens": 26,
    "total_tokens": 44,
    "cost": 0.000034,
    "currency": "EUR",
    "remaining_balance": 9.87
  },
  "lowrouter_metadata": {
    "provider": "openai",
    "region": "eu-west",
    "energy_wh": 0.0021,
    "carbon_gco2e": 0.00057,
    "carbon_intensity_gco2_per_kwh": 45.0,
    "estimation_methodology": "parameter-based",
    "routing_mode": "auto",
    "routing_reason": "lowest_carbon_intensity",
    "fallback_occurred": false,
    "providers_attempted": ["openai"]
  }
}

The OpenAI-compatible parts (id, choices, usage, …) follow the standard OpenAI Chat Completions shape. LowRouter adds three billing fields to usage:

  • cost — what this request cost, in currency. This is the per-request figure: attribute it to a user, tenant, or workflow without scraping a dashboard or maintaining your own price table.
  • currency — ISO-4217 code for cost and remaining_balance (EUR).
  • remaining_balance — your credit balance after this request.

Costs are billed in integer micros (millionths of a euro) and rounded up to the next micro, so a request never bills below what it cost us. On very small requests that rounding is visible: the amount you are charged can exceed the exact computed cost by up to €0.000001.

The lowrouter_metadata block carries the LowRouter-specific fields:

  • provider — which upstream actually served the request.
  • region — the region the upstream served from.
  • energy_wh and carbon_gco2e — the energy and carbon estimate for this request. Read methodology before quoting these numbers anywhere.
  • routing_mode, routing_reason, fallback_occurred, and providers_attempted — the routing trace: how the model was picked and whether a fallback was used.

To look up the full record for a request later, open its transaction on the dashboard.

Stream the response

For interactive UIs, set "stream": true and read Server-Sent Events:

Bash
curl https://api.lowrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer $LOWROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -N \
  -d '{
    "model": "auto/mistralai/mistral-large-2512",
    "stream": true,
    "messages": [{"role": "user", "content": "Count to 5 slowly"}]
  }'

The stream is a Server-Sent Events stream in the same format the OpenAI streaming API uses, so any OpenAI-compatible SDK consumes it unchanged. See integrations for per-SDK snippets.

Streaming does not cost you cost attribution. The final chunk before data: [DONE] carries lowrouter_metadata and a usage object with the same cost, currency, and remaining_balance fields the non-streaming response returns:

JSON
{
  "object": "chat.completion.chunk",
  "choices": [],
  "usage": {
    "cost": 0.000034,
    "currency": "EUR",
    "remaining_balance": 9.87
  },
  "lowrouter_metadata": { "provider": "openai", "...": "..." }
}

Token counts appear exactly once across the stream. If the upstream provider already sent a usage chunk with prompt_tokens / completion_tokens / total_tokens, this final chunk carries the money fields only rather than restating them — so read tokens from whichever chunk carries them, and cost from the final one.

If a stream is cut short — you cancel it, your client times out, or the connection drops — you are still billed for the tokens the provider generated before the cut. Those requests are marked interrupted on the dashboard, in the CSV export, and on the generation record, so you can reconcile them against your own logs.

Things that might surprise you

  • The model in the response is the resolved four-segment ID, not necessarily the string you sent. If you sent an auto/ or alias/ ID, the response tells you which route actually ran.
  • usage reflects upstream tokens, which may include caching discounts (for providers that support them). The credits charged on your dashboard match this usage.
  • The carbon estimate is absent on requests we couldn’t classify, e.g. a model whose parameter count is unknown. The dashboard shows the same record without an eco number rather than a fabricated one.

If it didn’t work

A 401, 402, or 404 here almost always means a key, balance, or model-id problem. The errors reference lists every payload the gateway returns, with the one-line fix for each.

Next

Tour the dashboard →