<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BoostRail</title>
    <description>The latest articles on DEV Community by BoostRail (boostrail).</description>
    <link>https://dev.to/boostrail</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14230%2Ff72d3897-530b-4791-af37-1442c99d1f86.png</url>
      <title>DEV Community: BoostRail</title>
      <link>https://dev.to/boostrail</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/boostrail"/>
    <language>en</language>
    <item>
      <title>BYOK: Using Your Own Provider Keys Behind One LLM API</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:34:11 +0000</pubDate>
      <link>https://dev.to/boostrail/byok-using-your-own-provider-keys-behind-one-llm-api-a11</link>
      <guid>https://dev.to/boostrail/byok-using-your-own-provider-keys-behind-one-llm-api-a11</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/byok-own-provider-keys/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on August 5, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Teams adopting a multi-model API usually hit the same procurement question: "We already have contracts and negotiated prices with our model providers — why would we re-buy inference through a middleman?"&lt;/p&gt;

&lt;p&gt;Bring Your Own Key (BYOK) is the answer to exactly that. You keep your provider accounts; one API in front of them keeps the integration simple.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;With BYOK on &lt;a href="https://boostrail.com/byok/" rel="noopener noreferrer"&gt;BoostRail&lt;/a&gt;, an organization stores its own provider API keys with the platform. When a request targets a model covered by one of those keys, BoostRail serves it &lt;strong&gt;with your key against the lab's official endpoint&lt;/strong&gt;. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inference charges land on your own provider account&lt;/strong&gt;, at your contract prices — not on platform credit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request data stays within your existing provider agreements&lt;/strong&gt;, which matters where procurement or compliance requires a direct provider relationship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your application never touches the stored keys&lt;/strong&gt; — it keeps using one BoostRail API key, and the provider keys stay on the platform side.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What BoostRail still handles: the single OpenAI-compatible endpoint, one key for your application, the unified catalog, and &lt;strong&gt;platform fallback&lt;/strong&gt;. If your own key fails, runs out of provider credit or is rate-limited, the request can continue on platform routes of the same model instead of failing; that needs a balance. Where data boundaries are strict, platform routes can be switched off per lab, and requests then fail rather than fall back.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;p&gt;The free plan includes &lt;strong&gt;1,000,000 BYOK requests per month&lt;/strong&gt;. Paid plans raise the monthly quota and the number of labs you can connect, for a flat monthly fee. Inference itself is billed by your provider, so BYOK is counted in requests rather than as a percentage of what the usage would cost. When the monthly quota runs out, requests switch to platform routes at the published platform prices until the quota resets on the 1st of the month (UTC); models that run only on your own key pause until then.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zero lock-in, by construction
&lt;/h2&gt;

&lt;p&gt;Lock-in is the standard objection to gateways, and BYOK inverts it: the provider keys are yours, and your application talks to an OpenAI-compatible endpoint. Leaving is pointing &lt;code&gt;base_url&lt;/code&gt; back at a provider's official endpoint. There is no proprietary SDK and no custom protocol.&lt;/p&gt;

&lt;h2&gt;
  
  
  When BYOK covers a model — and when it doesn't
&lt;/h2&gt;

&lt;p&gt;BYOK needs two things: the lab is on the supported list for your plan, and the model can be served from that lab's official endpoint. Models from labs without a public official API run on platform routes only. The current lab list and per-plan quotas are on the &lt;a href="https://boostrail.com/byok/" rel="noopener noreferrer"&gt;BYOK page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typical setups
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contract-price teams&lt;/strong&gt;: inference on negotiated provider prices, BoostRail for the single API and usage records, platform fallback for spillover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance-bound teams&lt;/strong&gt;: requests to sensitive models pinned to their own provider agreement with platform routes switched off for that lab, everything else on platform routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-split teams&lt;/strong&gt;: frontier models via their own keys (where contracts are), long-tail models on platform credit — one BoostRail bill alongside unchanged provider bills.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BYOK is set up in the console at &lt;a href="https://app.boostrail.com" rel="noopener noreferrer"&gt;app.boostrail.com&lt;/a&gt;; plans and the supported lab list are on the &lt;a href="https://boostrail.com/byok/" rel="noopener noreferrer"&gt;BYOK page&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Hidden Complexity of Multi-API AI Integrations</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:33:34 +0000</pubDate>
      <link>https://dev.to/boostrail/the-hidden-complexity-of-multi-api-ai-integrations-1hca</link>
      <guid>https://dev.to/boostrail/the-hidden-complexity-of-multi-api-ai-integrations-1hca</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/hidden-complexity-multi-api-ai-integrations/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on August 5, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first LLM integration looks deceptively simple: one HTTP &lt;code&gt;POST&lt;/code&gt; to a &lt;code&gt;/v1/chat/completions&lt;/code&gt; endpoint and you have working intelligence in under an hour. The trouble starts when the application matures. To survive provider outages, control inference cost, or use each model where it is strongest, teams inevitably go multi-provider — and what was one API call becomes a maze of incompatible schemas, divergent auth models, backoff logic, fragile streaming parsers and fragmented billing.&lt;/p&gt;

&lt;p&gt;These are the four failure modes that show up in practice, and the architectural pattern that removes them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Schema drift and payload normalization
&lt;/h2&gt;

&lt;p&gt;Providers do not agree on request or response formats. Many advertise "OpenAI compatibility", but the payload variances are real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI-style APIs&lt;/strong&gt; put system instructions inside the &lt;code&gt;messages&lt;/code&gt; array as &lt;code&gt;"role": "system"&lt;/code&gt;; temperature ranges 0.0–2.0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anthropic's native API&lt;/strong&gt; pulls the system prompt out into a top-level &lt;code&gt;system&lt;/code&gt; parameter, accepts only &lt;code&gt;user&lt;/code&gt;/&lt;code&gt;assistant&lt;/code&gt; roles, caps temperature at 1.0, and requires &lt;code&gt;max_tokens&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google's native Gemini API&lt;/strong&gt; uses &lt;code&gt;contents&lt;/code&gt; instead of &lt;code&gt;messages&lt;/code&gt;, &lt;code&gt;"role": "model"&lt;/code&gt; instead of &lt;code&gt;"role": "assistant"&lt;/code&gt;, and nests text in a &lt;code&gt;parts&lt;/code&gt; array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Swap a payload from one to another without a serialization layer and the destination rejects it with a 400.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;OpenAI-style&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-5.5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a precise JSON extractor."&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Extract data from this text..."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Anthropic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;native&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;—&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;top-level&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;system&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;prompt,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;max_tokens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;required&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-sonnet-5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are a precise JSON extractor."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Extract data from this text..."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tool calling cuts deeper. Providers enforce JSON Schema with different strictness: one rejects a definition over a missing optional field, another silently drops constraints it does not support — and malformed arguments flow into your backend. Without a normalization layer you end up maintaining separate serializers, parsers and schema validators for every vendor in the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Rate limits, retries and transient outages
&lt;/h2&gt;

&lt;p&gt;Classic microservices fail predictably: 500 means server error, 503 means try later. LLM APIs throttle on two independent dimensions — requests per minute and tokens per minute — so an endpoint can return 429 during a traffic spike even when your monthly spend has plenty of headroom.&lt;/p&gt;

&lt;p&gt;A naive fixed-interval retry loop makes a 429 worse: every retry counts against the same window, and the violation compounds into an extended lockout. The standard remedy is exponential backoff with full jitter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_backoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;32.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Exponential backoff with full randomized jitter.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;calculated_delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_delay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_delay&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;# Full jitter prevents a thundering herd of synchronized retries
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;calculated_delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Backoff alone does not cover extended outages — that needs failover to another provider, and model failover is not transparent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context window mismatch.&lt;/strong&gt; Fail over from a 200K-token model to a 32K-token model without validating prompt size first and you trade a 429 for a truncation error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt sensitivity.&lt;/strong&gt; A prompt tuned for one model family can produce unstructured output on another without adaptation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mid-stream disconnects.&lt;/strong&gt; SSE streams drop mid-response; unlike a plain HTTP error, the client is left holding a partial completion and must re-stitch or continue the prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Production setups pair health checks with circuit breakers: after consecutive failures the breaker opens, traffic routes to a backup line, and the primary is re-tested after a cooldown.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Key sprawl and billing fragmentation
&lt;/h2&gt;

&lt;p&gt;Beyond code mechanics, direct multi-provider integration is an operational tax. Separate SDKs mean separate secrets in every environment; rotating a key or scoping team access is a chore repeated across as many consoles as you have vendors. Each provider bills on its own cycle and prepayment model, so finance reconciles four or five dashboards a month while engineering has no single view of token spend per feature. And one unhandled retry loop against a frontier-priced endpoint can burn serious money in minutes if no centralized budget guardrail exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The architecture that removes the problem
&lt;/h2&gt;

