How Multi-Model AI Video Routing Works
What it actually takes to put Kling, Veo, and Wan behind one prompt box: a model registry, scene-aware endpoints, one derived credit economy, async webhooks, and idempotent billing.
How multi-model AI video routing works
"Just put all the models behind one button" sounds simple. It isn't — every model has a different API, a different price, a different set of scenes it supports, and they all run asynchronously. Here's the architecture I built for HyperFrames to make a single prompt box route cleanly to Kling, Google Veo, or Wan, without ever double-charging a credit.
1. A single source of truth for models
Everything starts with one registry that defines, for every model: which scenes it supports (text-to-video, image-to-video), valid durations and aspect ratios, what it costs in credits, and which upstream provider/endpoint serves it.
The rule I hold to: there is never a second, hand-maintained table of prices. The credit a user is charged is derived from the model definition at load time. I learned this the hard way on an earlier project — a duplicate price table drifted out of sync and a premium model got billed at a fraction of its real cost. Every successful generation lost money until we caught it. One registry, one derivation, no drift.
2. Scene-aware endpoint resolution
A model isn't a single endpoint. Some providers sell separate endpoints for text-to-video versus image-to-video of the same logical model; others use one endpoint and switch behavior based on whether you pass an image. So the registry resolves (model, scene) → endpoint at submit time, instead of assuming one model means one URL. Get this wrong and an image-to-video request silently hits the text-to-video endpoint.
3. The credit economy, with a margin invariant
Every model's credit price obeys one invariant:
model_credits × cost_floor ≥ provider_$cost
where the cost floor is the price of the cheapest credit pack. As long as that holds for every model, no generation can be sold below cost, no matter which provider wins the routing. The front-end estimator and the server use the same resolver, so the credit pill you see before clicking generate is the exact amount you'll be charged.
4. Async generation with webhooks
Video models take seconds to minutes. You can't hold an HTTP request open that long, so generation is fully asynchronous:
- Dispatch — validate the request against the registry, claim the credits, create a task, and fire the job at the provider with a signed callback URL.
- Callback — when the provider finishes, it POSTs to our webhook. We verify an HMAC token (so nobody can forge a "success"), download the result, store it on our own object storage, and mark the task complete.
- Reconcile — webhooks get dropped sometimes. A background pass polls any task that's been "processing" too long and finalizes it from the provider's status, so nothing gets stuck forever.
5. Idempotent billing — the part that protects your credits
The scariest failure mode in a credit product is charging twice for one generation. A slow render plus an impatient double-click, a retried script, a flaky network — any of these can fire the same request twice.
So every generation carries an idempotency key. The first request wins a uniqueness constraint and creates exactly one task; any duplicate with the same key loses the race and returns the existing task instead of dispatching a second job. I tested this directly: fire five identical requests at once, and you get exactly one task, one credit charge, one provider call. And if a dispatch fails after the credits were claimed, they're refunded automatically — you never pay for a generation that didn't happen.
Why this matters to you
You see a prompt box and a model dropdown. Underneath is a registry that keeps prices honest, scene-aware routing so the right endpoint always gets hit, async webhooks with a reconcile fallback so jobs finish reliably, and idempotent billing so your balance is only ever charged once per video. That's the boring infrastructure that lets "every model, one credit balance" actually be true.