Flex Mode
Cheaper processing, same endpoint, same shape
Add one field to your normal POST /v1/chat/completions call —
service_tier: "flex" — and get a real discount in exchange for a slower response,
on the exact same endpoint, same request, same response shape you already use. No file to upload, no job id, no second endpoint to learn —
this matches how OpenAI's and Gemini's own service_tier=flex work, and how OpenRouter exposes it too, so an
existing integration that already sets service_tier works against us unchanged.
Need to pool for longer than flex can reach — up to 1 or 6 hours — for deeper savings? See Async Jobs,
a dedicated POST /v1/jobs endpoint with poll-or-webhook delivery.
How it works
service_tier: "flex" is a normal, blocking call — we route it to whichever
candidate model would normally serve it, and when that candidate is OpenAI or Gemini (AI-Studio or Vertex), we forward a real
service_tier=flex upstream and bill you the discounted price those providers actually charge us — not a synthetic
markdown. We hold the connection open up to 15 minutes for it (sized to what OpenAI and Gemini's own flex tiers themselves target — OpenAI recommends a
15-minute client timeout, Gemini's stated latency target is 1–15 min). If the model you're calling has no native flex tier, the request still serves — just at the
standard price — rather than failing.
Need longer than 15 minutes? Async Jobs (POST /v1/jobs) has no
synchronous provider equivalent to be wire-compatible with, so it's a background job instead — pooling for up to 1 or 6 hours, delivered by poll or webhook.
Using the API
Base URL https://api.llmrouter.sh/v1, Bearer key
llmr_sk_live_….
"flex" — one call, blocking
Exactly your normal /v1/chat/completions body, plus service_tier: "flex". The call
blocks — same as any request without it — and returns a normal 200 with a chat.completion body once the
model responds. The response's own service_tier field reports which tier actually served: "flex" when the
discount applied, "default" when the resolved model had no native flex tier to use. Give it a long client-side timeout — up to
15 minutes.
import requests
response = requests.post(
"https://api.llmrouter.sh/v1/chat/completions",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"model": "openai/gpt-5",
"service_tier": "flex",
"messages": [{"role": "user", "content": "What is the meaning of life?"}],
},
timeout=900,
)
data = response.json()
print(data["choices"][0]["message"]["content"])
print("Served by tier:", data.get("service_tier"))
# → "flex" if a real discount applied, "default" if this model has no native flex tier
Need to submit and come back later instead of blocking? See Async Jobs —
POST /v1/jobs, delivered by poll or webhook.
Choosing a tier
service_tier: "flex" matches OpenAI's, Gemini's, and OpenRouter's own parameter — a blocking call, real ~50%
off when the model has a native flex tier. Need to wait longer than 15 minutes for deeper pooled savings, or submit more than a handful of requests at once?
See Async Jobs (single requests, 1h/6h, poll or webhook) and the file-based
Batch API (bulk, up to 24h, up to 50,000 requests).
service_tier |
Window | Delivery | Price |
|---|---|---|---|
| unset (default) | seconds | synchronous — normal 200, instant response |
standard + 1% |
"flex" |
≤ 15 min | synchronous — normal 200, same call blocks longer |
OpenAI / Gemini flex ~50% off; else standard |
"flex"'s window is 15 minutes, not 10 — sized to what OpenAI (recommends a 15-min client timeout) and Gemini
(target latency "1-15 min") themselves need. Promising less than the provider's own commitment isn't an SLA we could keep. Longer windows (1h/6h/24h) live on
Async Jobs and the Batch API.
Which models support flex
This is decided by OpenAI and Google, not by us, and it changes as they add models — neither publishes it as a queryable API field. We track it directly against
each provider's own published list below, and on top of that we detect it live, per model, from the provider's own response — so a model that isn't
on this list yet (a new release, say) still gets tried automatically, and a model that turns out not to support it still succeeds at the standard price
rather than failing. You never have to hardcode this list in your own integration to use service_tier: "flex" safely.
OpenAI (developers.openai.com/api/docs/pricing)
| o4-mini | o4-mini-deep-research | o3-deep-research | gpt-chat-latest |
| gpt-5.3-codex | gpt-5.4 | gpt-5.4-mini | gpt-5.4-nano |
| gpt-5.4-pro | gpt-5.5 | gpt-5.5-pro | gpt-5.6-sol |
| gpt-5.6-sol-pro | gpt-5.6-terra | gpt-5.6-terra-pro | gpt-5.6-luna |
| gpt-5.6-luna-pro |
Notably not on this list: the classic GPT-4o family (gpt-4o, gpt-4o-mini) and the plain
gpt-5/gpt-5.1/gpt-5.2 releases — call them with service_tier: "flex" anyway and
you'll still get a normal 200, just at standard price (service_tier:"default" in the response).
Gemini (ai.google.dev/gemini-api/docs/flex-inference)
| gemini-2.5-flash | gemini-2.5-flash-lite | gemini-2.5-pro | gemini-3-flash-preview |
| gemini-3.1-flash-lite | gemini-3.1-pro-preview | gemini-3.5-flash |
Available on both the AI-Studio and Vertex transports. Gemma models share Gemini's google provider tag but are a
separate model family and not on Gemini's flex-inference list.
These lists are checked against each provider's published docs and kept current in our routing config, not hand-typed into this page — see
the model directory or call GET /v1/models
for the full, live, routable model catalog and current pricing.
Errors
400 unsupported_service_tier— anything other than unset,"auto"/"default"/"standard"/"flex".400 flex_streaming_unsupported—stream: truewithservice_tier: "flex".429/503witherror.code: "resource_unavailable"— the upstream provider's flex capacity is exhausted (OpenAI's own shape for this). Never billed — retry with backoff, or dropservice_tierand resend.402 insufficient_credits— the same balance check every synchronous request does;"flex"never enqueues anything, so there's nothing to release on failure.
Async Jobs has its own error list — unsupported_completion_window, invalid_webhook_url, job_not_found — since it's a separate endpoint, not a service_tier value.
Pricing
Billed exactly like every other request — the model's per-token price × whatever discount the tier actually earned, plus the flat 1% platform fee.
We never advertise a discount we haven't bought: on "flex", models served through OpenAI or Gemini (AI-Studio or Vertex) get that
provider's own real service_tier=flex discount forwarded straight through and billed at the discounted price they actually charge us —
reported back to you in the response's own service_tier field. Everything else runs at the standard
price — "flex" still serves the request rather than failing, just without a price cut. The same OpenAI/Gemini discount
applies on Async Jobs' longer windows too.