&lt;p&gt;Three patterns cover the design space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direct SDK integration&lt;/strong&gt; — fastest to start, but provider conditionals leak into business logic, failover is hardcoded, and every model swap touches application code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-house abstraction layer&lt;/strong&gt; — decouples the app, but you now own a normalization-and-failover codebase that must track every provider API change, forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified gateway&lt;/strong&gt; — one OpenAI-compatible endpoint in front of all providers; normalization, failover and billing consolidation happen below your code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most teams the gateway is the pattern that scales. Pointing your HTTP client at &lt;a href="https://boostrail.com" rel="noopener noreferrer"&gt;BoostRail&lt;/a&gt; gives you one OpenAI-compatible API for {{MODELS}} text, image and video models from {{LABS}} labs. Request formats are normalized, and when a route for a model fails, the request moves to another route of the same model before any data reaches you — it never switches to a different model, so the context-window and prompt mismatches above don't arise. Once data has started streaming, the request stays on its route. With &lt;a href="https://boostrail.com/byok/" rel="noopener noreferrer"&gt;BYOK&lt;/a&gt;, inference can bill to your own provider contracts, with platform routes of the same model as fallback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;

&lt;span class="c1"&gt;# Switching models is a one-string change.
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.boostrail.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_BOOSTRAIL_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# or gpt-5.5, gemini-3.1-pro, deepseek-v4-pro...
&lt;/span&gt;    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain circuit breaker patterns in microservices.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A gateway adds a network hop. For most workloads that is small next to generation time, which runs to hundreds or thousands of milliseconds; measure it on your own traffic before you cut over.&lt;/p&gt;

&lt;h2&gt;
  
  
  A reliability checklist
&lt;/h2&gt;

&lt;p&gt;Before scaling a production AI application across providers, verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema abstraction&lt;/strong&gt; — provider payload formats isolated behind one OpenAI-compatible layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adaptive backoff&lt;/strong&gt; — exponential backoff with full jitter on 429s, never fixed-interval retries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated failover&lt;/strong&gt; — health checks and circuit breakers that account for context-window and prompt differences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stream recovery&lt;/strong&gt; — SSE parsers that survive abrupt disconnects without unhandled exceptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified telemetry and billing&lt;/strong&gt; — token spend, budgets and API health visible in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full model list is in the &lt;a href="https://boostrail.com/models/" rel="noopener noreferrer"&gt;BoostRail catalog&lt;/a&gt;; an API key takes a minute at &lt;a href="https://app.boostrail.com" rel="noopener noreferrer"&gt;app.boostrail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Migrating to an OpenAI-Compatible API: a Practical Guide</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:33:28 +0000</pubDate>
      <link>https://dev.to/boostrail/migrating-to-an-openai-compatible-api-a-practical-guide-b9k</link>
      <guid>https://dev.to/boostrail/migrating-to-an-openai-compatible-api-a-practical-guide-b9k</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/openai-compatible-api-migration-guide/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on August 5, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;"OpenAI-compatible" is the most load-bearing phrase in AI infrastructure, and it means something concrete: a service that accepts the same requests and returns the same responses as OpenAI's API — same endpoints, same JSON shapes, same streaming format. Your existing OpenAI SDK code works against it after changing exactly one thing: the base URL.&lt;/p&gt;

&lt;p&gt;That's why the OpenAI format has become the industry's common protocol, the way S3's API became the standard for object storage. This guide walks through what a migration actually involves — which is less than you'd think — and the few places where checking first saves a surprise later.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line migration
&lt;/h2&gt;

&lt;p&gt;Both official OpenAI SDKs accept a &lt;code&gt;base_url&lt;/code&gt; (Python) / &lt;code&gt;baseURL&lt;/code&gt; (JavaScript) parameter. Point it at a compatible endpoint, swap the key, and everything else stays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Python — before and after
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_BOOSTRAIL_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.boostrail.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;   &lt;span class="c1"&gt;# the only new line
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# any model in the catalog
&lt;/span&gt;    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// JavaScript / TypeScript&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_BOOSTRAIL_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.boostrail.com/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No new SDK, no new dependency, no request-shape changes. The same works for any framework that exposes a base-URL setting — LangChain, LlamaIndex, Vercel AI SDK and most others do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What carries over unchanged
&lt;/h2&gt;

&lt;p&gt;The point of compatibility is that the boring majority of your integration just works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chat completions&lt;/strong&gt; — &lt;code&gt;client.chat.completions.create&lt;/code&gt; with the full &lt;code&gt;messages&lt;/code&gt; array semantics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming&lt;/strong&gt; — server-sent events arrive in the same chunk format, so existing stream parsers keep working&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool calling&lt;/strong&gt; — &lt;code&gt;tools&lt;/code&gt;, &lt;code&gt;tool_calls&lt;/code&gt;, content parts and streaming tool-call deltas work in the same format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model listing&lt;/strong&gt; — &lt;code&gt;/v1/models&lt;/code&gt; returns the catalog, so model pickers keep working&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One endpoint difference worth knowing about: an API can also expose other clients' &lt;em&gt;native&lt;/em&gt; protocols alongside the OpenAI surface. On &lt;a href="https://boostrail.com" rel="noopener noreferrer"&gt;BoostRail&lt;/a&gt;, Anthropic-protocol clients like Claude Code talk to &lt;code&gt;/v1/messages&lt;/code&gt; and Codex CLI talks to &lt;code&gt;/v1/responses&lt;/code&gt; — each client uses the protocol it was built for, with no local adapter. Details are on the &lt;a href="https://boostrail.com/openai-compatible-api/" rel="noopener noreferrer"&gt;OpenAI-compatible API page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check before you flip the switch
&lt;/h2&gt;

&lt;p&gt;Compatibility covers the protocol; a few behaviors legitimately differ per model and are worth a look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model names.&lt;/strong&gt; &lt;code&gt;gpt-4o&lt;/code&gt;-era strings won't name the same model everywhere. Check the &lt;a href="https://boostrail.com/models/" rel="noopener noreferrer"&gt;catalog&lt;/a&gt; and pick explicitly — switching later is a one-string change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parameter ranges.&lt;/strong&gt; Temperature runs 0–2 in the OpenAI convention but 0–1 on Anthropic's API. BoostRail passes the value on as you send it rather than rescaling it, so if your product exposes a temperature slider, check its range against the models you call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token limits.&lt;/strong&gt; Different models have different context windows and default output caps. If you hard-coded &lt;code&gt;max_tokens&lt;/code&gt; for one model, confirm it fits the new one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt behavior.&lt;/strong&gt; A prompt tuned hard against one model may need a round of adjustment on another. Migrate the plumbing first, then A/B the prompts — don't change both at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Migrating coding agents
&lt;/h2&gt;

&lt;p&gt;Coding agents migrate the same way, usually via environment variables rather than code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Claude Code — ~/.claude/settings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.boostrail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-sonnet-5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_ATTRIBUTION_HEADER"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cline, OpenCode, Continue and Aider take a standard OpenAI-compatible provider block. Per-tool walkthroughs live on the &lt;a href="https://boostrail.com/coding/" rel="noopener noreferrer"&gt;coding tools page&lt;/a&gt;, and the rate-limit reasons agents benefit most from this migration are covered in &lt;a href="https://www.boostrail.com/blog/coding-agent-rate-limits/" rel="noopener noreferrer"&gt;Coding Agents and Rate Walls&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollback is also one line
&lt;/h2&gt;

&lt;p&gt;The migration is symmetric: point &lt;code&gt;base_url&lt;/code&gt; back at the provider's official endpoint and you've left. No proprietary SDK and no export process.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Will responses be byte-identical to OpenAI's?&lt;/strong&gt;&lt;br&gt;
The JSON structure is identical; the content depends on which model you call. Field-level extras (like provider-specific metadata) may appear but won't break standard parsers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to migrate everything at once?&lt;/strong&gt;&lt;br&gt;
No. Because both sides speak the same protocol, you can run a percentage of traffic through the new endpoint, compare, and cut over gradually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about my fine-tuned or provider-specific models?&lt;/strong&gt;&lt;br&gt;
Models that exist only in your own provider account, such as fine-tunes, are not in the catalog, so BoostRail can't serve them — keep calling those on the provider's own endpoint. If you have contract prices for catalog models, BYOK runs them on your own provider keys; see &lt;a href="https://www.boostrail.com/blog/byok-own-provider-keys/" rel="noopener noreferrer"&gt;the BYOK guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>openai</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What Is an LLM Gateway? A Plain-English Guide</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:32:51 +0000</pubDate>
      <link>https://dev.to/boostrail/what-is-an-llm-gateway-a-plain-english-guide-404o</link>
      <guid>https://dev.to/boostrail/what-is-an-llm-gateway-a-plain-english-guide-404o</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/what-is-an-llm-gateway/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on August 5, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An LLM gateway is a single entry point that sits between your application and every AI model provider you use. Your code talks to one API; the gateway talks to OpenAI, Anthropic, Google, DeepSeek and the rest, translating formats, routing traffic and consolidating billing along the way.&lt;/p&gt;

