Skip to main content
Version: 1.7.0

Model Pricing

The control plane calculates request cost from the usage it observes and the price associated with the upstream provider and model. Most models are priced on token counts; models billed by duration are priced on audio length. Configure a pricing override when a model has no catalog price or when your organization uses a different rate. Prices can also be tiered by input length or set per service tier, and a routing model can carry a model-group price and an off-peak discount of its own.

Pricing affects the spend shown in Usage and the totals evaluated by budgets. Prompt and completion rates can also affect target ordering for least_cost routing groups. Pricing does not change what the upstream provider charges.

Choose the Organization Currency​

Each organization records every amount in one currency: US dollars (USD, the default) or Chinese yuan (CNY). Owners and admins choose it in Settings → Currency; see Organization Currency.

Prices are entered by hand in the organization's currency. AISIX has no exchange rate and converts nothing:

  • The models.dev catalog is priced in USD, so it applies only to a USD organization. In a CNY organization, catalog prices are not used anywhere: not to bill requests, not to rank least_cost targets, not as price hints in the model form, and not in the Catalog tab of the Model pricing page. A model the organization has not priced has no price, so its requests record no cost and least_cost ranks it last. Set a price for every model you use.
  • Switching the currency does not convert recorded history. Usage costs, budget limits, budget spend, and prices keep their numbers and are read in the new currency from then on.
  • Admin API field names keep their _usd suffix, such as prompt_usd_per_1m, cost_usd, and limit_usd, but carry the organization's currency. GET /model_pricing returns the currency in its currency field.

The currency also appears wherever AISIX reports money: the dashboard's amounts, the budget rejection message, budget alert notifications, the currency field of the alert webhook document, and the currency column of an AISIX Enterprise organization backup.

How AISIX Resolves Prices​

AISIX applies the configured rates without hidden multipliers. Each usage event resolves a price by the exact (provider, model name) pair:

  1. An organization override wins when it matches the provider and model name.
  2. Otherwise, in a USD organization, AISIX uses the matching catalog default from models.dev. A CNY organization skips this step.
  3. If neither source matches, the usage event retains its reported usage but records zero spend.

Four rules then adjust the result:

  • A request addressed to a routing model that has a model-group price bills at that price instead, apart from the exceptions described there.
  • When the price that applies carries service-tier rates and one of its entries names the tier the upstream reported serving the request at, that entry's rates replace the price's base token rates.
  • A request addressed to a routing model that has an off-peak discount and completes inside one of its windows has its cost multiplied by the discount.
  • A request answered from the gateway's response cache costs 0, whether it was addressed to a direct, embedding, or routing model. Its usage event keeps the replayed token counts and the cache-savings counters. Earlier control-plane versions billed a cache hit on a direct model at the model's full price.

Catalog refresh behavior depends on how pricing synchronization is configured. In online mode, the control plane refreshes the catalog at startup and every 24 hours. If a refresh fails while the catalog is still empty, such as on a host that cannot reach models.dev, the control plane loads the catalog snapshot bundled in its image instead, and later successful refreshes update it. An existing catalog is never replaced by the snapshot. A refresh writes only the catalog rows whose prices changed, so a catalog row's Updated time on the Model pricing page records when its price last changed, not when the catalog was last refreshed. By default, the AISIX Enterprise Docker Compose package loads the bundled catalog snapshot at startup, even when it has internet access. To enable online synchronization for that package, see Pricing Catalog.

Within a matching price, AISIX calculates token and duration cost independently, then adds the two terms. Token pricing uses the prompt and completion rates, with the cache and reasoning fallbacks described below. Duration contributes only when the event reports audio length and Audio per minute is nonzero.

Cost is calculated and stored when the usage event is recorded. A pricing change applies to later events and does not re-price historical usage.

