Skip to content

Billing & usage accuracy

Most requests are priced from the token usage the provider reports (input, output, cached, audio) times the per-model rate; image, video, 3D and some audio requests are priced per image / per second / per character instead (see the modality table below). Either way the rate is your rate — the model’s published price when your operator has set one, otherwise the provider-cost basis; never marked up from a cheaper upstream you don’t see (which provider actually serves a given model is an internal routing detail, and any margin is the operator’s, not billed to you on top). How precisely we can meter a request depends on how you call the gateway. There are two modes.

Your usage draws down an account balance. Your operator puts your account on one of two payment modes:

  • Prepay — you top up the balance up front; requests are served while the balance is positive.
  • Postpay — you spend against a credit limit and are invoiced for the accrued usage each period.

This is the platform billing you ↔ the gateway operator. It is separate from Stripe Token Billing, which is how you bill your own end-users.

Create a Stripe Checkout session for the amount you want to add:

POST /gw/billing/checkout # scope: keys:manage
{ "amount_usd": 50 }
→ { "url": "https://checkout.stripe.com/c/pay/…" }

Open the returned url, pay by card, and your balance is credited once Stripe confirms the payment (the gateway credits on the signed payment webhook — not on the browser redirect, so a closed tab never loses a paid top-up). The amount is credited before tax; any VAT is collected by Stripe on top. Minimum and maximum top-up amounts are set by your operator.

This endpoint exists only when your operator has enabled platform billing; otherwise it returns 404. If you’re unsure which payment mode your account is on, ask your operator.

On postpay you keep serving traffic up to your credit limit; the platform issues a Stripe invoice for the usage accrued since the last one (typically monthly). You receive a hosted Stripe invoice link to pay by the due date — paying it restores your headroom for the next period. Usage is invoiced exactly once.

Your per-request spend is always visible in GET /gw/usage; your operator can confirm your current balance and limit.

Point your existing OpenAI/Anthropic client at the gateway base URL and call vendor routes directly (/openai/*, /anthropic/*, /alibaba/*, …). The gateway forwards your request byte-for-byte — it never rewrites your body.

  • Non-streaming responses always carry usage, so they are billed exactly.
  • Streaming responses, on OpenAI-compatible providers, only include usage in the final chunk if your request sets stream_options.include_usage: true. If you don’t set it, that stream has no usage to meter and is billed approximately, then trued-up at the end of the billing period against the provider’s own numbers (reconciliation).

In short: transparent mode is “we aggregate your traffic and reconcile your invoice monthly.” For exact, immediate per-request cost, either set stream_options.include_usage yourself, or use the SDK.

The official SDKs (sociaro-ai for Python and TypeScript) set stream_options.include_usage for you on every OpenAI-format stream (Anthropic streams report usage in message_delta events, which the gateway aggregates). So every call — streaming or not — is metered exactly at the moment it completes. No month-end true-up needed.

This is the main billing advantage of the SDK, on top of:

  • one unified API across all providers (author/model slugs),
  • automatic fallback chains and routing,
  • typed image / video / async helpers,
  • the /gw self-service client (keys, budgets, usage).

See the Python SDK and TypeScript SDK guides.

Call styleNon-streamingStreamingAccuracy
Transparent, no include_usageexactapproximate → monthly true-upeventual
Transparent, include_usage: trueexactexactimmediate
SDKexactexact (set for you)immediate
  • Input / output tokens at the model’s per-MTok rate.
  • Cached prompt tokens are billed at the model’s cache-read rate when set (cheaper), otherwise at the input rate. Cached tokens are never double-counted — the OpenAI-format prompt_tokens (which includes the cached portion) is normalized so the cached part is billed once.
  • Cache writes (Anthropic prompt caching) at the cache-write rate.
  • Audio input tokens (omni models) at the model’s audio rate when set.

Non-token modalities (images, video, audio seconds, 3D) are billed per their own unit — see Async jobs and Media doors.

The billing unit depends on the model’s kind (from GET /v1/models). Each unit is multiplied by the model’s per-unit rate; the cost lands in your usage records the same way regardless of kind.

KindUnitMetered fromNotes
llm (chat)tokens (per MTok)provider usage — input, output, cached, cache-write, audio-inputthe cases above; tiered rates and variant multipliers apply where set
imageper imagenumber of images returned (or n)flat USD per generated image; async image jobs hold a provisional cost at create and finalize at terminal state — see async jobs
videoper second or per tokenfinalized at terminal stateAlibaba Wan/HappyHorse → per_second_video × resolution multiplier (e.g. 720p ×1, 1080p ×1.5); ByteDance Seedance → per_token × resolution/variant multipliers. A provisional cost is held at create and trued-up on completion — see async jobs
embedding / rerankinput tokens (per MTok)provider usage.prompt_tokensinput-only; output not billed
audio — TTSper characterUnicode characters of the request inputcharged from your request text, not the audio
audio — ASRper second of audioprovider usage.secondsvia the chat door / native async
audio — voice opsflatper calle.g. voice enrollment / design
3dper tokenfinalized at terminal stateasync, like video

embedding and rerank models are live (alibaba/text-embedding-v4, -v3, alibaba/qwen3-rerank). audio and 3d models are not in the live catalog yet — no audio model is enabled, so both TTS (/v1/audio/speech, 404) and ASR (through the chat door) are not yet callable — see embeddings, reranks & audio; their rows document how they bill once available.

Exact per-model rates are not published in a static table (they change); your actual charge is always recorded per request in GET /gw/usage. cost_usd there is what you are charged — your operator’s published rate for that model when one is set, otherwise the provider-cost basis; either way you never see the upstream provider or the margin between the two.

If your account has a negotiated discount, cost_usd already reflects it — you see your own (discounted) rate directly, nothing to apply yourself. The discount is a percentage off the operator’s published rate for a model; it does not apply on requests where no published rate exists (you’re billed the provider-cost basis there, undiscounted). You still never see the upstream provider or the margin the operator captures — the routing provider is always hidden (#71).

Some accounts have a different, model-specific rate for one or more models. This comes in two forms, and your operator picks which one applies per model:

  • a model-specific discount — simply overrides your general discount for that model only (it can be more or less favorable than your general rate, and may even be no discount at all on a specific model while your general discount still applies everywhere else);
  • a negotiated fixed rate — your own rate for that model, computed from your actual usage the same way the published rate is, but set independently of it (not a percentage off the published rate — it can be higher or lower).

Either way, if one model’s cost_usd looks different from what your general discount would imply, that’s an intentional per-model arrangement, not a billing error. cost_usd in GET /gw/usage already reflects whichever rate applies to that request; there’s nothing for you to compute, and you still never see the upstream provider or the margin the operator captures (#71).