&lt;p&gt;That's the whole idea. The rest of this guide explains why that one layer has become standard kit for production AI applications, what varieties exist, and how to decide whether you need one at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problems it solves
&lt;/h2&gt;

&lt;p&gt;Teams rarely adopt a gateway on day one — they adopt it after hitting some combination of four walls. We've written up the engineering detail in &lt;a href="https://www.boostrail.com/blog/hidden-complexity-multi-api-ai-integrations/" rel="noopener noreferrer"&gt;The Hidden Complexity of Multi-API AI Integrations&lt;/a&gt;; the short version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every provider speaks a different dialect.&lt;/strong&gt; All the major APIs handle message formats, system prompts and parameters slightly differently. Code written for one breaks against another. A gateway normalizes everything behind one format — in practice, the OpenAI format, which has become the de-facto standard the way S3's API did for storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits and outages don't announce themselves.&lt;/strong&gt; Providers throttle by requests &lt;em&gt;and&lt;/em&gt; tokens per minute, and even top-tier models have bad days. A gateway tracks the health of each route and moves failed requests automatically, so fewer errors reach your users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keys and bills multiply.&lt;/strong&gt; Four providers means four secrets to rotate, four dashboards to reconcile, four places spending can leak. A gateway collapses that to one key and one bill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switching models means touching code.&lt;/strong&gt; Without a gateway, trying a new model is an integration project. With one, it's changing a model name in a string.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The three kinds of gateway
&lt;/h2&gt;

&lt;p&gt;The market has sorted itself into three shapes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted open source.&lt;/strong&gt; You run the router on your own infrastructure — maximum control and data residency, in exchange for owning deployment, upgrades and provider-API chasing forever. LiteLLM is the best-known example.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted multi-model gateways.&lt;/strong&gt; A managed service exposes one OpenAI-compatible endpoint backed by a large catalog; routing, failover and billing consolidation happen behind it. &lt;a href="https://boostrail.com" rel="noopener noreferrer"&gt;BoostRail&lt;/a&gt; is in this camp: {{MODELS}} text, image and video models from {{LABS}} labs behind one key, with every per-token price published.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability- and governance-first platforms.&lt;/strong&gt; Products whose center of gravity is logging, cost analytics, access policies or guardrails, with routing attached. Helicone and Portkey lead here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These categories overlap at the edges — most products do some of everything — but knowing a product's center of gravity is the fastest way to predict where it will serve you well.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose: seven questions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Am I using, or likely to use, more than one model?&lt;/strong&gt; If genuinely no, a gateway is optional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What happens to my product when my provider has an outage?&lt;/strong&gt; If the answer is "it goes down," failover is your first requirement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Must request data stay inside my infrastructure?&lt;/strong&gt; Yes → self-hosted. No → hosted saves you the operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How does the gateway charge?&lt;/strong&gt; Compare per-token prices against the official list, top-up and payment fees, and any platform or subscription fee. At scale the differences add up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I bring my own provider contracts?&lt;/strong&gt; If you have negotiated prices, BYOK support — using your own provider keys through the gateway — protects them. Check the free allowance; on &lt;a href="https://boostrail.com/byok/" rel="noopener noreferrer"&gt;BoostRail's free plan&lt;/a&gt; it's 1M BYOK requests a month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What modalities do I need?&lt;/strong&gt; Text is table stakes; image input is common; image and video generation vary more between platforms — check the &lt;a href="https://boostrail.com/models/" rel="noopener noreferrer"&gt;catalog&lt;/a&gt; covers what your roadmap needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How hard is leaving?&lt;/strong&gt; With an OpenAI-compatible gateway, leaving is changing one URL back. A proprietary SDK requirement makes it harder.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does a gateway slow my requests down?&lt;/strong&gt;&lt;br&gt;
It adds a network hop. For most workloads that is small next to generation time, which runs to hundreds or thousands of milliseconds; measure it on your own traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is an LLM gateway the same as an API gateway?&lt;/strong&gt;&lt;br&gt;
Same concept, specialized differently. Classic API gateways (Kong, Cloudflare) manage generic HTTP traffic; LLM gateways add model-specific work — payload translation between provider dialects, token-aware rate limit handling, model routing and failover, per-token cost tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need one for a prototype?&lt;/strong&gt;&lt;br&gt;
No — one provider, one SDK is the right way to start. The gateway earns its place when you add a second model, hit your first rate limit, or need the bill explained. Since adopting one is a &lt;code&gt;base_url&lt;/code&gt; change, deferring the decision costs nothing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>architecture</category>
    </item>
    <item>
      <title>LLM API Fallback: Keep Your App Up When a Model Fails</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:32:45 +0000</pubDate>
      <link>https://dev.to/boostrail/llm-api-fallback-keep-your-app-up-when-a-model-fails-5ni</link>
      <guid>https://dev.to/boostrail/llm-api-fallback-keep-your-app-up-when-a-model-fails-5ni</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/llm-api-fallback/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on October 16, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An LLM API fallback plan decides what your application does when a model call fails: wait and retry, send the same request somewhere else, or ask a different model. Without one, a provider's bad hour becomes your outage. With a careless one, a retry loop can double your bill or send a user two half-answers. This guide covers the failures that happen in practice, the patterns that handle them, a short Python implementation, and which parts a multi-route API already takes off your hands.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually fails in production
&lt;/h2&gt;

&lt;p&gt;LLM calls fail in a handful of distinct ways, and each needs a different response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits (429).&lt;/strong&gt; Too many requests or tokens per minute for an account, a key or a model. Usually temporary, and the response often says how long to wait.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server errors (500, 502, 503).&lt;/strong&gt; The model's service is overloaded or broken. Often temporary, sometimes for hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeouts (504 or a client timeout).&lt;/strong&gt; No answer within the time allowed. A timeout is not always an outage: when we sent a long coding prompt to two reasoning models on 16 October 2026 without streaming, neither had finished within the 180 seconds limit for non-streaming requests, and both returned &lt;code&gt;provider_timeout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Broken streams.&lt;/strong&gt; The connection drops after part of the answer has arrived.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request errors (400).&lt;/strong&gt; The request itself is wrong: an unknown model, a parameter the model does not accept, input longer than its context window. Retrying the same request gives the same error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account errors (401, 402, 403).&lt;/strong&gt; A bad key, an empty balance, a disabled key. Retrying makes no difference until someone fixes the account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Retry, failover and fallback are different things
&lt;/h2&gt;

&lt;p&gt;The three words get used loosely. Keeping them apart makes the design easier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retry&lt;/strong&gt; sends the same request to the same place again after a pause. It fixes brief overloads and rate limits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failover&lt;/strong&gt; sends the same request for the same model to another place that serves it: another region, deployment or provider. The answer should be equivalent, because the model is the same.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback&lt;/strong&gt; sends the request to a different model. It keeps the application answering when a model is unavailable everywhere, at the price of a different answer: other strengths, other formatting, sometimes other tool-calling habits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Retry and failover are safe to automate. Fallback to another model is a product decision, because users may notice the change.&lt;/p&gt;

&lt;h2&gt;
  
  
  LLM API fallback patterns that work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Classify the error before acting.&lt;/strong&gt; A small table in code prevents the two classic mistakes: retrying requests that can never succeed, and giving up on errors that would clear in seconds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Retry&lt;/th&gt;