The cost the control plane records is the authoritative one. The gateway estimates a cost of its own only for Realtime sessions and Batch jobs, from the target model's flat input and output rates, without tiers, service-tier rates, model-group prices, or off-peak discounts, and in the organization's currency despite the usd in its names. That estimate appears as cost_usd on those usage events and in the aisix_llm_spend_micro_usd_total metric for Realtime sessions. Every other request carries a cost of 0 from the gateway.

How Reasoning Tokens Are Billed​

Upstreams count reasoning in two different ways. OpenAI, for example, counts it inside completion_tokens and names the reasoning part separately. Gemini on the Vertex AI adapter can report its thinking tokens beside the completion instead. Usage events keep the counts as the upstream reported them, so the control plane decides per event which accounting applies, using the total the upstream itself reported (total_tokens):

  • Reasoning beside the completion. This applies when total_tokens and reasoning_tokens are both greater than zero, and total_tokens equals prompt + completion + reasoning tokens but not prompt + completion tokens. The whole of completion_tokens bills at the completion rate, and the whole of reasoning_tokens bills at the reasoning rate.
  • Reasoning inside the completion. Every other event, including every event without a reported total, is priced this way. reasoning_tokens bills at the reasoning rate, and the rest of completion_tokens, never below zero, bills at the completion rate. An upstream that reports more reasoning than completion is therefore billed for the reasoning it reported and nothing more.

Either way, a model with no distinct reasoning rate bills reasoning at its completion rate. For example, both of these events bill 20 tokens at the completion rate and 30 at the reasoning rate:

UpstreamPromptCompletionReasoningReported totalAccounting
Gemini on Vertex AI1002030150Beside the completion
OpenAI1005030150Inside the completion

Cached input is recorded as reported too. When cached_prompt_tokens exceeds prompt_tokens, no uncached input is billed rather than a negative amount.

A gateway at 1.4.0 or earlier reports no total_tokens, so its events are priced by the second rule, exactly as before. On a newer gateway, /v1/messages and /v1/completions record reasoning_tokens and total_tokens the same way /v1/chat/completions does, so reasoning tokens reaching those two endpoints bill at the model's reasoning rate. A gateway at 1.4.0 or earlier records no reasoning count on them. See Recorded Token Counts for what each counter holds.

Review the Prices in Use​

The Model pricing page opens on the In use tab. It lists the prices of the models your environments actually dispatch to, from every environment, together with every price the organization set itself:

  • Prices in use lists each priced (provider, model name) pair that a direct or embedding model names. A model whose model name is a * template is not listed, because it names no concrete model.
  • In use without a price lists the pairs in use that have no price. Requests to them record no cost until you select Set price and enter one. In a CNY organization, every pair in use that the organization has not priced appears here.
  • Model groups lists the routing models that carry a model-group price or an off-peak discount. Edit them on the model group.

The Catalog tab shows every price, including the catalog defaults. In a CNY organization it lists only the model names each provider offers, without catalog prices, so you can find a model and set its price.

In the Admin API, GET /model_pricing?view=in_use returns the same view: priced pairs in data, unpriced pairs in unpriced, and the model groups in model_groups. Paging applies to data only.

Identify a Missing Price​

Start with an expanded event in Request Logs, which shows the cost of each usage event or routing attempt to six decimal places. The aggregate Usage view rounds spend to two decimal places and shows only the top 10 environment/model rows. Therefore, zero spend or an absent model in Usage does not prove that pricing is missing. When checking a very low-priced request, generate enough token usage to make the expected cost visible before concluding that a price is missing.

A catalog price can be missing when:

  • The model runs on a self-hosted or reseller upstream that models.dev does not price.
  • The configured model name is a custom alias.
  • The provider offers a newer model that the catalog does not yet include under that provider.

In a CNY organization, a missing price usually means the organization has not priced the model yet, because catalog prices do not apply. Check In use without a price on the In use tab.

Before adding an override, note the provider and model name exactly as they are configured. A pricing row that differs from either value does not match the usage event.

