November 01, 2026
Five modalities on one bill can mean five billing units. On GMI, for example, language models bill by input and output tokens, seedream-5.0-lite by output image, kling-3.0-turbo-t2v by the second, hunyuan-3d-pro by each generated model, and speech by its own unit on the model card. Since the invoice is a single document, allocation has to happen underneath it. Give each team and environment its own API key, write a ledger row for every request, reconcile that ledger against usage filtered by key and model, and only then split the cost. GMI Cloud MaaS supports that workflow directly: every model, from chat completions to hunyuan-3d-pro, is covered by centralized billing on a single invoice, and the usage view breaks spend down by API key and model name, by day or by hour.
For a company that wants LLM, image, video, speech, and 3D generation from one provider with one billing account, that combination is the deciding factor. Finance deals with one invoice, and each team lead still receives a statement built from the team's own request records.
Every team works inside one GMI organization, which carries the usage tier and the rate limits that all teams share. Inside it, the API key is the unit that usage reports can filter, so keys become your cost centers.
<team>-<product>-<env> reads well in reports: support-assistant-prod, creative-ads-staging, commerce-3d-prod.platform-shared-* keys, allocated by rule instead of guessed at month end.Allow exactly one team per key in the mapping sheet. A key that two teams share produces usage that no filter can separate later.
Each model page on GMI states its own billing unit, and two models in one modality can bill differently, so the ledger records whatever drives each model's charge, using values your code already has.
| Modality | Example model | What the ledger records | Where it comes from |
|---|---|---|---|
| LLM | Chat models | prompt_tokens and completion_tokens as separate quantities |
The usage object on each response; streams include it in the final chunk |
| Image | seedream-5.0-lite, per output image |
Images returned | Count of URLs in outcome.media_urls |
| Video | kling-3.0-turbo-t2v, per second |
Seconds and resolution, since 1080p carries a higher per-second rate than 720p | The duration and resolution fields in your payload |
| Speech | minimax-tts-speech-2.8-hd |
Script characters and returned audio duration | The text field in your payload and the downloaded audio file |
| 3D | hunyuan-3d-pro, per 3D model |
Models generated | Jobs that reached success |
These quantities cannot be added across rows, so they are not the allocation driver. Spend is. The console shows input and output rates and any region modifiers on each model card in Inference > Model Hub, per GMI's pricing documentation, and rates change as new models and regions come online. Keep the rate in effect on the day of each request in a small rate table, keyed by model, region, and settings such as video resolution, with contracted rates in place of list rates under a volume agreement. Price each ledger row at its matching rate, then sum per key and model to get expected spend; the usage view gives actual spend. Allocation uses the actual figure, and the expected figure exists to catch variances.
Create each ledger row with your own correlation ID before sending, and add the server's identifier when the response arrives. A minimal schema:
correlation_id, generated by your wrapperrequest_id for request-queue jobs, or the response id for chat completionsapi_key_name, team, project, featuremodel, modality, and the rate-relevant settings, such as resolutionquantity and unit, with chat completions writing one row for input tokens and one for output tokensraw_status as returned, plus status normalized to pending, success, failed, or cancelledsubmitted_at and completed_at, both stored as UTC timestampsMap any raw status your wrapper has not seen before to pending and flag it for review. Keep failed and cancelled rows instead of deleting them. When usage and the ledger disagree, those rows separate client-side errors and retries from work that was delivered. At month end, group the ledger the way the usage view is filtered, counting distinct correlation IDs so a two-row chat request counts once:
Build the daily summary in your reporting tool with these rules:
Use gmi_request_ledger as the source. Include records with completed_at at or after 2026-10-01 00:00:00 UTC and before 2026-11-01 00:00:00 UTC.
Derive day_utc from the UTC calendar date of completed_at. Group by api_key_name, model, unit, resolution, and day_utc.
For each group, calculate delivered_units by adding quantity only for rows whose status is success.
Calculate succeeded_requests as the number of distinct correlation_id values among successful rows in that group.
Calculate not_completed as the number of distinct correlation_id values among rows whose status is failed or cancelled in that group.
Keep quantities separated by unit. Distinct request counts apply within each group; adding counts across input-token and output-token groups can count the same chat request twice.
On the other side, the Serverless Usage view under Billing takes a timezone, a time range, a granularity of daily or hourly, an API key, and a model name. Pull the month in UTC with daily granularity, compare the account total with the ledger first, then work through keys in order of spend. Async jobs that cross midnight can land on adjacent days on the two sides, so a pair of daily differences that cancel out across the month points to timing, and an hourly pull around midnight on those two days settles it.
Set a tolerance before the first close; 1% of expected spend per key is a reasonable assumed starting point. Cells outside it get a second pull at hourly granularity to find the window. Then work through the candidates: a retry loop that created new request IDs without ledger rows, a batch script that bypassed the wrapper, a key used by a team other than the one in the mapping sheet, or a rate table entry that does not match the settings used.
Money enters the account in a few ways, and each needs a rule set before the first close. The Credits & Coupons page shows the General Credit Balance and a Recent Transactions table filtered by date range, and coupon codes are redeemed in the Coupons tab. With Auto Pay on, GMI reloads credits up to once per hour from the default saved card as the balance nears its threshold. Orders and receipts sit under Billing > Orders.
Three rules cover most cases:
Volume pricing follows the same logic. Pricing, policies, and deployment on MaaS can be customized per client, and when a commitment arranged with sales is in place, its benefit is shared by each team's spend on the models the agreement covers.
The figures below are assumptions chosen to show the arithmetic. Three product teams and one shared platform key used the account in October, and the usage view, pulled per key in UTC, gives each key's share of total usage spend:
| Key group | Modalities used | Share of usage spend | Share of platform-shared reallocated |
Allocated share |
|---|---|---|---|---|
| Support Assistant | LLM, speech | 36% | 2.30% | 38.30% |
| Creative Studio | Image, video | 44% | 2.81% | 46.81% |
| Commerce 3D | 3D, image | 14% | 0.89% | 14.89% |
platform-shared |
LLM, image | 6% | Spread pro rata (36:44:14) | 0% |
The close runs in five steps, and it works in amounts rather than shares once credits enter:
platform-shared already spread.Billing also has a Dedicated Usage view, broken down by model and API key in the same way as the serverless one. Give it its own line per team. A dedicated endpoint is billed for the time it spends in Running status, so its cost follows the deployments a team keeps running rather than its request counts, and folding it into the serverless request shares would shift cost toward teams that only use the serverless API.
Use UTC on both sides. The usage view offers Local Timezone or UTC, and a ledger in one zone compared against a report in another moves late-evening requests into the wrong day, and on the last night of the month into the wrong month.
Create one key per team and environment in the GMI Cloud console and add the ledger write to your request wrapper, so the first close has request-level records to reconcile against. For volume commitments, or billing terms that fit your finance process, speak with GMI sales.
Colin Mo
GMI Cloud helps you architect, deploy, optimize, and scale your AI strategies