&lt;th&gt;Fail over&lt;/th&gt;
&lt;th&gt;Fall back to another model&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;429 rate limit&lt;/td&gt;
&lt;td&gt;Yes, after the wait it asks for&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;If it persists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500, 502, 503&lt;/td&gt;
&lt;td&gt;Yes, with backoff&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;If it persists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;504 or client timeout&lt;/td&gt;
&lt;td&gt;Stream instead, or raise the limit&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;If it persists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400 bad request&lt;/td&gt;
&lt;td&gt;No; fix the request&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Only if another model accepts the request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401, 402, 403&lt;/td&gt;
&lt;td&gt;No; fix the account&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. Back off exponentially, with jitter, and respect &lt;code&gt;retry-after&lt;/code&gt;.&lt;/strong&gt; Doubling the wait between attempts and adding a random offset stops many clients from retrying in lockstep. When the response carries &lt;code&gt;retry-after&lt;/code&gt;, wait at least that long.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Stream long generations and set timeouts in layers.&lt;/strong&gt; A connect timeout catches a dead network. A first-token timeout catches a stuck request. A total timeout stops a runaway answer. For prompts that make a model think for minutes, streaming keeps the connection alive and lets the client see progress, where a non-streaming request would hit a time limit first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Keep the fallback chain short and tested.&lt;/strong&gt; Two or three models, chosen in advance, each tested with your real prompts. A chain of models nobody has tried with your prompts is a guess, not a plan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Stop sending traffic to a target that keeps failing.&lt;/strong&gt; After repeated failures, pause requests to that model or endpoint for a short time instead of letting every request discover the same outage. This is the circuit breaker pattern, and it saves both latency and money during an incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Do not silently retry a stream the user is already reading.&lt;/strong&gt; If text has reached the user and the stream breaks, a fresh request produces a different answer, not a continuation. Show what arrived, mark it as incomplete, and offer a retry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Log the request id.&lt;/strong&gt; Every failed call should record the model, the error code and the request id. That turns "the AI was down this morning" into something support can trace.&lt;/p&gt;

&lt;h2&gt;
  
  
  A minimal implementation in Python
&lt;/h2&gt;

&lt;p&gt;The OpenAI Python SDK already retries connection errors, 408, 409, 429 and 5xx responses with exponential backoff, twice by default, as its &lt;a href="https://github.com/openai/openai-python#retries" rel="noopener noreferrer"&gt;README&lt;/a&gt; describes. The code below adds the part it does not do: moving to the next model in a short chain when one stays unavailable, while letting request and account errors surface immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.boostrail.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;FALLBACK_CHAIN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kimi-k3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deepseek-v4.1-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;RETRYABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RateLimitError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APITimeoutError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIConnectionError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InternalServerError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;last_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;FALLBACK_CHAIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;RETRYABLE&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;last_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;last_error&lt;/span&gt;


&lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarise this incident report in three bullet points.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because every model sits behind the same endpoint and key, the chain is a list of strings. &lt;code&gt;reply.model&lt;/code&gt; tells you which model answered, which is worth logging and, in some products, showing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a multi-route API handles for you
&lt;/h2&gt;

&lt;p&gt;On BoostRail, failover for the same model happens before the response reaches you. The rules are published on &lt;a href="https://www.boostrail.com/docs/errors/" rel="noopener noreferrer"&gt;Errors and failover&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the route serving a request fails, BoostRail tries the same model on another route before anything is sent to you. It never switches to a different model.&lt;/li&gt;
&lt;li&gt;Server errors, rate limiting and the route refusing BoostRail's own access are moved to another route. Request errors and non-streaming timeouts are not, because another route would fail the same way.&lt;/li&gt;
&lt;li&gt;For streaming requests, if no first event arrives within 45 seconds, the request moves to the next route.&lt;/li&gt;
&lt;li&gt;Once any data has been sent to you, the request is not moved.&lt;/li&gt;
&lt;li&gt;When every route fails, you get the error from the last attempt, and the request is not charged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That changes what your own code needs to do. Failover for the same model is covered, so your retries mostly handle what is left: &lt;code&gt;429&lt;/code&gt; with &lt;code&gt;retry-after&lt;/code&gt;, and &lt;code&gt;502&lt;/code&gt; or &lt;code&gt;504&lt;/code&gt; after BoostRail has already tried its routes. Fallback to a different model stays your decision, because BoostRail does not make it for you. The price is the model's published price on the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;Models page&lt;/a&gt;, whichever route serves the request.&lt;/p&gt;

&lt;p&gt;For the broader integration problems that sit around fallback, such as schema differences and key sprawl, see &lt;a href="https://www.boostrail.com/blog/hidden-complexity-multi-api-ai-integrations/" rel="noopener noreferrer"&gt;The Hidden Complexity of Multi-API AI Integrations&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the fallback path
&lt;/h2&gt;

&lt;p&gt;A fallback path that has never run will fail the first time it matters. Three cheap ways to exercise it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Force a timeout.&lt;/strong&gt; Give the first model in the chain a client timeout far shorter than any real answer, and check that the second model answers and the log records why.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Break the network.&lt;/strong&gt; Point the client at an address that refuses connections and confirm the error is classified as retryable, not as a request error.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the account errors.&lt;/strong&gt; Use a disabled key in a test environment and confirm the application reports the problem instead of cycling through the chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run these whenever the chain changes, and watch the cost of a test run: every attempt that succeeds is billed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Should my application switch to a different model automatically?
&lt;/h3&gt;

&lt;p&gt;Only to models you have tested with your real prompts, and only when users can accept a different answer style. For internal tools and batch jobs, automatic fallback is usually fine. For customer-facing features, log or show which model answered.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long should LLM API timeouts be?
&lt;/h3&gt;

&lt;p&gt;Long enough for the slowest legitimate answer, and no longer. For anything that may reason or write at length, stream the response: on BoostRail a non-streaming request is limited to 180 seconds, while a stream only needs its first event within 45 seconds on each route.&lt;/p&gt;

&lt;h3&gt;
  
  
  Am I charged for failed attempts?
&lt;/h3&gt;

&lt;p&gt;On BoostRail, a request that fails on every route is not charged. Each retry or fallback your code sends is a new request, billed normally if it succeeds.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens if a stream breaks halfway?
&lt;/h3&gt;

&lt;p&gt;BoostRail does not move a request once data has been sent, because a new attempt would produce a different answer. The client should keep what arrived, mark it incomplete and offer a retry. Billing for interrupted streams follows the rule on the &lt;a href="https://www.boostrail.com/pricing/#pr-interrupted" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is retrying a 400 error ever useful?
&lt;/h3&gt;

&lt;p&gt;Only after changing the request: trimming the input to fit the context window, removing a parameter the model rejects, or choosing a model that accepts it. Sending the same request again returns the same error.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>python</category>
    </item>
    <item>
      <title>Chinese AI Models in 2026: Kimi, Qwen, GLM, DeepSeek</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:32:08 +0000</pubDate>
      <link>https://dev.to/boostrail/chinese-ai-models-in-2026-kimi-qwen-glm-deepseek-3dki</link>
      <guid>https://dev.to/boostrail/chinese-ai-models-in-2026-kimi-qwen-glm-deepseek-3dki</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/chinese-ai-models-2026/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on October 16, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Chinese AI models had a busy 2026: the major labs released new flagships aimed at coding and agent work, and most of them shipped with open weights and one-million-token context windows. For a team outside China, the practical questions are narrower than the headlines: which model is meant for which job, what it costs per token, and how to call several of them without opening an account with each lab.&lt;/p&gt;

&lt;p&gt;This guide covers seven labs whose current models are in the BoostRail catalog, as of 16 October 2026. Model descriptions come from each lab's own model card or announcement, linked in each section. Benchmark figures in those sources are reported by the labs themselves, so treat them as a starting point for your own tests. The capabilities described are the models' own; which input types a given API passes through depends on the provider serving it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Chinese AI models are worth evaluating
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open weights.&lt;/strong&gt; Most of the models below publish their weights, under licences that range from MIT and Apache 2.0 to each lab's own terms. That gives you a way out if you later want to host a model yourself, and it lets the wider community test the models independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long context as standard.&lt;/strong&gt; Kimi K3, Qwen3.8-Max, DeepSeek V4.1 Flash, MiniMax M3, MiMo V2.6 Pro and Hy4 preview all list a context window of about one million tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price.&lt;/strong&gt; On the BoostRail catalog, DeepSeek V4.1 Flash's output price is about one sixteenth of Claude Sonnet 5's. Prices vary: Kimi K3 costs more per output token than Claude Sonnet 5, while the other flagships in this guide cost less per output token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coding and agents first.&lt;/strong&gt; Nearly every flagship released this year leads its announcement with coding, tool use and long-running agent tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The seven labs and their current models
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Moonshot AI: Kimi
&lt;/h3&gt;

