How to Integrate OpenRouter AI Models in ASP.NET Core 10 Using C# – Multi-Model API Guide (2026)
Switching a chatbot to another model is easy until its context length, price, or output behavior changes. A fallback can improve availability, but it can also route a request to a provider your privacy policy did not approve.
This guide integrates OpenRouter with ASP.NET Core 10 using C# and IHttpClientFactory. It keeps the key on the server, defines an ordered model list in configuration, and returns the actual model identifier so callers can see what served the request.
How does model fallback work?
The OpenRouter Chat Completions endpoint is POST https://openrouter.ai/api/v1/chat/completions. It accepts a bearer token and an ordered models array for fallback. This is distinct from routing among providers that serve the same model. A fallback can change capabilities, provider, latency and pricing. Approve every model in the fallback chain. See the OpenRouter API overview and model fallback documentation.
| Routing choice | Use when | Tradeoff |
|---|---|---|
| One model | Stable evaluation and predictable features | Less flexibility during outages |
| Ordered models | Equivalent tasks can tolerate another model | Possible quality and cost differences |
| Provider restrictions | Data handling or geography matters | Reduced provider choice |
Build the client and endpoint
Install .NET 10 and create a web project with the files below. Set Router__Key through process secrets. Set Router__Primary and Router__Fallback to identifiers available to your key. Inspect the OpenRouter model catalog before pinning a pair. Model aliases can change their target over time. The demo accepts no model ID from callers and must be bound to loopback. Add authorization and quota limits before any shared deployment.
The client disables redirects and applies a 25-second request budget. The API bounds prompt and completion sizes and returns a small JSON contract. A provider 429 returns 429 to the caller, whereas other upstream errors become generic 502 responses. Log the provider status and trace ID separately from the prompt. Apply a controlled retry policy only where a repeated model request and possible repeated charge are acceptable.
Send a chat request
Expect {"model":"<actual model>","text":"<reply>"}. Empty input should return 400 before calling OpenRouter. Test a forced upstream 429 with a fake handler rather than deliberately exhausting a real quota. For fallback testing, use a disposable account and approved model pair. Check the actual model returned. Do not assume the fallback was used just because the call took longer.
The C# project compiled on .NET 10. No live OpenRouter model, billing, or fallback call was made.
Streaming and cost controls
The endpoint above uses non-streaming JSON. For supported streaming calls, set stream=true, use HttpCompletionOption.ResponseHeadersRead, and parse SSE. Handle comment frames and terminal error data. A stream can fail after returning text. Do not replay automatically after any output without an application-level recovery policy. See the ASP.NET PB OpenAI integration guide for the general server-side credential pattern.
Budget tokens and money separately. A 350-token completion cap does not cap input length in tokens or the provider’s per-token price. Evaluate every candidate for tool support, context and response shape. If the workload requires identical structured output, run both models through the same validation fixture and reject invalid content. Restrict provider selection according to your data policy. Track latency and usage by served model, not by configured primary.
| Symptom | Check |
|---|---|
| 401 upstream | Key and bearer header |
| 429 | Account quota, provider limit, and retry hints |
| Fallback never appears | Availability and model routing settings |
| Unexpected bill | Actual model, input and output tokens, and retries |
| Stream arrives in a burst | Proxy buffering and SSE parsing |
FAQ and references
Should the browser call OpenRouter directly? Keep a shared application key behind your server. Apply per-user authorization and quota before forwarding prompts.
Are all fallback models interchangeable? No. Verify tool, modality, output format and context support independently.
What should I store for diagnostics? Record the actual model, latency, outcome, token usage where supplied, and a trace ID. Avoid storing raw prompts by default.
Start with a narrow model pair and verify both on representative inputs before enabling fallback in production.
Comments
Post a Comment