Add a Pricing Override​

  1. Open Model pricing from the organization navigation.
  2. Select Add pricing.
  3. Enter the Provider and Model name exactly as configured on the model. The Provider field suggests known catalog providers but also accepts a custom value.
  4. Configure the basis the provider charges. Every rate is in the organization's currency:
    • For a token-priced model, enter the Prompt and Completion rates per 1M tokens and leave Audio per minute at 0.
    • For a duration-priced speech-to-text model, leave the token rates at 0 and enter the Audio per minute rate per minute of audio, such as 0.006.
  5. For a token-priced model, optionally enter distinct Cache read, Cache write, One-hour cache write, and Reasoning rates. To price by input length instead of one flat rate set, select Price by input-token tier; see Price by Input-Token Tier.
  6. To bill requests served at a fast or priority tier at their own rates, add them in Service tier prices (optional); see Price by Service Tier.
  7. Save the override.

The cache and reasoning rates price the upstream's prompt-cache reads, prompt-cache writes, and reasoning tokens. Cache write prices a five-minute write. A one-hour write, which the usage event records separately in its split by lifetime, bills as follows:

  • At the One-hour cache write rate, cache_write_1h_usd_per_1m in the Admin API, when the price sets one. It applies to the base rates only, which the first input-token tier shares: a higher input-token tier or a service-tier entry never uses it.
  • Otherwise, for a Claude model served by Anthropic, Amazon Bedrock, or Google Vertex AI, at twice the input rate in effect, including the rate of the input-token tier or service-tier entry that the request selects. This matches how those providers charge a one-hour write. AISIX recognizes such a model by the price's provider (anthropic, amazon-bedrock, google-vertex, or google-vertex-anthropic) and a model name that contains claude, ignoring case. A model name without it, such as a Bedrock application inference profile ARN, is not recognized as Claude.
  • Otherwise at the Cache write rate. This covers every other model, Claude served through Azure AI Foundry or a reseller, a request billed at a model-group price, and a request on the decision endpoints, where a decision-endpoint cache write rate also replaces the one-hour rate.

A write that the upstream does not split by lifetime bills entirely at the Cache write rate. Leave one blank, null in the Admin API, to fall back: cache tokens then bill at the prompt rate, and reasoning tokens at the completion rate. Enter 0 only to make that token class free. The same rate set, with the same fallbacks, applies to each price tier and to a model-group price.

Price by Input-Token Tier​

Some providers charge a higher rate for a long request. A tiered price selects its rates by the size of the request's input:

  • The input size is the request's input tokens, cache reads and cache writes included. Output length never changes the tier.
  • Each tier has an inclusive Up to (input tokens, inclusive) limit, and the limits increase from tier to tier. The last tier has no limit and covers every larger request. A tiered price has at least two tiers.
  • The whole request bills at the rates of the first tier whose limit covers its input. Tiers are not marginal: a request one token over the first limit bills every token at the second tier's rates.
  • Each tier carries the full rate set: prompt, completion, cache read, cache write, and reasoning.
  • The price's top-level rates equal the first tier's, and least_cost routing ranks targets on them.

For example, with a first tier up to 200000 input tokens and an unlimited second tier, a request with 150,000 uncached input tokens and 60,000 cache-read tokens has an input of 210,000 tokens, so the whole request, output included, bills at the second tier's rates.

In a USD organization, a catalog price carries the long-context tiers models.dev publishes for the model, and they refresh with the catalog. The catalog's base rates become the first tier, up to and including the first threshold, and each published threshold starts the next tier; the highest tier has no limit. The same rules as above select the tier: the whole request bills at the tier its input crosses into, and a request exactly at a threshold stays in the lower tier. A catalog tier that publishes no cache read, cache write, or reasoning rate inherits that rate from the first tier, so a long-context cache read is not billed at the full input rate. When a model's catalog tiers cannot be represented, its catalog price stays flat. An organization override replaces the whole catalog price, tiers included.