&lt;p&gt;Kimi K3 is a mixture-of-experts model with 2.8 trillion total parameters, 104 billion of them active per token, and a context window of 1,048,576 tokens. Moonshot's &lt;a href="https://huggingface.co/moonshotai/Kimi-K3" rel="noopener noreferrer"&gt;model card&lt;/a&gt; describes it as built for long-horizon coding, agentic knowledge work and reasoning, accepts text and images, and notes that it works best with Moonshot's own Kimi Code CLI. The weights are released under the Kimi K3 License. The catalog also carries the earlier &lt;code&gt;kimi-k2.6&lt;/code&gt;, &lt;code&gt;kimi-k2.7-code&lt;/code&gt; and &lt;code&gt;kimi-k2.5&lt;/code&gt; at lower prices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alibaba: Qwen
&lt;/h3&gt;

&lt;p&gt;Alibaba &lt;a href="https://www.alibabagroup.com/document-2021044032125272064" rel="noopener noreferrer"&gt;announced Qwen3.8-Max&lt;/a&gt; on 3 August 2026 as the most capable model in the Qwen series so far: about 2.4 trillion total parameters with roughly 95 billion active, a context window of up to one million tokens, and native image and video understanding. The announcement leads with autonomous coding and long-horizon execution, and said the weights would follow. Qwen's strength for builders is the ladder below the flagship: &lt;code&gt;qwen3.7-plus&lt;/code&gt;, &lt;code&gt;qwen3.7-flash&lt;/code&gt; and &lt;code&gt;qwen3-coder-flash&lt;/code&gt; cover cheaper tiers from the same lab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Z.ai: GLM
&lt;/h3&gt;

&lt;p&gt;GLM-5.3 is a 753-billion-parameter open-weights model. Z.ai's &lt;a href="https://huggingface.co/zai-org/GLM-5.3" rel="noopener noreferrer"&gt;model card&lt;/a&gt; calls it its most capable open-weights model for coding and says it shares GLM-5.2's base model, with the gains coming from post-training. The card highlights terminal and software-engineering benchmarks such as Terminal Bench and DeepSWE. For high-volume work, &lt;code&gt;glm-5.3-flash&lt;/code&gt; is the low-cost option.&lt;/p&gt;

&lt;h3&gt;
  
  
  DeepSeek
&lt;/h3&gt;

&lt;p&gt;DeepSeek V4.1 Flash arrived in September 2026 as the successor to V4 Flash. The &lt;a href="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash" rel="noopener noreferrer"&gt;model card&lt;/a&gt; describes 552 billion backbone parameters, with 8 billion active per token when reading input and 16 billion when writing output, a context of up to one million tokens, native image input, and an MIT licence. DeepSeek positions it for cost-efficient, input-heavy agent workloads. For how the V4 family split work between its two tiers, see &lt;a href="https://www.boostrail.com/blog/deepseek-v4-pro-vs-flash/" rel="noopener noreferrer"&gt;DeepSeek V4 Pro vs Flash&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  MiniMax
&lt;/h3&gt;

&lt;p&gt;MiniMax M3 has about 428 billion total parameters with about 23 billion active, and a one-million-token context. The &lt;a href="https://huggingface.co/MiniMaxAI/MiniMax-M3" rel="noopener noreferrer"&gt;model card&lt;/a&gt; emphasises long-horizon agent work and coding, and long-context efficiency from MiniMax's sparse attention design. It accepts text, images and video. The weights are under the MiniMax Community License. &lt;code&gt;minimax-m2.7&lt;/code&gt; is the cheaper previous generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Xiaomi: MiMo
&lt;/h3&gt;

&lt;p&gt;MiMo V2.6 Pro is Xiaomi's flagship: a sparse mixture-of-experts model with 1.02 trillion total and 42 billion active parameters, a one-million-token context, and input across text, images, video and audio. Xiaomi publishes it under the MIT licence; see the &lt;a href="https://huggingface.co/XiaomiMiMo/MiMo-V2.6-Pro-RL" rel="noopener noreferrer"&gt;model card&lt;/a&gt;. &lt;code&gt;mimo-v2.6-flash&lt;/code&gt; is the smaller companion model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tencent: Hy
&lt;/h3&gt;

&lt;p&gt;Hy4 preview is Tencent's new flagship, with 770 billion total parameters, about 49 billion active, a one-million-token context and an Apache 2.0 licence. The &lt;a href="https://huggingface.co/tencent/Hy4-preview" rel="noopener noreferrer"&gt;model card&lt;/a&gt; is explicit that this is an early version, and lists known issues including overly long reasoning and over-verification. Worth testing, with that in mind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prices on BoostRail
&lt;/h2&gt;

&lt;p&gt;Prices in USD per 1M tokens on 16 October 2026. Live prices for every model are on the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;Models page&lt;/a&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lab&lt;/th&gt;
&lt;th&gt;Model id&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Cache read&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Moonshot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;kimi-k3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2.85&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;0.3165&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alibaba&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3.8-max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.9&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;0.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alibaba&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen3.7-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Z.ai&lt;/td&gt;
&lt;td&gt;&lt;code&gt;glm-5.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.33&lt;/td&gt;
&lt;td&gt;4.18&lt;/td&gt;
&lt;td&gt;0.247&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Z.ai&lt;/td&gt;
&lt;td&gt;&lt;code&gt;glm-5.3-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.1425&lt;/td&gt;
&lt;td&gt;0.475&lt;/td&gt;
&lt;td&gt;0.0285&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;0.018&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MiniMax&lt;/td&gt;
&lt;td&gt;&lt;code&gt;minimax-m3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.3&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Xiaomi&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mimo-v2.6-pro&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.41325&lt;/td&gt;
&lt;td&gt;0.8265&lt;/td&gt;
&lt;td&gt;0.00342&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tencent&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hy4-preview&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.834&lt;/td&gt;
&lt;td&gt;2.501&lt;/td&gt;
&lt;td&gt;0.042&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For reference, &lt;code&gt;claude-sonnet-5&lt;/code&gt; is 1.9 input and 9.5 output on the same date. For how these prices turn into a monthly bill, see &lt;a href="https://www.boostrail.com/blog/llm-api-pricing-explained/" rel="noopener noreferrer"&gt;LLM API Pricing Explained&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which model for which job
&lt;/h2&gt;

&lt;p&gt;This is a starting shortlist based on what each lab says the model is built for. Your own test is what decides.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Models to try first&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main model for a coding agent&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;kimi-k3&lt;/code&gt;, &lt;code&gt;glm-5.3&lt;/code&gt;, &lt;code&gt;qwen3.8-max&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long documents and repositories&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;kimi-k3&lt;/code&gt;, &lt;code&gt;qwen3.8-max&lt;/code&gt;, &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-volume, low-cost steps&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;, &lt;code&gt;qwen3.7-flash&lt;/code&gt;, &lt;code&gt;glm-5.3-flash&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long agent runs on a budget&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;minimax-m3&lt;/code&gt;, &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Several of these models also work as the main model inside Claude Code through the Anthropic format; see &lt;a href="https://www.boostrail.com/blog/claude-code-with-other-models/" rel="noopener noreferrer"&gt;Claude Code with Other Models&lt;/a&gt; for the setup and our test results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Calling Chinese AI models from outside China
&lt;/h2&gt;

&lt;p&gt;There are three routes, each with a real trade-off.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Each lab's international platform.&lt;/strong&gt; Most of these labs run their own international API platform. You get the lab's own pricing and features, and you manage one account, key, balance and set of docs per lab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosting the open weights.&lt;/strong&gt; Full control, and full responsibility. A model with hundreds of billions or trillions of parameters needs a multi-GPU cluster to serve at useful speed, so this pays off mainly at large, steady volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One API in front of all of them.&lt;/strong&gt; BoostRail serves every model above through one OpenAI-compatible endpoint and one Anthropic-compatible endpoint, with one key and one USD balance. Switching models is a change to the &lt;code&gt;model&lt;/code&gt; string. The &lt;a href="https://www.boostrail.com/openai-compatible-api/" rel="noopener noreferrer"&gt;OpenAI-compatible API page&lt;/a&gt; has the details.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Testing them on your own workload
&lt;/h2&gt;

&lt;p&gt;Because the endpoint is the same for every model, a side-by-side test is a loop. This streams one prompt to five models and prints each answer as it arrives, followed by its token usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.boostrail.com/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write a Python function that parses ISO 8601 durations such as PT1H30M.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kimi-k3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;glm-5.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen3.8-max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deepseek-v4.1-flash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;minimax-m3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;=== &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Streaming matters here. Reasoning models differ a lot in how much they think before the first visible word, and on BoostRail a non-streaming request stops at 180 seconds. When we ran this exact prompt on 16 October 2026, GLM-5.3 reasoned for about ten minutes and used 29,570 output tokens before finishing its answer, and Qwen3.8-Max took about three minutes and 17,329 output tokens. With &lt;code&gt;max_tokens&lt;/code&gt; set to 4000, both spent the whole budget on reasoning and returned no text.&lt;/p&gt;

