OpenRouter API
- Kind: OpenAI-compatible aggregator (300+ models, 50+ providers, one key)
- Official docs: https://openrouter.ai/docs
- Cyberine adapter:
LoopAgentAdapter(idsloop-deepseek-openrouter, build workerloop-openrouter-build) - Fallback for the model-level DeepSeek worker when no
DEEPSEEK_API_KEYis set. - Researched/verified: 2026-06-07 — confidence high.
- DeepSeek section re-verified 2026-08-24 (T686) against the live catalog — see DeepSeek ids (V4) and Pricing below.
Base URL & auth
| Base URL | https://openrouter.ai/api/v1 |
| Auth header | Authorization: Bearer <OPENROUTER_API_KEY> |
| Keys | https://openrouter.ai/settings/keys |
| Optional headers | HTTP-Referer: <site>, X-Title: <name> — attribution only (affect public rankings), not required for server use |
No per-provider auth — OpenRouter wraps every provider under one key.
Endpoints
| Method + path | Purpose |
|---|---|
POST /chat/completions | OpenAI-compatible chat completions + OpenRouter extensions (provider routing, reasoning). |
GET /models | Catalog with pricing, context_length, supported_parameters; add auth for per_request_limits. |
GET /generation?id=<id> | Usage/metadata for a past generation. |
GET /key | Credit balance, usage, limit_remaining. |
GET /openapi.{yaml,json} | Full OpenAPI spec. |
Models
Model ids use vendor/model form. Enumerate live via GET /api/v1/models — the catalog changes.
| Model id | Notes |
|---|---|
deepseek/deepseek-v4-pro-0813 | Cyberine default (OPENROUTER_MODEL) since T691. Dated current V4 Pro GA — see DeepSeek ids (V4) below for why the date suffix is mandatory here. |
deepseek/deepseek-r1 | 671B/37B, 164K ctx, $0.70/$2.50, MIT, open reasoning tokens. |
anthropic/claude-sonnet-4.6 | 1M ctx, $3/$15. Note the dot, not hyphen (see gotcha). |
google/gemini-2.5-flash | 1M ctx, $0.30/$2.50, built-in thinking. |
moonshotai/kimi-k2-0905 | 1T/32B, 262K ctx, $0.60/$2.50. (Repo's kimi-k2.6 is not an OpenRouter slug — see gotcha.) |
openrouter/auto | Auto-router picks the best model. |
~vendor/model-latest | Tilde-prefixed dynamic aliases → newest version. |
DeepSeek ids (V4) — re-verified live 2026-08-25 (T691)
Enumerated via curl https://openrouter.ai/api/v1/models (raw JSON — a summarizing fetch drops
exactly the id/pricing precision this table needs):
| Model id | Modalities | Notes |
|---|---|---|
deepseek/deepseek-v4-flash-vision-exp | ["text","image"] | The only OpenRouter DeepSeek id that accepts images (new 2026-08-21). |
deepseek/deepseek-v4-flash-0731 | ["text"] | Current V4 Flash GA, dated id. CYBERINE_JUDGE_MODEL_WEAK's default and the flash variant of loop-openrouter-build since T691. 29 upstream vendors. |
deepseek/deepseek-v4-pro-0813 | ["text"] | Current V4 Pro GA, dated id. OPENROUTER_MODEL's default since T691. canonical_slug: deepseek/deepseek-v4-pro-20260813, created 2026-08-12, 15 upstream vendors. |
~deepseek/deepseek-v4-flash-latest | ["text"] | Floating alias; currently targets flash-0731. |
deepseek/deepseek-v4-pro | ["text"] | Legacy undated alias — resolves to canonical_slug: deepseek/deepseek-v4-pro-20260423, an OLDER GA than the dated -0813 id above. Was OPENROUTER_MODEL's default until T691 repointed it; still valid to pin, but DeepSeek themselves no longer serve it (see below). |
deepseek/deepseek-v4-flash | ["text"] | Same pattern — legacy undated alias, canonical_slug dated 0423. Was CYBERINE_JUDGE_MODEL_WEAK's default until T691. |
Dated-vs-stable id trap: DeepSeek's own direct API exposes stable, undated ids
(deepseek-v4-flash, deepseek-v4-pro) that always point at the current GA — see
deepseek.md. OpenRouter inverts this: its DATED ids (-0731, -0813) are the
ones that track a specific GA release, while its UNDATED ids (deepseek/deepseek-v4-pro,
deepseek/deepseek-v4-flash) are legacy aliases frozen on an older release. Copying an id
between the two routes on the assumption "no date suffix = latest" silently pins the OLDER
model on OpenRouter.
How to tell them apart — read the ENDPOINTS listing, not the model page (the page and the
catalog's top-level pricing field both disagree with it; see Pricing below):
curl https://openrouter.ai/api/v1/models/deepseek/deepseek-v4-pro/endpoints # 17 vendors
curl https://openrouter.ai/api/v1/models/deepseek/deepseek-v4-pro-0813/endpoints # 15 vendorsLive 2026-08-25 the differing vendor counts and price ceilings are what separate them, but the
decisive field is provider_name: the undated aliases have no "DeepSeek" endpoint at all
(17 third-party re-hosts topping out at Azure $1.91/$3.83 for pro-0423, and 17 topping out at
$0.44/$1.32 for flash-0423), while each dated current-GA id does (pro-0813 at $0.66/$1.98,
flash-0731 at $0.22/$0.66 — matching DeepSeek-direct's own off-peak rates to the cent). DeepSeek
has walked away from serving its own frozen 0423 weights here.
T691 decision: the Cyberine defaults are DATED, and the re-pointing burden is accepted
Cyberine repointed rather than freeze. OPENROUTER_MODEL, JUDGE_MODEL,
CYBERINE_JUDGE_MODEL_STRONG, CYBERINE_JUDGE_MODEL_WEAK, and loop-openrouter-build's model +
reasoning/flash variants now default to the dated current GAs. Before T691 every dispatch
through loop-deepseek-openrouter / loop-openrouter-build silently ran the 2026-04-23 GA while
the code and docs read as current. "Leave it undated and document the staleness as deliberate"
was rejected for one reason above all: no upstream party stands behind the alias any more — see
the provider_name finding above.
The burden this creates, stated plainly: a dated id goes stale by construction. When DeepSeek
ships the next V4 GA, OpenRouter mints a new -MMDD id and Cyberine's defaults keep running the
previous one until someone bumps them. Three things bound it:
| Bound | What it is |
|---|---|
| One edit site | src/core/openrouterModelIds.ts holds the two constants; config.ts, workerProfiles.ts, and selectJudgeModel.ts's customized-weak sentinel all read them. Add a modelPricing.ts row for the new id too, or cost estimation silently drops to the coarse provider-level fallback. |
| A scheduled owner | Recurring chore R02 (the CHANGELOG-WATCH sweep, every 7d) already treats "new model id" as a material upstream change; its OpenRouter row now names this check explicitly. |
| An operator escape hatch | OPENROUTER_MODEL overrides the default with no code change, so a stale constant is a wrong default, never a wall. |
| A regression guard | npm run selftest:openrouter-model-default (offline) asserts both directions: every OpenRouter-routed default is dated, every DeepSeek-direct / dual-route id stays undated, the DeepSeek-direct judge sentinel still yields a bare id, each dated default has a modelPricing.ts row, and no src/ file re-hardcodes an undated alias as an OpenRouter default. |
2026-09-10 (kq2ne, R02 sweep): deepseek/deepseek-v4.1-flash appeared; NOT adopted, and this
route just became more important, not less. DeepSeek shipped V4.1-Flash on 2026-09-10 and the new
line is live here: 1M context, $0.15/$0.60 per 1M, canonical_slug: null, and 4 endpoints —
against 29-30 for the dated deepseek/deepseek-v4-flash-0731. Not adopted, for the reason this
section already settles: it is UNDATED, so pinning it reproduces exactly the drift T691 removed,
and 4 endpoints is thin routing next to the dated line's 30. The adoptable form is a dated
-MMDD V4.1 id; re-check for one each sweep. Both existing constants are still the newest dated
ids, so nothing is stale today.
The asymmetry worth recording: from 2026-09-14 this route is the only one that still reaches a
real V4-Pro. DeepSeek-direct routes deepseek-v4-pro to V4.1 Flash on that date (k9tvx), while
OpenRouter dispatches DATED snapshots — deepseek/deepseek-v4-pro-0813 keeps resolving to the
2026-08-13 Pro build. The dated-id burden this section accepted as a cost is what makes the
OpenRouter path immune to an upstream re-route, which is the strongest argument yet for keeping it.
Re-confirmed 2026-09-04 (km6mp), with a fifth and decisive reason: the alias serves NOTHING.
GET /api/v1/models/~deepseek/deepseek-v4-flash-latest/endpoints returns 0 endpoints and a
canonical_slug of null, against 30 endpoints for deepseek/deepseek-v4-flash-0731 on the
same call minutes apart. So the floating alias is listed in the catalogue but no provider serves it:
adopting it would not merely cost reproducibility, it would make every loop-openrouter-build
dispatch fail with no route. The four T691 reasons below stand unchanged and this one supersedes the
need to weigh them. Also re-verified the same day: the two dated constants in
src/core/openrouterModelIds.ts are still the newest dated ids (no newer -MMDD upstream), and
there is still no ~deepseek/deepseek-v4-pro-latest at all. Two ids new to the route since the last
sweep are recorded as available and NOT adopted: deepseek/deepseek-v4-flash-vision-exp (canonical
...-20260821, DeepSeek's own experimental vision model) and :batch variants of both dated ids.
~...-latest was considered and rejected. A real floating alias exists for flash
(~deepseek/deepseek-v4-flash-latest) but not for pro — verified against the full 417-model
catalog 2026-08-25. Adopting it for flash alone would make one tier self-maintaining while the
other still needs a manual bump; a moving pointer cannot carry a stable modelPricing.ts row (its
catalog price already differs from flash-0731: $0.040/$0.080 vs $0.066/$0.132); a run's recorded
model id would stop identifying which weights actually ran, breaking .local/runs/<id>/run.json
reproducibility; and zsh performs filename expansion on the right-hand side of assignments, so
OPENROUTER_MODEL=~deepseek/... is a live tilde-expansion footgun in this repo's own shell.
Two ids deliberately stay undated. DEEPSEEK_MODEL / OPENCODE_MODEL /
CYBERINE_OPENCODE_DEEPSEEK_MODEL reach DeepSeek directly (OpenCode's deepseek/ namespace
authenticates with DEEPSEEK_API_KEY, not an OpenRouter key), where undated is the current
pointer and a dated id is rejected with HTTP 400. And CYBERINE_ROUTER_MODEL is a dual-route
id: router.ts strips the deepseek/ prefix and sends it to DeepSeek-direct when no OpenRouter
key is configured, so only the undated form resolves on both branches — it keeps running the
frozen 0423 alias on the OpenRouter branch, accepted for one cheap classification call.
Key request params
- Standard OpenAI fields:
model,messages,max_tokens/max_completion_tokens,temperature,top_p,top_k,stream,response_format,tools/tool_choice,seed,stop, penalties,logprobs,parallel_tool_calls reasoning— thinking control;reasoning_effort:xhigh|high|medium|low|minimal|noneprovider— provider-routing object (only,sort,zdr, BYOK …)structured_outputs,web_search_options- Suffix shortcuts on a slug:
:nitro(sort by throughput),:floor(sort by price),:free
Notable features
- OpenAI drop-in (works with
openaiSDK by settingbaseURL). - Provider routing + auto schema translation for non-OpenAI providers.
- Streaming over SSE; post-stream errors arrive as SSE events with HTTP 200.
GET /modelswith auth returnsper_request_limitsscoped to your balance.- BYOK, ZDR routing (
provider.zdr:true), free tier (:freeids). - Unsupported params are silently ignored (schema normalized across providers).
Gotchas
- Credit reservation: OpenRouter reserves the full
max_tokensagainst your balance up front. On a credit-limited key this returns HTTP 402 immediately even if real usage would be tiny → keepmax_tokensconservative. (This is why Cyberine keepsLOOP_MAX_TOKENSlow on OpenRouter fallback.) - 402 = insufficient credits; a negative balance also 402s free models.
- 503 = no provider meets routing constraints (e.g.
provider.only/zdr) — config issue, not transient. - Model id format is
vendor/model— verify slugs viaGET /models; wrong separator → model-not-found. - Repo's
kimi-k2.6is unconfirmed on OpenRouter (onlymoonshotai/kimi-k2-0905confirmed). Cyberine reaches Kimi via Moonshot-direct / OpenCode, not OpenRouter, so this is informational. - Repo's
claude-sonnet-4-6(hyphen) vs OpenRouter'santhropic/claude-sonnet-4.6(dot).
Pricing
No markup in principle — each listing shows an upstream provider's own rate. The Jun 2026
example here (deepseek/deepseek-v4-pro $0.435/$0.87) was a promo rate that expired
2026-05-31; it is stale and has been removed rather than replaced with a new point figure,
because live 2026-08-24 measurement (below) shows OpenRouter's own numbers for a single model
id are NOT one stable price.
Unresolved discrepancy, recorded rather than picked: for deepseek/deepseek-v4-pro-0813,
GET /api/v1/models reports "prompt":"0.000001122","completion":"0.000003366" ($1.122/$3.366
per 1M) at the catalog's top level, while the model's own human-readable page
(openrouter.ai/deepseek/deepseek-v4-pro-0813) advertises a lower "$0.66 per million input
tokens, $1.98 per million output tokens" for the SAME id — both re-confirmed live 2026-08-24 via
raw curl (JSON field and page HTML respectively), cause unexplained. Drilling into
GET /api/v1/models/deepseek/deepseek-v4-pro-20260813/endpoints shows why a single number is
misleading: OpenRouter multiplexes this one model id across (at last count) 15 upstream compute
vendors, each billed at its own independently-set rate — DeepSeek's own endpoint is cheapest at
$0.66/$1.98 (matching the page), others run up to Phala at $1.45/$4.36 per 1M — and which vendor
actually serves a given request depends on OpenRouter's live routing/availability, not a fixed
catalog price. Do not treat either the page price or the /models price as authoritative;
Cyberine's own conservative fallback for this route (src/store/creditLedger.ts) is set from
this per-endpoint spread rather than either single figure — see that file's openrouter row
for the exact reasoning. Other rows remain approximate: anthropic/claude-sonnet-4.6 $3/$15;
google/gemini-2.5-flash $0.30/$2.50. Catalog: https://openrouter.ai/pricing
Cyberine integration notes
- Registered as
loop-deepseek-openrouteronly whenDEEPSEEK_API_KEYis absent andOPENROUTER_API_KEYis set; build variant isloop-openrouter-build. LOOP_MAX_TOKENSmatters more here than on DeepSeek-direct because of the credit-reservation behavior above.
Sources
- https://openrouter.ai/docs/api/reference/overview
- https://openrouter.ai/docs/api/reference/authentication
- https://openrouter.ai/docs/guides/routing/provider-selection
- https://openrouter.ai/docs/api/reference/parameters
- https://openrouter.ai/docs/api/reference/errors-and-debugging
- https://openrouter.ai/docs/api/reference/limits
- https://openrouter.ai/api/v1/models (live catalog; re-fetched raw 2026-08-24)
- https://openrouter.ai/api/v1/models/deepseek/deepseek-v4-pro-20260813/endpoints (per-vendor pricing spread; fetched 2026-08-24)
DeepSeek API (direct)
All paths are relative to https://api.deepseek.com. Every one below was called live on 2026-08-25 (T679) and returned the status shown.
Anthropic Claude API (Messages)
Fable 5 $10/$50 · Opus 5 + 4.x $5/$25 (Opus 5 / Opus 4.8 fast mode $10/$50) · Sonnet 5 $2/$10 (permanent since 2026-08; the 2026-09-01 rise to $3/$15 was cancelled) · Sonnet 4.x $3/$15 · Haiku 4.5...