To configure tiers in the Add pricing dialog, select Price by input-token tier, then edit each tier's limit and rates, and use Add tier or Remove tier as needed. A tiered row shows a tier-count badge on the Model pricing page. Clearing the option makes the first tier the flat price again.

In the Admin API, send the tiers as the tiers array of PUT /model_pricing/precise or PUT /model_pricing. The top-level rates must equal the first tier's, otherwise the request is rejected. null is a flat price:

{
"provider": "google",
"model_name": "gemini-2.5-pro",
"prompt_usd_per_1m": 1.25,
"completion_usd_per_1m": 10,
"cache_read_usd_per_1m": 0.31,
"tiers": [
{"max_input_tokens": 200000, "prompt_usd_per_1m": 1.25, "completion_usd_per_1m": 10, "cache_read_usd_per_1m": 0.31},
{"max_input_tokens": null, "prompt_usd_per_1m": 2.5, "completion_usd_per_1m": 15, "cache_read_usd_per_1m": 0.625}
]
}

Decision-endpoint rates and Audio per minute are not tiered. They apply on top of whichever tier the request selects. Tiers are also available on a model-group price.

Price by Service Tier​

Some providers serve a request at a faster or cheaper service tier and charge a different rate for it, such as OpenAI's priority processing or Anthropic's fast mode. A price can carry service-tier rates that bill those requests at their own rates.

The tier that selects the rates is the one the upstream reports it actually served the request at, recorded as the usage event's service_tier. It is never the tier the request asked for. A request that asks for a fast tier but that the upstream serves at its standard tier bills at the base rates.

  • Each entry lists one or more tier names in match and carries a full rate set: prompt, completion, cache read, cache write, and reasoning. A blank cache rate falls back to the entry's own prompt rate, and a blank reasoning rate to the entry's own completion rate. An entry can also be tiered by input length, with the same rules as input-token tiers.
  • The event's service_tier is compared with every match value, ignoring case and surrounding whitespace. The entry that names it replaces the price's base token rates and input-token tiers for that request.
  • A request whose tier no entry names, or whose upstream reported no tier, bills at the base rates.
  • A price holds at most 16 entries, and an entry at most 16 match values of up to 256 characters each. A value can appear in only one entry of a price, ignoring case, so a reported tier selects at most one entry.
  • Decision-endpoint rates and Audio per minute have no per-tier values. They apply the same way whichever entry a request selects.
  • A response cache hit still costs 0, and a model group's off-peak discount multiplies the cost that the selected entry produced.
  • Service-tier rates affect recorded cost and budgets only. least_cost routing ranks targets on the base rates.

Use the provider's own tier names, because AISIX passes the reported value through as is. OpenAI's fast mode reports priority, and Anthropic's reports fast. To find the value your upstream reports, expand one of its requests in Request Logs and read Service tier.

To configure service-tier rates in the Add pricing dialog, expand Service tier prices (optional) and select Add service tier price. Type each tier name in Service tier names and press Enter, then enter the entry's rates. Remove service tier price deletes an entry.

In the Admin API, send the entries as the service_tier_prices array of PUT /model_pricing/precise or PUT /model_pricing. A save replaces the whole price, so a request that omits service_tier_prices or sends null removes them. The following price bills requests that the upstream served at priority or fast at one set of rates, and requests served at ultrafast at another. The rates are illustrative:

{
"provider": "openai",
"model_name": "gpt-5",
"prompt_usd_per_1m": 1.25,
"completion_usd_per_1m": 10,
"cache_read_usd_per_1m": 0.125,
"service_tier_prices": [
{"match": ["priority", "fast"], "prompt_usd_per_1m": 2.5, "completion_usd_per_1m": 20, "cache_read_usd_per_1m": 0.25},
{"match": ["ultrafast"], "prompt_usd_per_1m": 5, "completion_usd_per_1m": 40, "cache_read_usd_per_1m": 0.5}
]
}