&lt;p&gt;Most reasoning models also accept a reasoning effort setting, which BoostRail's Chat Completions endpoint takes as &lt;code&gt;reasoning_effort&lt;/code&gt;. With &lt;code&gt;reasoning_effort&lt;/code&gt; set to &lt;code&gt;low&lt;/code&gt;, the same prompt took GLM-5.3 3,348 output tokens and Qwen3.8-Max 1,918, about a ninth of what they used by default. The effect varies by model, so measure it on each one.&lt;/p&gt;

&lt;p&gt;Use prompts from your real workload, not puzzles, and compare three things: whether the answer is right, how many output tokens it took, and how long it took. All three show up in the bill and in what users wait for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Are Chinese AI models open source?
&lt;/h3&gt;

&lt;p&gt;Most of the current flagships publish their weights. Licences differ: DeepSeek V4.1 Flash and MiMo V2.6 Pro use MIT, Hy4 preview uses Apache 2.0, and Kimi K3, MiniMax M3 and GLM-5.3 use each lab's own licence. Read the licence file before you build on self-hosted weights.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use Chinese AI models from outside China?
&lt;/h3&gt;

&lt;p&gt;Yes. Most of these labs run an international API, and BoostRail serves all the models in this guide through one key with USD billing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do they support tool calling?
&lt;/h3&gt;

&lt;p&gt;On 16 October 2026 we ran a two-turn tool call through BoostRail's Anthropic-format endpoint on &lt;code&gt;kimi-k3&lt;/code&gt;, &lt;code&gt;glm-5.3&lt;/code&gt;, &lt;code&gt;qwen3.8-max&lt;/code&gt;, &lt;code&gt;minimax-m3&lt;/code&gt; and &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;, and all five called the tool and used its result correctly. The &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;Models page&lt;/a&gt; also marks capabilities that passed automated checks on every route serving a model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which one is the cheapest?
&lt;/h3&gt;

&lt;p&gt;In the table above, &lt;code&gt;qwen3.7-flash&lt;/code&gt; has the lowest input and output prices, with &lt;code&gt;glm-5.3-flash&lt;/code&gt; and &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt; close behind. Price per token is only half the comparison; check how many tokens each one needs to finish your task.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I switch between them?
&lt;/h3&gt;

&lt;p&gt;Change the &lt;code&gt;model&lt;/code&gt; string. The endpoint, the key and the request format stay the same, so you can route different tasks to different models in the same application.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>deepseek</category>
      <category>api</category>
    </item>
    <item>
      <title>LLM API Pricing Explained: How to Estimate Your Bill</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:32:02 +0000</pubDate>
      <link>https://dev.to/boostrail/llm-api-pricing-explained-how-to-estimate-your-bill-op5</link>
      <guid>https://dev.to/boostrail/llm-api-pricing-explained-how-to-estimate-your-bill-op5</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/llm-api-pricing-explained/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on October 16, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;LLM API pricing looks simple on a price list, two numbers per model, and becomes hard to predict once real traffic arrives. The bill depends on how many tokens go in, how many come out, how much of the input repeats, and how much hidden reasoning the model does before it answers. This guide explains each part, shows where the numbers come from with measurements we took on 16 October 2026, and works through a monthly estimate you can repeat with your own figures.&lt;/p&gt;

&lt;h2&gt;
  
  
  How LLM API pricing works
&lt;/h2&gt;

&lt;p&gt;Almost every text model is priced per million tokens, with separate prices for input and output. Input is everything you send: the system prompt, the conversation so far, tool definitions, retrieved documents and the new message. Output is everything the model generates.&lt;/p&gt;

&lt;p&gt;Three things about tokens matter more than the exact definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokens are not words.&lt;/strong&gt; Each lab uses its own tokenizer, so the same text can be a different number of tokens on different models. Code, non-English text and long numbers often take more tokens than plain English prose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your request is bigger than your message.&lt;/strong&gt; On Kimi K3, the three-word message "Reply with OK" was counted as 88 input tokens. Templates and formatting count too. Read the &lt;code&gt;usage&lt;/code&gt; field in each response instead of estimating from the text you typed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output usually costs several times more than input.&lt;/strong&gt; On the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;BoostRail catalog&lt;/a&gt;, Claude Sonnet 5's output price is five times its input price, and DeepSeek V4.1 Flash's is four times. Workloads that generate a lot of text feel this most.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The four token types on a bill
&lt;/h2&gt;

&lt;p&gt;A modern LLM bill has up to four lines, even when the price list shows two numbers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Token type&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;How it is usually billed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Input&lt;/td&gt;
&lt;td&gt;New, uncached tokens you send&lt;/td&gt;
&lt;td&gt;Input price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cached input&lt;/td&gt;
&lt;td&gt;Repeated prefix the provider recognises from an earlier request&lt;/td&gt;
&lt;td&gt;Cache-read price, a fraction of the input price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output&lt;/td&gt;
&lt;td&gt;Text and tool calls the model returns&lt;/td&gt;
&lt;td&gt;Output price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reasoning&lt;/td&gt;
&lt;td&gt;Thinking the model does before answering&lt;/td&gt;
&lt;td&gt;Counted as output&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Reasoning tokens are easy to miss.&lt;/strong&gt; When we asked Kimi K3 to "Reply with OK", the visible answer was two characters and the response reported 98 output tokens, because the model reasoned before answering. With a budget of 16 tokens, the same request returned no text at all. Reasoning models need room in &lt;code&gt;max_tokens&lt;/code&gt;, and that room is billed as output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache writes are priced differently by each provider.&lt;/strong&gt; Anthropic's own API, for example, charges more than the input price to write to its cache and a tenth of it to read, according to its &lt;a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching" rel="noopener noreferrer"&gt;prompt caching documentation&lt;/a&gt;. On BoostRail, cache writes carry no surcharge: the first pass bills at the normal input price, and later cache reads bill at the cache-read price published for each model, where the model's route supports caching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agents cost more than chat
&lt;/h2&gt;

&lt;p&gt;A chat turn sends one message and gets one answer. An agent turn sends the whole working context again: instructions, tool definitions, files it has read, command output and every earlier step. In Claude Code 2.1.295, a one-word reply still sent 20,751 input tokens. A long session repeats a prefix like that dozens of times per task.&lt;/p&gt;

&lt;p&gt;Two consequences follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input dominates.&lt;/strong&gt; For coding agents, input tokens are usually many times the output tokens, so the input price and the cache-read price decide most of the bill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache share decides the rest.&lt;/strong&gt; If most of each request is a repeated prefix that hits the cache, the effective input price drops close to the cache-read price. If the prefix changes every turn, nothing is cached and every token bills at the full input price.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://www.boostrail.com/cost-calculator/" rel="noopener noreferrer"&gt;cost calculator&lt;/a&gt; has three usage profiles built on this, and explains why the cache share matters more than the headline price. For the coding-specific side, see &lt;a href="https://www.boostrail.com/blog/claude-code-with-other-models/" rel="noopener noreferrer"&gt;Claude Code with Other Models&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: estimating a monthly bill
&lt;/h2&gt;

&lt;p&gt;Take the calculator's middle profile, roughly one developer using a coding agent every day: 30M input tokens and 6M output tokens a month, with 70% of the input served from cache. That splits the input into 21M cached tokens and 9M uncached tokens.&lt;/p&gt;

&lt;p&gt;Prices from the BoostRail catalog on 16 October 2026, in USD per 1M tokens:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Cache read&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;0.60&lt;/td&gt;
&lt;td&gt;0.018&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claude-sonnet-5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1.90&lt;/td&gt;
&lt;td&gt;9.50&lt;/td&gt;
&lt;td&gt;0.19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The formula is the same for every model: uncached input × input price, plus cached input × cache-read price, plus output × output price, each divided by one million.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line, in USD&lt;/th&gt;
&lt;th&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;claude-sonnet-5&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;9M uncached input&lt;/td&gt;
&lt;td&gt;1.35&lt;/td&gt;
&lt;td&gt;17.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21M cached input&lt;/td&gt;
&lt;td&gt;0.38&lt;/td&gt;
&lt;td&gt;3.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6M output&lt;/td&gt;
&lt;td&gt;3.60&lt;/td&gt;
&lt;td&gt;57.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month&lt;/td&gt;
&lt;td&gt;5.33&lt;/td&gt;
&lt;td&gt;78.09&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So the same month of work costs about $5.33 on DeepSeek V4.1 Flash and about $78.09 on Claude Sonnet 5. Without caching, the Sonnet month would be $114.00, because all 30M input tokens would bill at the full input price. The gap between models is large, and so is the gap between a cache-friendly setup and one that is not.&lt;/p&gt;

