You wanted to try three models from three vendors, so you did the sensible thing: pointed one client at a gateway, put one key in the environment, and stopped thinking about it. A gateway here is a service that speaks the OpenAI API and forwards your requests to Anthropic, Google, OpenAI, xAI and the rest, so switching models is a string change instead of a new SDK.
What almost nobody checks after that: what the gateway charges for the exact same tokens the vendor would have sold you directly.
Three things, and they are worth very different amounts.
One key and one invoice. Real, and boring. It saves you three signups and three billing pages.
Routing and fallback. If a provider returns 529 or a region goes dark, the gateway retries elsewhere. Worth something on production traffic, nothing on a weekend project.
A price per token. This is the one that varies by an order of magnitude between services, and the one nobody puts in a comparison table — because there is no single "gateway price". There is a price per model, and a service can sit below vendor list on one model and far above it on another.
Vocabulary, in case it is new: models are billed per million tokens (a token is roughly ¾ of a word), input and output priced separately, with output typically 3–10× more expensive. The list price is what the vendor publishes on its own pricing page. That list price is your baseline — a gateway is either below it, at it, or taking a markup on top.
Many gateways publish per-model pricing in their models endpoint. If yours does, this reads it and prices out your token mix, not a benchmark's:
import json, urllib.request
GATEWAY = "https://api.altrouter.ai/v1/models/public" # your gateway's models endpoint
LIST = {"claude-sonnet-5": (2.00, 10.00), "gpt-5.6": (2.50, 15.00)} # vendor list $/1M in, out
MIX = (200, 40) # your monthly millions of tokens: input, output
req = urllib.request.Request(GATEWAY, headers={"User-Agent": "price-check"})
models = json.load(urllib.request.urlopen(req))["data"]
for m in models:
inp, out = m["pricing"].get("prompt_per_1m_usd"), m["pricing"].get("completion_per_1m_usd")
if m["id"] not in LIST or inp is None:
continue
li, lo = LIST[m["id"]]
mine = MIX[0] * inp + MIX[1] * out
vendor = MIX[0] * li + MIX[1] * lo
print(f"{m['id']:<18} gateway ${mine:>8.2f} list ${vendor:>8.2f} {mine / vendor - 1:+.1%}")
Run on 2026-08-14 against the endpoint in the snippet, it prints:
gpt-5.6 gateway $ 935.09 list $ 1100.00 -15.0%
claude-sonnet-5 gateway $ 677.91 list $ 800.00 -15.3%
If your gateway does not publish prices in that endpoint — plenty don't — use the invoice method instead: take last month's charge, divide by the input and output tokens the gateway logged, and you have your real effective $/1M. That number is the only one that matters, and it is the one you compare to the vendor's page.
The obvious objection: the mix is made up. It is — replace MIX
with your own two numbers before you believe any of the output. The ratio between input and output tokens is workload-specific, and since output costs several times more, a chat workload and a document-summarizing workload rank gateways differently.
base_url
is genuinely the only change.usage
object in the response. Those are where compatibility usually breaks.Disclosure, since the URL in the snippet is mine: I work on altrouter.ai, which is why I could hardcode an endpoint that publishes its prices. It resells vendor models below list — Claude Sonnet 5 at $1.69 / $8.50 per 1M against the official $2.00 / $10.00, Opus 4.5 at $3.74 / $18.75 against $5.00 / $25.00, discounts running 10–25% by model, prices as of August 2026. Point the script at whatever you use now; the arithmetic does not care.
Price, and only price. The script says nothing about latency, uptime, rate limits, or whether prompt caching is passed through at the vendor's discount — check that separately, it can outweigh a 15% price gap. And the honest gaps on my side: no embedding models, no data residency options, no SLA of our own beyond the upstream vendor's. If you are on one vendor and never plan to leave, buy direct — you save exactly the middleman's margin.
Run the seventeen lines on your own gateway this week. Whatever the number is, it is better to know it than to assume the convenience was free.