Where the service-tier rates come from depends on the price:

  • In a USD organization, a catalog price carries the rates that models.dev publishes for the model's service-tier modes, and they refresh with the catalog. Each entry matches both the tier value that selects the mode and the mode's name, because an upstream can report either.
  • An organization override replaces the whole catalog price, service-tier rates included. An override without service-tier rates bills every request at its base rates, so enter in the override any tier rates you still want.
  • A CNY organization uses no catalog prices, so it enters service-tier rates by hand.

Service-tier rates are also available on a model-group price. A gateway at 1.6.x or earlier reports no service tier, so its requests always bill at the base rates.

Price a Model Billed by Audio Length​

Some speech-to-text models are billed per minute of audio rather than per token and report no token counts. Such a request records its audio length instead, and the Audio per minute rate turns that length into spend. A model left at 0 for this rate contributes no duration-based cost.

The current AISIX catalog does not supply duration rates, so there is no default to inherit: create the row with the provider and model name exactly as configured. For example, OpenAI currently lists whisper-1 at $0.006 per minute. At that rate, a 60-second transcription costs $0.006.

caution

Token and duration costs are additive. If an event contains both token usage and audio duration, and the matching price has nonzero rates for both, AISIX adds both terms. Configure only the usage basis that the provider charges.

Price the Decision Endpoints​

A pricing override can carry a separate set of rates for requests on the decision endpoints, /v1/systemone and /v1/decisions. Use it when a model is billed differently there than on its other endpoints, or to price a decision model the catalog does not list.

  1. In the Add pricing dialog, enter the base rates as usual.
  2. Expand Decisions pricing (optional). The section notes that its rates apply to requests on /v1/systemone and /v1/decisions, and that a blank rate uses the matching rate above.
  3. Enter the decision-endpoint rates you need, and leave the others blank.
  4. Save the override.

Each decision-endpoint rate you set replaces the matching base rate for those requests, whichever request format the caller used. A blank rate keeps the base rate. The cache and reasoning fallbacks then run over the rates in effect, so a decision request's cache tokens fall back to its decision-endpoint prompt rate when one is set. Leaving every rate blank stores no decision-endpoint rates.

In the Admin API, send the rates as the decisions object of the price, with the fields prompt_usd_per_1m, completion_usd_per_1m, cache_read_usd_per_1m, cache_write_usd_per_1m, and reasoning_usd_per_1m. A save replaces the whole price, so a request that omits decisions or sends null clears the decision-endpoint rates.

Decision-endpoint rates affect recorded cost and budgets only. least_cost routing still ranks targets on the base rates.

Price a Model Group​

A routing model can carry its own price, so that callers of the group pay one price whichever target serves them. Only routing models accept a model-group price; direct, embedding, ensemble, and semantic models reject it.

A request addressed to the group bills at the group price, whichever target serves it. The group price replaces the target's own price, and applies even when the target has no price. Two kinds of request addressed to the group bill at the serving target's own price instead, exactly as if the group had no price, because the group price has no rate for them:

  • Requests on the decision endpoints, /v1/decisions and /v1/systemone.
  • Requests that the target's price bills by audio duration.

A group price can carry its own service-tier rates. A request addressed to the group whose tier no entry of the group price names bills at the group price's base rates, never at a target's service-tier rates. The two exceptions above bill at the serving target's own price, including the target's service-tier rates.

The group price does not apply to a request addressed to a target directly, or to a request forwarded by a passthrough route, even if its model field equals the group's name. It affects recorded cost and budgets only: least_cost routing still ranks targets by their own prices.

To set it, open the routing model's create or edit form and select Bill requests to this group at a group price in Model group price (optional). Enter the rates in the organization's currency, optionally as tiers and with service-tier rates. Clearing the option removes the price.

In the Admin API, send the rates as the price object of the routing model, with the same rate fields, optional tiers, and optional service_tier_prices as an organization price. A PATCH with "price": null removes it:

{
"price": {
"prompt_usd_per_1m": 2.5,
"completion_usd_per_1m": 10,
"cache_read_usd_per_1m": 1.25
}
}

Discount a Model Group Off-Peak​

A routing model can discount the requests addressed to it during off-peak hours. An off-peak discount is a set of weekly windows and a multiplier between 0 and 1, exclusive:

  • timezone is an IANA timezone name, and it defaults to Asia/Shanghai.
  • Each window has an inclusive start from 00:00 to 23:59 and an exclusive end from 00:01 to 24:00. 00:00 to 24:00 is a full day.
  • A window whose start is later than its end crosses midnight.
  • weekdays restricts a window to ISO weekdays, 1 for Monday to 7 for Sunday. Omit it for every day. For a window that crosses midnight, weekdays matches the day the window starts: 22:00 to 06:00 on weekdays 1 to 5 covers Friday 22:00 to Saturday 06:00, but not Monday 00:00 to 06:00.
  • Windows may overlap. A request inside any of them is discounted.

Whether a request is off-peak is decided by when it completed, read in the discount's timezone. Public holidays and make-up workdays are not considered.

The multiplier applies to the request's whole recorded cost, whichever price produced it: the group price, including its tiers, or the serving target's own price, including the decision-endpoint and audio-duration cases above. A group with an off-peak discount and no group price discounts its targets' prices. A cache hit stays free. The same scope as the group price applies: requests addressed to a target directly or forwarded by a passthrough route are not discounted, and least_cost ranking is unaffected.

The following discount halves the cost of requests that complete between 22:00 and 06:00 starting on a weekday, and all weekend, in China Standard Time:

{
"off_peak": {
"timezone": "Asia/Shanghai",
"windows": [
{"start": "22:00", "end": "06:00", "weekdays": [1, 2, 3, 4, 5]},
{"start": "00:00", "end": "24:00", "weekdays": [6, 7]}
],
"multiplier": 0.5
}
}

A request that completes at 23:00 on Friday, at 05:30 on Tuesday, or at any time on Sunday is discounted. A request that completes at 05:30 on Monday is not: that time belongs to a night that started on Sunday, which the first window does not cover, and the weekend window ends at Sunday 24:00.

In the console, select Discount requests to this group off-peak in the routing model's Off-peak discount (optional) section, then set the timezone, the windows, and the multiplier. Clearing the option removes the discount. In the Admin API, send the off_peak object on the routing model; a PATCH with "off_peak": null removes it.

Verify the Override​

For the simplest verification, send a new request directly to the matching model, then expand the event in Request Logs. For a token-priced model, generate enough token usage to produce a visible cost. For a duration-priced model, use an audio sample with a known or sufficiently long duration. Confirm that the event shows the expected model and event cost. Request Logs does not currently display the measured audio duration, so calculate the expected duration cost from the sample length.

If you verify a routed or ensemble request instead, find the event or attempt rows that share its request ID. Add their costs before comparing the total with the expected cost.

Request Logs shows six decimal places. If the expected event cost rounds to zero at that precision, generate enough token usage to make the cost visible at that precision.

After sufficient traffic, you can also confirm aggregate spend in Usage. Usage rounds spend to two decimal places and shows only the top 10 model rows, so it is less reliable for verifying a single low-cost request.

Historical rows do not change after the override is saved. Compare an event created after the change rather than expecting an earlier zero-cost event to be recalculated.

Edit or Reset a Price​

Edit a row to change the rates used for later events. Reset to catalog default removes the organization override. In a USD organization, if a catalog price exists, it takes effect again on the next usage event. In a CNY organization, the pair becomes unpriced.

A manually created duration-pricing row usually has no catalog default. Resetting that row removes its effective price, so later matching events record zero cost until another override is configured.

Next Steps​

Continue with Budgets to enforce spending limits, then configure Budget Alerts and Notifications. Use Logging and Auditing to investigate individual request outcomes.