&lt;p&gt;Two cautions keep the estimate honest. The token counts are the hard part: measure a week of real usage from the &lt;code&gt;usage&lt;/code&gt; fields before you trust a monthly figure. And a cheaper model that needs more turns to finish a task can cost more per task than its price suggests, so compare cost per finished task, not cost per token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other charges that can appear
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Images and video.&lt;/strong&gt; Image inputs are counted in tokens on most text models. Video generation is usually priced per second of output instead, by resolution; see the &lt;a href="https://www.boostrail.com/models/video/" rel="noopener noreferrer"&gt;video models page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context caps.&lt;/strong&gt; Some models on BoostRail accept inputs up to a stated cap at a single flat rate. Larger inputs return a &lt;code&gt;context_length_exceeded&lt;/code&gt; error before any charge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interrupted streams.&lt;/strong&gt; A streaming request closed before it completes is billed for the usage the provider reports, which can include reasoning tokens. The exact rule is in the &lt;a href="https://www.boostrail.com/pricing/#pr-interrupted" rel="noopener noreferrer"&gt;pricing FAQ&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failed requests.&lt;/strong&gt; On BoostRail, when every route for a model fails, the request is not charged. Your own retries are new requests and are billed if they succeed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top-up fees.&lt;/strong&gt; Card top-ups carry a 5.5% processing fee with a $0.80 minimum; USDT top-ups carry 1% with a $0.10 minimum. Pay-as-you-go use has no monthly subscription.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to bring the bill down
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep the prompt prefix stable.&lt;/strong&gt; Put fixed instructions and tool definitions first and changing content last, so repeated requests share a cacheable prefix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route by task.&lt;/strong&gt; Send planning and hard reasoning to a strong model, and bulk summarising, classification and simple edits to a cheap one. The &lt;a href="https://www.boostrail.com/blog/deepseek-v4-pro-vs-flash/" rel="noopener noreferrer"&gt;DeepSeek V4 Pro vs Flash&lt;/a&gt; post walks through one such split.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose the reasoning effort.&lt;/strong&gt; Many reasoning models accept a lower effort setting (&lt;code&gt;reasoning_effort&lt;/code&gt; on Chat Completions). On a coding prompt we tested, &lt;code&gt;low&lt;/code&gt; cut GLM-5.3's output from 29,570 tokens to 3,348.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set &lt;code&gt;max_tokens&lt;/code&gt; on purpose.&lt;/strong&gt; Enough for reasoning models to finish, not so much that a runaway answer gets expensive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap spending per key.&lt;/strong&gt; BoostRail keys can carry a daily or monthly spend limit; requests past it return &lt;code&gt;key_spend_limit_exceeded&lt;/code&gt; instead of growing the bill. See &lt;a href="https://www.boostrail.com/docs/errors/" rel="noopener noreferrer"&gt;Errors and failover&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is a token the same across models?
&lt;/h3&gt;

&lt;p&gt;No. Each lab has its own tokenizer, so the same text produces different token counts on different models. Compare models on the &lt;code&gt;usage&lt;/code&gt; they report for the same request, not on the price list alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is output more expensive than input?
&lt;/h3&gt;

&lt;p&gt;Generating a token takes more compute time than reading one, because output is produced one token at a time, and labs price output accordingly. Prices in the catalog show output at several times the input price for most models.&lt;/p&gt;

&lt;h3&gt;
  
  
  How are reasoning tokens billed?
&lt;/h3&gt;

&lt;p&gt;As output. The model's thinking is counted in the output tokens of the response, even when only the final answer is shown. A short answer from a reasoning model can therefore bill far more output tokens than its visible length.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the cheapest way to run a coding agent?
&lt;/h3&gt;

&lt;p&gt;Use a cache-friendly setup, a low-priced model for routine steps, and a strong model only where it changes the result. Then measure cost per finished task over a week; the catalog price alone does not tell you that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where can I see what each request cost?
&lt;/h3&gt;

&lt;p&gt;In the BoostRail console. It records the usage and the price applied to every request, which is the number that reaches your balance.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Claude Code with Other Models: DeepSeek, Kimi, GLM, Qwen</title>
      <dc:creator>Lee Gao</dc:creator>
      <pubDate>Sat, 17 Oct 2026 08:31:56 +0000</pubDate>
      <link>https://dev.to/boostrail/claude-code-with-other-models-deepseek-kimi-glm-qwen-k54</link>
      <guid>https://dev.to/boostrail/claude-code-with-other-models-deepseek-kimi-glm-qwen-k54</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://www.boostrail.com/blog/claude-code-with-other-models/" rel="noopener noreferrer"&gt;boostrail.com&lt;/a&gt; on October 16, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Running Claude Code with other models comes down to one fact: Claude Code speaks the Anthropic Messages format, and any endpoint that serves that format can answer it. Point Claude Code at such an endpoint, name a model, and the same terminal agent, tools and workflow run on DeepSeek, Kimi, GLM, Qwen or MiniMax instead of Claude.&lt;/p&gt;

&lt;p&gt;This guide covers the setup, which model suits which kind of work, what we saw when we tested it on 16 October 2026, and the limits worth knowing before a long session. One point first, so it is not buried: Anthropic's own documentation says it does not support routing Claude Code to non-Claude models through any gateway. It works because the protocol is shared, not because anyone certifies the combination. Test with your own repository before you depend on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why run Claude Code with other models
&lt;/h2&gt;

&lt;p&gt;Three reasons come up repeatedly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost per task.&lt;/strong&gt; A coding agent resends its system prompt, tool definitions and conversation on every turn. In our test, a one-word reply in Claude Code 2.1.295 still sent 20,751 input tokens. At those volumes, the per-token price of the model decides the bill more than any single prompt does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No usage window.&lt;/strong&gt; A subscription meters agent use in time windows, and a heavy session can run out mid-task. Pay-per-token access through an API key has no window to wait out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choice per task.&lt;/strong&gt; Some teams keep Claude for planning and hard debugging, and hand routine edits, test runs and repository exploration to a cheaper model. Claude Code lets you set the main model, the background model and the subagent model separately.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the wider argument about subscription windows and rate limits, see &lt;a href="https://www.boostrail.com/blog/coding-agent-rate-limits/" rel="noopener noreferrer"&gt;Coding Agents and Rate Walls&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;Claude Code reads its endpoint from &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; and its credential from &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; (sent as a Bearer token) or &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; (sent as &lt;code&gt;x-api-key&lt;/code&gt;). Every request goes to &lt;code&gt;/v1/messages&lt;/code&gt; on that base URL, in Anthropic's format, with the model name you configured.&lt;/p&gt;

&lt;p&gt;BoostRail serves &lt;code&gt;/v1/messages&lt;/code&gt; for every text model in its catalog, not only Claude. The request is translated for the route serving that model, and the response comes back as Anthropic streaming events, including tool calls. The fields that cannot be applied are listed on the &lt;a href="https://www.boostrail.com/docs/messages/" rel="noopener noreferrer"&gt;Messages reference&lt;/a&gt; and reported in the &lt;code&gt;x-boostrail-degraded&lt;/code&gt; response header, so nothing is dropped silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup in three steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Create a key in the BoostRail console. The same key works for every model in the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;catalog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; Put the settings in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;. A settings file reaches desktop launches and background agents, which shell exports do not reliably do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_BASE_URL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.boostrail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_AUTH_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR_API_KEY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kimi-k3[1m]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ANTHROPIC_DEFAULT_HAIKU_MODEL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deepseek-v4.1-flash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What each line does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; is the credential variable Anthropic's documentation recommends when a gateway accepts Bearer tokens. While it is set, requests carry this key instead of your claude.ai login, and the subscription's limits do not apply to them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt; sets the main model. The &lt;code&gt;[1m]&lt;/code&gt; suffix tells Claude Code the model has a one-million-token window; Claude Code strips it before sending, so BoostRail receives &lt;code&gt;kimi-k3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ANTHROPIC_DEFAULT_HAIKU_MODEL&lt;/code&gt; moves background work, such as session titles and summaries, to a cheaper model.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS&lt;/code&gt; stops Claude Code from sending pre-release fields that only Anthropic's own API accepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Check the connection before a long session. This is a direct request with the same key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://api.boostrail.com/v1/messages &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"anthropic-version: 2023-06-01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"content-type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model": "kimi-k3", "max_tokens": 256, "messages": [{"role": "user", "content": "Reply with OK"}]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A JSON body whose &lt;code&gt;content&lt;/code&gt; array holds the reply means the key and base URL work. Leave room in &lt;code&gt;max_tokens&lt;/code&gt;: reasoning models spend part of it thinking, and with a budget of 16 tokens Kimi K3 returned an empty &lt;code&gt;content&lt;/code&gt; array. Then start &lt;code&gt;claude&lt;/code&gt;, run &lt;code&gt;/status&lt;/code&gt;, and look for the &lt;code&gt;Anthropic base URL&lt;/code&gt; line. If it is missing, the variables did not reach the session. The &lt;a href="https://www.boostrail.com/coding/" rel="noopener noreferrer"&gt;coding agents page&lt;/a&gt; has the same settings for Codex CLI, Cline and other tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which model for which job
&lt;/h2&gt;

