For Providers
If you’d like to be a model provider and sell inference on OpenRouter, fill out our form to get started.Integrated before the current model document format? The
legacy flat format remains supported for existing
integrations.
1. List Models Endpoint
You must implement an endpoint that returns all models that should be served by OpenRouter. Each model is described as a set of typed input and output modality objects: every modality owns its capabilities, constraints, passthrough parameters, pricing, and capacity. Only request-scoped prices and capacity entries with no owning modality remain at the document root. Below is an example of the response format:id field should be the exact model identifier that OpenRouter will use when calling your API.
All cost_usd fields are in string format to avoid floating point precision issues, and must be in USD.
The previous flat model document format (a flat
pricing object with pricing.overrides, supported_sampling_parameters,
supported_features, and capacity_tpm) remains supported for existing integrations, but use
the format above for all new integrations.int4, int8, fp4, mxfp4, nvfp4, fp6, fp8, mxfp8, fp16, bf16, fp32. Use null (or omit the field) when the precision is undeclared.
The optional tokenizer field names the tokenizer family the model uses (for example GPT, Claude, Llama3, Gemini). Like quantization, it describes the model as a whole, so it lives at the root rather than under any modality. Omit it when unknown.
2. Modalities
A document must declare at least one input modality and at least one output modality.Input Modalities
Valid input modality types are:text, image, video, audio, file.
The
supported_inputs object uses the same capability descriptor grammar as output supported_parameters, with closed enums for every known value domain:
Common constraint fields:
sources— how media may be supplied:url,base64formats— accepted MIME types, e.g.image/png,image/jpeg,image/webp,image/giffor images;video/mp4,video/webmfor video;audio/wav,audio/mpegfor audio;application/pdf,text/plain,text/markdown,text/html,text/csv,application/jsonfor filesdetail_levels(image) —auto,low,high,originalrole(image) — the role an image plays in the request:reference,first_frame,last_framereferences(image, file) — an integer descriptor for how many reference items a request may include, e.g.{ "type": "integer", "min": 0, "max": 10 }max_context_length(text) — the total context window: input and output tokens combinedmax_prompt_length(text) — the maximum input length alone; declare it only when it differs from the context window
max_context_length, max_prompt_length, output max_length, max_duration_seconds, max_content_size_bytes) are objects with a value and an optional unit (second, pixel, byte, token, character):
Output Modalities
Valid output modality types are:text, image, video, speech, transcription, embeddings, rerank, audio.
Capability Descriptors
supported_parameters and passthrough_parameters are maps from parameter name to a typed descriptor describing what the parameter accepts:
Descriptors may carry an optional
default and, for numeric types, a unit. An absent key means the parameter is unsupported.
3. Pricing
Pricing uses arrays nested on the modality that owns them. Each pricing entry has atype (the billing kind), a unit (the billing basis), and a cost_usd string. The unit is the base billing unit, not a commitment to a flat price: per-image and per-token prices can scale with parameters declared by the owning modality.
Each pricing scope accepts the units it can bill in: input entries take token, image, second, or character; output entries additionally take request; root request entries are always per request and web_search entries per search. Other combinations are rejected at validation time.
A document that validates is a valid declaration, not a guarantee that every declared SKU is billed today: OpenRouter bills the SKUs its pipeline supports and records the rest, and billing for newly declared SKU shapes lands as support for them does. Declare what you charge; do not tailor the document to what OpenRouter currently bills.
Input pricing types (on input modality entries):
Output pricing types (on output modality entries):
Request pricing types (root
pricing array — the only prices at the root):
Do not zero-stuff prices: omit pricing entries for SKUs you don’t bill. A genuinely free SKU exposed as a distinct billable line may use
"0". A modality with no pricing array is simply unpriced.
Conditional Pricing with overrides
Conditional pricing (e.g. long-context tiers) attaches declaratively to the individual pricing entry it modifies, using a when predicate:
supported_parameters and attach overrides keyed by those parameter names. A plain predicate map applies AND across its keys:
when predicate is either a parameter-to-condition map or a composition using allOf, anyOf, and not. Composition members are predicates, so these operators can be nested. Conditions reuse the operators equals, gte, lte, and min_items, with exactly one operator per condition object; a composition object carries exactly one of allOf, anyOf, or not. A plain multi-key map is equivalent to allOf over single-key maps.
Override entries are evaluated in order. Among matching predicates, the later entry wins. This makes a resolution-by-steps price matrix expressible without OR nesting. Predicates may reference parameters declared by the owning modality or request-derived quantities such as prompt token count.
Override predicates are parameter-based. Time-dependent pricing is not an override, because time
is not a request parameter — see Time-of-Day Pricing.
Cache Pricing
Cache prices are first-class SKUs in a modality’spricing array. Multiple entries may have the same type when their qualifier fields differ. The effective identity of an entry is its type together with its qualifiers, so two cache_write entries with different TTLs are separate SKUs. Two entries with the same effective identity are invalid.
ttl_seconds is the cache lifetime the price applies to. It is a qualifier field, not part of the type string, so providers can add lifetimes without expanding the pricing type enum. implicit marks provider-initiated caching that the request does not ask for and defaults to false. Explicit and implicit cache modes can coexist on one model.
Cache pricing is input-side. Prompt caching stores and re-reads input tokens, so cache entries belong on input modality entries and never on outputs. The word write describes writing to the prompt cache, not generated output.
Cache prices are base entries, not overrides. Overrides remain reserved for request-conditional pricing on generation parameters. Cache SKUs are enumerable so billing and product surfaces can display them directly. A provider may take TTL as a request parameter and the price is still modeled as a cache SKU rather than an override. A cache entry may itself carry overrides for genuinely request-conditional pricing, such as a long-context tier raising the cache write rate, but never for TTL differences.
Cache pricing is per modality, so an image input modality can carry its own cache entries at its own rates. A text input modality offering two explicit write lifetimes alongside provider-initiated caching looks like this:
Time-of-Day Pricing
Time-dependent prices (peak and off-peak rates) follow the same pattern as cache lifetimes: the time window is a pair of structured qualifier fields on the pricing entry, not an override. Time is not a request parameter, so an override’swhen predicate has nothing to reference.
utc_start and utc_end are HHMM values in UTC (0000–2359; the minute component must be 00–59), declared together, and must differ. The window is half-open — it includes utc_start and excludes utc_end — and may wrap midnight. An entry without a window is the base rate for all other hours. A text modality billed at a higher rate during a peak window looks like this:
ttl_seconds, the window is part of the entry’s effective identity, so entries with different windows are separate SKUs and two entries with the same window are invalid.
4. Capacity
Capacity uses the same typed, scoped placement as pricing. Each input and output modality may carry its owncapacity array as a sibling of pricing. The root capacity array holds request-scoped entries only. This adds no new root structure.
Each capacity entry has a type describing what is limited, a unit giving the basis, a per window, and a positive integer value:
concurrency for simultaneous in-flight work. concurrency has no per window. Valid windows are minute, hour, and day. An absent capacity array means the limit is undeclared, not zero.
A capacity entry’s identity is its type, unit, and per window together, and two entries with the same identity are invalid. Entries that differ only in their window may coexist, so a per-minute burst limit and a daily quota on the same dimension are both declarable. concurrency entries carry no window, so they are unique by type and unit alone.
Limits declared in different scopes are independent buckets that all apply simultaneously: a per-modality token limit and a root request limit each constrain traffic on their own dimension, and a request is admitted only when every declared limit it consumes against has headroom. Declaring a limit in one scope does not relax or replace a limit in another.
This reuse distinguishes prompt, cached prompt, and output capacity without adding separate fields for each dimension. Capacity and pricing remain separate sibling arrays because a modality may declare limits without prices, or prices without declared limits. Units are constrained per scope, exactly as pricing units are: an entry accepts any unit its scope (input, output, or root) can bill in, so image capacity is expressed as images per minute, video capacity as output seconds per minute, and a mismatched pairing (such as a prompt capacity per search) is rejected at validation time. Validation is not narrowed to the owning modality’s own billing unit, which is why an image output modality may carry a concurrency entry in request units.
Here is a capacity declaration covering text input, text output, image output, and request scope:
5. Passthrough Parameters
Passthrough parameters are provider-specific escape hatches that OpenRouter forwards verbatim, distinct from the normalizedsupported_parameters. They are placed by scope:
- Request-scoped parameters (applying to the request as a whole) live in the root
passthrough_parametersmap. - Input-scoped parameters (owned by one input modality, e.g. reference-media controls) live on that input entry.
- Output-scoped parameters (generation controls owned by one output modality) live on that output entry.
6. Datacenters & Compliance
Declare where each endpoint physically serves from and its data-handling posture:datacenters[].country_code— ISO 3166-1 alpha-2 country code.datacenters[].region— provider-scoped region identifier (e.g.us-east-1).compliance.zdr— zero data retention: no prompt retention and no training on prompts.compliance.hipaa— HIPAA compliance. Additional boolean certification flags (SOC 2, GDPR, FedRAMP, …) may be added over time.
7. Operational Fields
The operational fields control model availability and routing:Deprecation Date
If a model is scheduled for deprecation, include thedeprecation_date field in ISO 8601 format. OpenRouter accepts either a date-only value or a specific UTC hour:
- Use
YYYY-MM-DDfor date-only deprecations. Date-only values default to 13:00 UTC on that date. - Use
YYYY-MM-DDTHH:00:00Zto request a specific UTC hour, for example2025-06-01T15:00:00Z.
Controlling Launch with is_ready
By default, when OpenRouter’s provider monitor sees a new model in your /v1/models response, it auto-stages the endpoint, runs baseline tests, and unhides it (makes it live) once the tests pass and pricing is configured. If you need to upload a model ahead of an announcement — or temporarily take a model offline — set the optional boolean is_ready field:
is_ready: falseskips baseline tests for newly-staged endpoints, keeping them hidden, and auto-hides any matching endpoint that is currently live. Use this to upload a model in advance of launch, or to take a live model offline coordinated with us.is_ready: trueand an omitted/absent field both preserve the default auto-stage and auto-unhide behavior.
Free Model Variants with is_free
If you want to offer a free version of a model, set is_free: true:
is_free: truemarks the endpoint as a free endpoint (:freesuffix).- Any pricing sent alongside
is_free: trueis ignored — free endpoints always have zero cost. is_free: falseor an omitted field preserves the default behavior (standard paid variant).
is_free: true on the free one.
Discounts with discount_to_user
To offer a discount on the prices users see and pay, include the optional discount_to_user field. It’s a decimal fraction that OpenRouter applies to your displayed pricing:
0.2means users see and pay 20% less than your listed pricing. Acost_usdof"0.000024"displays as0.0000192.- The discount applies to every priced SKU (prompt, completion, image, cache reads, and so on), including conditional overrides and time windows.
0, an omitted field, or an absent field all mean no discount.- A negative value applies a markup instead of a discount, so
-0.1shows prices 10% higher. - A value of
1or higher would make the model free (or negative-priced), which isn’t a valid discount. The schema rejects it as a validation error, so use a value below1.
discount_to_user as a number, not a string. Unlike the cost_usd fields, it isn’t quoted.
8. Schema Download
The full schema is available as an OpenAPI 3.1 document, in which every closed value domain (modality types, pricing types and units, capacity windows, descriptor types, media sources, formats) surfaces as an explicitenum:
Download the provider schema (OpenAPI 3.1 JSON)
9. Auto Top Up or Invoicing
For OpenRouter to use the provider we must be able to pay for inference automatically. This can be done via auto top up or invoicing.10. Uptime Monitoring & Traffic Routing
OpenRouter automatically monitors provider reliability and adjusts traffic routing based on uptime metrics. Your endpoint’s uptime is calculated as: successful requests ÷ total requests (excluding user errors). Errors that affect your uptime:- Authentication issues (401)
- Payment failures (402)
- Model not found (404)
- All server errors (500+)
- Mid-stream errors
- Successful requests with error finish reasons
- Bad requests (400) - user input errors
- Oversized payloads (413) - user input errors
- Rate limiting (429) - tracked separately
- Geographic restrictions (403) - tracked separately
- Minimum data: 100+ requests required before uptime calculation begins
- Normal routing: 95%+ uptime
- Degraded status: 80-94% uptime → receives lower priority
- Down status: <80% uptime → only used as fallback
11. Performance Metrics
OpenRouter publicly tracks TTFT (time to first token) and throughput (tokens/second) for all providers on each model page. Throughput is calculated as: output tokens ÷ generation time, where generation time includes fetch latency (time from request to first server response), TTFT, and streaming time. This means any queueing on your end will show up in your throughput metrics. To keep your metrics competitive:- Return early 429s if under load, rather than queueing requests
- Stream tokens as soon as they’re available
- If processing takes time (e.g. reasoning models), send SSE comments as keep-alives so we know you’re still working on the request. Otherwise we may cancel with a fetch timeout and fallback to another provider
12. Auto Exacto: Tool-Calling Traffic Routing
Auto Exacto is a routing step that automatically reorders providers for all requests that include tools. It runs by default on every tool-calling request and may change how much tool-calling traffic your endpoints receive.How traffic is affected
Auto Exacto shifts tool-calling traffic toward providers that perform well on tool-use quality signals. Providers with strong metrics are moved to the front of the routing order and will receive more tool-calling requests, while providers with weaker signals are deprioritized and will see less. Non-tool-calling traffic is not affected by Auto Exacto — it continues to follow the standard price-weighted routing.How ranking factors are determined
Auto Exacto uses three classes of signals, all derived from real traffic and evaluations on your endpoints:- Throughput — real-time tokens-per-second measured from actual requests routed through your endpoint (visible on the Performance tab of any model page).
- Tool-calling success rate — how reliably your endpoint completes tool calls without errors (also visible on the Performance tab).
- Benchmark data — results from internal evaluations we run against provider endpoints. We are actively collecting this data and will make it available in your provider dashboard soon so you can review and run the same benchmarks on your end.
How deprioritization thresholds work
Throughput and tool-calling success rate compare current signal values against the live group of providers serving each model using a median + MAD (median absolute deviation) approach. Benchmark accuracy instead uses a historical baseline from the model’s early benchmarking window, so once that window closes its cutoff does not move with the current peer group. Each signal has a different sensitivity:- Benchmark accuracy — the cutoff is a baseline computed from the first approximately 21 days of benchmarking for that model and benchmark type: the median of per-endpoint scores over that window minus 2 standard deviations (median − 2σ). Each window opens with the first qualifying result for that model and benchmark type. While a window is still in progress, the baseline is periodically recomputed from all qualifying results collected so far, so a new qualifying result for that benchmark type from any provider can shift the cutoff; after the window closes, the baseline as currently constituted admits no results from later benchmark runs and later changes in another provider’s score do not move the cutoff. An endpoint scoring below the cutoff, or missing benchmark data entirely, is deprioritized.
- Throughput — providers falling more than 1.5 standard deviations below the median are deprioritized. The wider margin accounts for natural throughput variance caused by time-of-day load patterns.
- Tool-calling success rate — providers falling more than 2 standard deviations below the median are deprioritized. Success rates cluster near 100%, so this wider margin avoids penalizing normal noise while catching genuinely broken endpoints.
- Good — sufficient data and no signals below threshold. These receive top routing priority.
- Insufficient data — not enough recent traffic to evaluate. These sort behind known-good providers but ahead of deprioritized ones. An endpoint needs at least 100 general requests (30-minute window) and 200 tool-call requests (2-hour window) before it can be evaluated.
- Deprioritized — one or more signals fell below threshold. These are routed to last.
How to improve your ranking
To maximize the tool-calling traffic routed to your endpoints:- Maintain high tool-call reliability — ensure your endpoint returns well-formed tool call responses consistently.
- Optimize throughput — minimize queueing and stream tokens as soon as they are available (see Performance Metrics above).
- Return early 429s under load — rather than queueing and degrading throughput, return rate limit errors so we can retry with another provider and your metrics stay healthy.