Live channel vs scaffold estimate — what the badge on /pricing means
Every row on the /pricing endpoint table carries a small status badge. "Live channel" means the price came from the gateway's admin export — what we actually charge today. "Scaffold estimate" means we listed a conservative public-list-price approximation until that endpoint's channel is wired up. The split is deliberate; here's why we surface it instead of hiding it.
If you've scrolled the /pricing table you've seen rows with two distinct chip styles in the rightmost Status column. One is filled teal — "live" or "rolling out" — and a small label below says "live channel". The other is muted gray, label "scaffold estimate". Same table, two trust levels, surfaced deliberately.
What "live channel" actually means
The pricing engine pulls from a JSON export of the gateway's admin /channels endpoint. Each channel ships with a model_pricing row that lists the per-token (text) or per-call (image / video) rate the gateway charges today. We don't restate it; we render it verbatim with the same currency, the same rounding, the same per-request tiers. If the gateway charges you differently next week, the next /pricing build will say so.
What "scaffold estimate" actually means
Some endpoints in the table are listed in our marketing metadata but their gateway channel isn't yet wired into the production admin (often new models still going through compliance / vendor onboarding). For those rows we fall back to a conservative approximation of the upstream's public list price — "conservative" meaning if anything we round up, not down. When the channel goes live, the same row flips to live-channel pricing automatically on the next build.
Why we surface the badge instead of hiding the estimate rows
- We want the table to list every endpoint our gateway speaks, not just the ones with locked-in pricing. "This is supported" + "price is approximate" is more honest than "this isn't on our pricing page yet".
- Estimate rows incentivize us to lock real channels in fast. A row that's been "scaffold estimate" for too long is a visible eyesore we own.
- Customers planning capacity want a worst-case number. Conservative-list-price estimate is the right shape for that — pad your plan against it and discover you spent less.
How the JOIN actually works
Marketing-side `lib/endpoints.ts` holds 23 endpoint slugs with vendor + capability + category. Marketing-side `data/channels-export.json` is the gateway admin export. `lib/pricing.ts` matches them by slug ↔ models[] entry, with a hyphen-insensitive normalize so cosmetic punctuation drift on either side (`seedream-v5lite` vs `seedream-v5-lite`) doesn't drop a real row to the estimate fallback. Whatever channels-export covers wins; the rest fall back with `source: "estimate"`. Schema is intentionally a 1:1 mirror of the admin API so swapping the JSON in is a no-op.
“Either we charge you this much today, or our best guess says we'd charge you about this much when the channel goes live — pick a row, the badge tells you which case you're reading.”
Live nightly-refreshed numbers always live on the /pricing table itself. The badge is the truth marker; the number next to it is the price.