&lt;p&gt;The model ids below are the ones BoostRail accepts. The positioning comes from each lab's own model card or announcement, linked in the last column, so read it as the lab's claim rather than ours.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model id&lt;/th&gt;
&lt;th&gt;What the lab says it is built for&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kimi-k3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Long-horizon coding, agentic knowledge work and reasoning&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;&lt;a href="https://huggingface.co/moonshotai/Kimi-K3" rel="noopener noreferrer"&gt;Moonshot model card&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;glm-5.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Coding; Z.ai calls it its most capable open-weights coding model&lt;/td&gt;
&lt;td&gt;see card&lt;/td&gt;
&lt;td&gt;&lt;a href="https://huggingface.co/zai-org/GLM-5.3" rel="noopener noreferrer"&gt;Z.ai model card&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;qwen3.8-max&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Autonomous coding and long-horizon execution&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;&lt;a href="https://www.alibabagroup.com/document-2021044032125272064" rel="noopener noreferrer"&gt;Alibaba announcement&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;minimax-m3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Long-horizon agent work, coding and long-context efficiency&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;&lt;a href="https://huggingface.co/MiniMaxAI/MiniMax-M3" rel="noopener noreferrer"&gt;MiniMax model card&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cost-efficient, input-heavy agent workloads&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;&lt;a href="https://huggingface.co/deepseek-ai/DeepSeek-V4.1-Flash" rel="noopener noreferrer"&gt;DeepSeek model card&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A practical split many teams start with: a strong model as the main model for planning and multi-file changes, and &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt; for background work and subagents that read and summarise code. Prices for each model, input and output, are on the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;Models page&lt;/a&gt;. For a broader look at these labs, see &lt;a href="https://www.boostrail.com/blog/chinese-ai-models-2026/" rel="noopener noreferrer"&gt;Chinese AI Models in 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we tested
&lt;/h2&gt;

&lt;p&gt;On 16 October 2026 we ran two checks with BoostRail's internal test key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A two-turn tool call over &lt;code&gt;/v1/messages&lt;/code&gt;.&lt;/strong&gt; Each model received a &lt;code&gt;read_file&lt;/code&gt; tool and the question "What Python version does this project need?". All five models in the table above called the tool with the right file, accepted the tool result, and answered correctly with &lt;code&gt;end_turn&lt;/code&gt;. This shows the request and response shapes Claude Code relies on round-trip correctly for these models. It is a single test per model, not a guarantee across every route.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code itself.&lt;/strong&gt; We ran Claude Code 2.1.295 in print mode against BoostRail, with &lt;code&gt;glm-5.3&lt;/code&gt; as the main model, and asked it to create a Python file and run it. It wrote the file, ran it with &lt;code&gt;python3&lt;/code&gt;, and reported the correct output in three turns. Shorter runs with &lt;code&gt;kimi-k3&lt;/code&gt; and &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt; as the main model also returned normally. Two details from those runs are useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usage showed cache reads on Kimi K3 and DeepSeek V4.1 Flash (&lt;code&gt;cache_read_input_tokens&lt;/code&gt; above zero), so repeated context was billed at the cache-read price on those runs. GLM-5.3 showed almost none.&lt;/li&gt;
&lt;li&gt;Claude Code's own cost figure is computed from its built-in price table, not from your bill. For the one-word DeepSeek reply it showed $0.083; the same tokens at DeepSeek V4.1 Flash's catalog price come to about $0.003. Check spending in the BoostRail console, which records the price applied to each request.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits to know before a long session
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;/model&lt;/code&gt; picker will not list them.&lt;/strong&gt; With gateway model discovery on, Claude Code only keeps ids that contain "claude" or "anthropic". Type the id instead: &lt;code&gt;/model glm-5.3&lt;/code&gt; switches the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context window.&lt;/strong&gt; For an id it does not recognise, Claude Code assumes 200K tokens and compacts the conversation before that. Add &lt;code&gt;[1m]&lt;/code&gt; for models with a one-million-token window. For a model capped below 200K, such as &lt;code&gt;qwen3-coder-flash&lt;/code&gt; on BoostRail, set &lt;code&gt;CLAUDE_CODE_AUTO_COMPACT_WINDOW&lt;/code&gt; to its limit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token counting.&lt;/strong&gt; BoostRail does not serve &lt;code&gt;/v1/messages/count_tokens&lt;/code&gt;. Claude Code falls back to its own estimate, so &lt;code&gt;/context&lt;/code&gt; shows approximate numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Thinking blocks.&lt;/strong&gt; Earlier thinking blocks in the conversation history are accepted and dropped, and named in &lt;code&gt;x-boostrail-degraded&lt;/code&gt;. Each model reasons in its own way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto mode.&lt;/strong&gt; Auto mode sends a separate safety-classifier request for each action, and in our run it went to a Claude model rather than the one we configured. With Claude Code 2.1.295 and a non-Claude main model, auto mode blocked the shell command it could not evaluate. Use the default permission mode with allow rules for the commands you trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A diagnostic line.&lt;/strong&gt; Print mode starts with &lt;code&gt;[claude-code:unrecognized_model]&lt;/code&gt; for ids Claude Code does not know. It is informational; the request still goes through.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Mixing Claude and other models
&lt;/h2&gt;

&lt;p&gt;Nothing forces an all-or-nothing switch. Because every model sits behind the same endpoint and key, you can keep &lt;code&gt;claude-sonnet-5&lt;/code&gt; as the main model and move only background work to &lt;code&gt;deepseek-v4.1-flash&lt;/code&gt;, or the other way round. &lt;code&gt;CLAUDE_CODE_SUBAGENT_MODEL&lt;/code&gt; sets the default model for subagents, and a subagent definition can still name its own model. When a session needs Claude's judgement for one hard step, &lt;code&gt;/model claude-sonnet-5&lt;/code&gt; switches back without touching the settings file.&lt;/p&gt;

&lt;p&gt;If your team already holds contracts with model providers, BYOK runs catalog models on your own provider keys behind the same endpoint; see &lt;a href="https://www.boostrail.com/blog/byok-own-provider-keys/" rel="noopener noreferrer"&gt;the BYOK guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does Anthropic support Claude Code with other models?
&lt;/h3&gt;

&lt;p&gt;No. Anthropic's documentation states that it does not support routing Claude Code to non-Claude models through any gateway. The setup works because the Messages format is shared. Treat it as a configuration you own and test it on your own code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will my Claude subscription still be charged?
&lt;/h3&gt;

&lt;p&gt;No. While &lt;code&gt;ANTHROPIC_AUTH_TOKEN&lt;/code&gt; is set, Claude Code sends that key instead of your claude.ai login, and the subscription's usage limits do not apply to those requests. Usage is billed per token to the BoostRail account that owns the key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is DeepSeek, Kimi or GLM missing from /model?
&lt;/h3&gt;

&lt;p&gt;Gateway model discovery only adds ids that contain "claude" or "anthropic". Set the model in &lt;code&gt;ANTHROPIC_MODEL&lt;/code&gt;, or type &lt;code&gt;/model&lt;/code&gt; followed by the id during a session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does prompt caching work with non-Claude models?
&lt;/h3&gt;

&lt;p&gt;It depends on the model's route. Where caching is supported, cache reads appear in &lt;code&gt;cache_read_input_tokens&lt;/code&gt; and are billed at the cache-read price shown on the &lt;a href="https://www.boostrail.com/models/" rel="noopener noreferrer"&gt;Models page&lt;/a&gt;. In our runs Kimi K3 and DeepSeek V4.1 Flash showed cache reads and GLM-5.3 showed very few.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which settings file should I use?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;~/.claude/settings.json&lt;/code&gt; for your own machine. Do not put the key in a project's &lt;code&gt;.claude/settings.json&lt;/code&gt;, which is committed to the repository and shared with everyone who clones it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>claude</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
