OpenRouter Integration
Use official OpenRouter docs as the source of truth for current endpoints, parameters, and capability metadata. Prefer openrouter.ai/docs, openrouter.ai/openapi.json, and the API reference pages under openrouter.ai/docs/api-reference.
Quick Snippets
Use these for fast copy-paste before reaching for the fuller references or templates.
Curl: list models
curl -s https://openrouter.ai/api/v1/models \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Accept: application/json"
Curl: list providers
curl -s https://openrouter.ai/api/v1/providers \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Accept: application/json"
Curl: fetch one generation and its cost
curl -s "https://openrouter.ai/api/v1/generation?id=$GENERATION_ID" \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Accept: application/json"
Fetch: free models from the catalog
const res = await fetch("https://openrouter.ai/api/v1/models", {
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
Accept: "application/json",
},
});
const json = await res.json();
const freeModels = (json?.data ?? []).filter((model: any) => {
const pricing = model?.pricing ?? {};
return ["prompt", "completion", "request", "image"].every((key) => {
const value = pricing[key];
return value == null || value === "0";
});
});
Curl: text-only chat call
curl -s https://openrouter.ai/api/v1/chat/completions \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-H "HTTP-Referer: ${OPENROUTER_SITE_URL:-http://localhost:3000}" \
-H "X-OpenRouter-Title: ${OPENROUTER_APP_NAME:-My App}" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [
{"role": "user", "content": "Write a one-line summary of invoice OCR."}
],
"temperature": 0
}'
Fetch: image input
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": process.env.OPENROUTER_SITE_URL || "http://localhost:3000",
"X-OpenRouter-Title": process.env.OPENROUTER_APP_NAME || "My App",
},
body: JSON.stringify({
model: "google/gemini-2.5-flash",
messages: [
{
role: "user",
content: [
{ type: "text", text: "Extract all visible text from this image." },
{
type: "image_url",
image_url: { url: imageDataUrl },
},
],
},
],
temperature: 0,
}),
});
const json = await res.json();
const content = json?.choices?.[0]?.message?.content;
Fetch: image generation
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": process.env.OPENROUTER_SITE_URL || "http://localhost:3000",
"X-OpenRouter-Title": process.env.OPENROUTER_APP_NAME || "My App",
},
body: JSON.stringify({
model: "google/gemini-3.1-flash-image-preview",
messages: [
{
role: "user",
content: "Generate a clean product-style illustration of a glass teacup on a plain background.",
},
],
modalities: ["image", "text"],
image_config: { size: "1024x1024" },
}),
});
const json = await res.json();
const imageUrl = json?.choices?.[0]?.message?.images?.[0]?.image_url?.url;
Fetch: PDF input with file-parser
const res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`,
"Content-Type": "application/json",
"HTTP-Referer": process.env.OPENROUTER_SITE_URL || "http://localhost:3000",
"X-OpenRouter-Title": process.env.OPENROUTER_APP_NAME || "My App",
},
body: JSON.stringify({
model: "google/gemini-2.5-flash",
messages: [
{
role: "user",
content: [
{ type: "text", text: "Extract the invoice totals as JSON." },
{
type: "file",
file: {
filename: "invoice.pdf",
file_data: pdfDataUrl,
},
},
],
},
],
plugins: [
{
id: "file-parser",
pdf: { engine: "pdf-text" },
},
],
response_format: { type: "json_object" },
temperature: 0,
}),
});
Workflow
-
Check the docs before making non-trivial changes.
- Run
scripts/check_openrouter_docs.py --quickwhen accuracy matters or the integration seems stale. - If the script flags warnings, read
references/docs-check-workflow.mdand browse only the flagged official pages. - Reconcile templates, headers, and parameter usage with the current docs before coding.
- Run
-
Keep secrets server-side.
- Do not expose
OPENROUTER_API_KEYin browser code. - Put a server route in front of OpenRouter for model discovery and chat calls.
- Set
HTTP-RefererandX-OpenRouter-Titleheaders when the app has a stable URL and title. - Do not forward arbitrary user-supplied
http(s)asset URLs straight to OpenRouter. Fetch trusted assets server-side and convert them todata:URLs, or enforce an explicit host allowlist such asOPENROUTER_ALLOWED_REMOTE_ASSET_HOSTS.
- Do not expose
-
Install a starter instead of retyping boilerplate.
- Use
scripts/install_template.shwith--template nextjsor--template express. - Override base path and env var names at install time when the target project already has conventions.
- Copy shared helpers, streaming UI example, and test fixtures with the template.
- Use
-
Decide what you are integrating.
- Catalog, providers, free-model filters, or generation cost lookup: read
references/catalogs-and-costs.md. - Model catalog or picker: read
references/models-and-ui.md. - Model selection, provider filters, or fallback policy that should be production-friendly: read
references/catalog-routing-best-practices.md. - Text, image analysis, image generation, or PDF inference: read
references/requests-and-responses.md. - End-to-end image asset workflows such as icons, OG images, preview, and storage: read
references/image-generation-best-practices.md. - Tool calling or an agentic loop: read
references/tools-and-function-calling.md. - Tool reliability or structured-output extraction that should survive production use: read
references/tool-calling-and-structured-output-best-practices.md. - Routing and failover policy: read
references/routing-and-fallbacks.md. - Logging, generation audit, and cost observability: read
references/operations-and-observability-best-practices.md. - Common failures: read
references/troubleshooting.md.
- Catalog, providers, free-model filters, or generation cost lookup: read
-
Discover models before choosing one.
- Use
GET /api/v1/modelsfor the full catalog. - Use
GET /api/v1/models/userwhen user or provider preferences matter. - Use
GET /api/v1/providerswhen provider routing, privacy, or availability matter in the UI. - Use
GET /api/v1/models/:author/:slug/endpointswhen you need endpoint-level provider data. - Derive free-model lists by filtering zero-priced entries from the model catalog.
- Store model
id, not modelname. - Filter by
architecture.input_modalitiesandarchitecture.output_modalitiesfirst; use name heuristics only as fallback.
- Use
-
Build requests in OpenAI-compatible format.
- Send text-only prompts as normal chat
messages. - Send images with
contentarrays containing atextpart and one or moreimage_urlparts. - Generate images by sending normal chat
messagesplusmodalitiesthat includeimage; passimage_configwhen output settings matter. - Choose image-output models from the live catalog by checking
architecture.output_modalitiesforimage. - Send PDFs with a
filecontent part and, when needed, thefile-parserplugin. - Default to
data:URLs for private uploads and for any untrusted remote asset. Use remotehttp(s)URLs only from explicit allowlisted hosts that you control or trust. - Keep
toolsin every tool-calling request, including follow-up calls that only send tool results.
- Send text-only prompts as normal chat
-
Choose response handling deliberately.
- For plain prose, read
choices[0].message.content. - For image generation, read
choices[0].message.images. - For structured data, prefer
response_format: { type: "json_schema", ... }when the model supportsstructured_outputs. - Fall back to
response_format: { type: "json_object" }when you need JSON but not full schema enforcement. - Use
assets/shared/parse-openrouter-response.tsfor robust text, generated-image, and tool-call extraction. - Use
assets/shared/stream-openrouter-sse.tsfor streaming. - Use
assets/shared/validate-structured-output.tswithzodfor type-safe parsing. - Use
assets/nextjs-template/components/openrouter-streaming-chat.tsxas the end-to-end streaming UI example.
- For plain prose, read
-
Reuse parsed PDFs when iterating.
- If a PDF request returns assistant
annotations, pass them back on follow-up requests to avoid reparsing cost and latency. - Preserve the original file message and append the annotated assistant message before the next user turn.
- If a PDF request returns assistant
-
Verify the integration.
- Run
assets/tests/smoke-curl.shfor text, structured JSON, tools, image analysis, image generation, and PDF cases. - Run
assets/tests/smoke-catalogs.shfor models, user models, providers, free-model filtering, image-output model discovery, and generation cost lookup. - Check both successful responses and non-2xx OpenRouter errors.
- Log returned
usage,cost, finish reason, resolved model id, and generation id for debugging. - Fetch
GET /api/v1/generation?id=...when exact post-hoc cost or token accounting matters.
- Run
Resources
- Docs-check script:
scripts/check_openrouter_docs.py - Installer script:
scripts/install_template.sh - Next.js starter:
assets/nextjs-template/ - Express starter:
assets/express-template/ - Shared TypeScript helpers:
assets/shared/ - Smoke tests and fixtures:
assets/tests/ - Catalog and cost helper:
assets/shared/openrouter-catalog-and-cost.ts - Image asset helper:
assets/shared/openrouter-generated-image-assets.ts - Node image persistence helper:
assets/shared/openrouter-generated-image-assets-node.ts - Catalogs, providers, free-model filters, and generation cost lookup:
references/catalogs-and-costs.md - Catalog and routing production rules:
references/catalog-routing-best-practices.md - Image generation usage, preview, storage, icons, and OG workflows:
references/image-generation-best-practices.md - Tool calling and structured-output production rules:
references/tool-calling-and-structured-output-best-practices.md - Operations, logging, and generation audit rules:
references/operations-and-observability-best-practices.md
Quality Rules
- Prefer a server proxy with caching for model lists.
- Keep model picker UIs searchable; plain
<select>breaks down on large catalogs. - Use
architecture.input_modalitiesandarchitecture.output_modalitiesas the primary capability signals. - Treat pricing fields as strings from the API; convert explicitly if you need numeric math.
- Persist generation ids anywhere later cost inspection matters.
- Prefer exact generation lookup over estimated UI-only price math when a completed request id exists.
- Include the organization prefix in model ids such as
openai/gpt-4o-mini. - Expect
choicesto always be an array. - For streaming, expect SSE comment lines and ignore them.
- For PDFs, choose
pdf-textfor clean text PDFs,mistral-ocrfor scanned or image-heavy PDFs, andnativeonly when the selected model supports file input natively. - Do not assume every model supports
response_format,structured_outputs,tools, or every OpenAI parameter; checksupported_parametersfirst. - When a request depends on specific parameters such as tools or
response_format, preferprovider.require_parameters: true.
References
- Model discovery, caching, and picker UX:
references/models-and-ui.md - Catalogs, providers, free-model filters, and generation cost lookup:
references/catalogs-and-costs.md - Catalog and routing production rules:
references/catalog-routing-best-practices.md - Image generation usage, preview, storage, icons, and OG workflows:
references/image-generation-best-practices.md - Text, image analysis, image generation, and PDF request patterns plus response handling:
references/requests-and-responses.md - Tool calling and agentic loops:
references/tools-and-function-calling.md - Tool calling and structured-output production rules:
references/tool-calling-and-structured-output-best-practices.md - Model routing, provider routing, and fallbacks:
references/routing-and-fallbacks.md - Operations, logging, and generation audit rules:
references/operations-and-observability-best-practices.md - Troubleshooting and failure diagnosis:
references/troubleshooting.md - Docs-check workflow:
references/docs-check-workflow.md