AI model prices¶
Specivo values AI usage at API prices: what the same tokens would have cost on a provider's pay-as-you-go price list. The prices live in a table administrators manage under Admin → AI model prices. Each version of Specivo ships the list prices of several hundred models, and you can add your own, in any enabled currency.
Usage covered by a flat-rate plan such as Claude Max is still valued at these prices, to compare it with the plan's fee; record the plans under AI subscriptions.
Prices change over time, so the table is a history. Every price is valid for a period, and usage is always priced with the price that was valid at its own time. Changing a price never rewrites an old one.
What a price holds¶
All prices are per one million tokens, in one currency. Usage is counted in token classes:
| Price | Applies to |
|---|---|
| Input | Fresh input tokens, not counting cache reads and writes |
| Output | Generated tokens |
| Cache write, 5 minutes | Prompt cache writes kept for five minutes |
| Cache write, 1 hour | Prompt cache writes kept for an hour. When a provider publishes none, the bundled price is twice the input price. |
| Cache read | Prompt cache hits |
| Reasoning | Reasoning ("thinking") tokens reported apart from output. Empty means they cost the same as output. |
Any other empty price means that kind of token is not priced. Usage with such tokens is shown
as partly priced, never as if those tokens were free. A price of 0 is a real price: free.
Long context¶
Some providers charge more once a request carries a long context, for example above 200,000 tokens. A price can hold a threshold and a second set of prices for that tier. A request whose context (input plus cache reads and writes) is above the threshold is billed entirely at the long context prices; exactly at the threshold it is not. A long context price left empty falls back to the normal price of the same kind.
Reporters send the tokens of such requests in a separate bucket, long_context_tokens, next to
the normal tokens of the other requests. The two buckets never overlap: each token is priced
once, at the prices of its own tier, and token totals add both buckets.
Local models¶
A price can be marked as a local model, with an optional baseline model: the paid model whose prices value the local model's usage, to show what running it locally saved.
Where prices come from¶
Each price has a source:
| Source | Where it comes from |
|---|---|
| Bundled | The price list shipped with this version of Specivo |
| Admin | Entered by an administrator on the page or through the API |
Where a bundled price and one you entered are both valid, yours wins.
The bundled prices¶
The bundled list comes from LiteLLM's model price list (MIT License), trimmed to the text models of the providers coding agents use directly: Anthropic, OpenAI, Google Gemini, xAI, DeepSeek, Mistral, Moonshot, Z.ai and Alibaba DashScope. The card Bundled prices shows how many models this version carries and the date the list describes.
LiteLLM publishes current prices only, without their history. So the bundled list is loaded append-only:
- A model that is new to your instance gets its first price valid from 1 January 2000 (UTC), not from the list's date, so usage logged before the list was made is priced too. This applies when the model has no earlier bundled period and no price you entered that starts before it.
- An unchanged price changes nothing.
- A changed price ends the bundled period at the new list's date and starts a new one. The old period stays, so older usage keeps its old price.
- Prices you entered are never touched, and neither is a bundled price you deactivated.
The list is loaded when Specivo is installed, and again whenever a worker starts, so an upgrade that brings a newer list applies it by itself. Load bundled prices now does the same on demand.
Instances that stored a model's first bundled period from the list's date under an earlier version get it moved back on the next load, and the entries from before the old start are priced again.
Usage from before the first period of a model is not priced: Specivo never falls back to a later price for older usage. If you need an older price than the bundled one, enter it as a past period (below); prices you enter win over bundled ones.
Unpriced usage in reports¶
When some entries have no price for their model and date, they count as 0 and the report says so next to its totals: N of M entries has no price for its model and date, so it counts as 0, with the models concerned and a link to Add or load prices. In the charts, periods with such entries are marked with an asterisk. Add a price for the model that covers those dates (or load the bundled prices), then use Recompute past usage to value the entries already logged.
Find a price¶
The list shows by default the prices valid now, one line per model and source. Filter by provider, by part of a model name or alias, by source, or by status (active or deactivated), and switch to All periods to see past ones too. Click a model to open its price history: every period, bundled and yours, newest first. The period in use right now is marked In use now.
How a model name is matched¶
Tools report model names in different shapes. Before matching, Specivo:
- lowers the case and trims spaces;
- drops provider prefixes such as
anthropic/,openai/,google/ormodels/(Anthropic/Claude-Sonnet-4-5becomesclaude-sonnet-4-5); - looks for a model of that name, then for a model that lists it as an alias.
Among the prices valid at the usage's time, an exact model name beats an alias, and a price you entered beats a bundled one. If nothing is valid then, the usage is unpriced.
Change a price¶
Prices are never edited in place. A price change is a new price from an instant:
- Open the model from the list.
- Under New price from…, the form is filled with the current prices. Change what changed.
- Set Valid from (UTC) to the instant the new price takes effect, and save.
The price you entered before for that model now ends at that instant, and the new one starts there. The two periods meet exactly: usage at the change instant gets the new price, usage a moment before gets the old one. All times are UTC.
To add a price for a model that has none, or to override a bundled price, use Add a price on the list page and type the provider and model.
Enter a past period¶
When a provider announces a price change late, or you need prices for usage from before the bundled list's date, enter a past period: fill in Valid until (UTC) as well. A past period must not overlap another price you entered for the same model; end or deactivate that one first.
Recompute past usage¶
AI usage is valued when it is logged, with the price valid at its own time, and keeps that value:
adding, ending or deactivating a price never changes usage that was already logged. When a price
you just entered starts in the past and usage was already logged in its period, the model's page
shows Recompute past usage with the number of entries and the range. Click Recompute these
entries to value them again in the background. Each entry is priced at its own time, so usage on
either side of a price change gets the price of its own period, never simply the latest price.
Entries whose value changes get a new revision, and the audit log records one
ai_usage_costs_recomputed event with the totals before and after.
Through the API, an administrator can recompute any range with
POST /api/v1/admin/ai-usage/recompute/ and a body such as
{"from": "2026-01-01T00:00:00Z", "to": "2026-06-01T00:00:00Z", "provider": "anthropic", "model": "claude-opus-4-6"}
(provider and model are optional; the model also matches its aliases). It answers 202 with the
task id and the number of entries in the range.
Other currencies¶
Pick any enabled currency for a price, for example CNY for a provider that bills in yuan, or EUR or THB for a contract price. Usage is then valued in that currency, and reports convert it with the exchange rates like any other amount.
End, deactivate or delete a price¶
Under Details on a period of the price history:
- Save end sets or clears the end of the period. Clearing it reopens the period.
- Deactivate takes the price out of use without deleting it; Activate puts it back.
- Delete removes a price you entered. Bundled prices cannot be deleted (they would come back on the next load); deactivate them instead.
- Aliases and the note (for example a link to the provider's announcement) can be edited at any time.
Once usage has been priced with a price, that price cannot be deleted, and its end cannot be moved to before that usage. Deactivate it instead. Neither its amounts nor its start can ever change: enter a new price.
Through the API¶
Everything on the page is available to administrators under /api/v1/admin/ai-model-prices/.
Prices are decimal strings such as "3.75",
never JSON numbers, and instants need a time zone offset (2026-06-01T00:00:00Z).
# Prices valid at an instant (given here in Asia/Bangkok time)
curl -H "Authorization: Bearer $TOKEN" \
"https://specivo.example.com/api/v1/admin/ai-model-prices/resolve/?model=claude-sonnet-4-5&at=2026-11-06T09:00:00%2B07:00"
# A new price from an instant: ends your previous price of the model there
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
https://specivo.example.com/api/v1/admin/ai-model-prices/ \
-d '{"provider": "anthropic", "model": "claude-sonnet-4-5", "currency": "USD",
"prices": {"input": "3", "output": "15", "cache_write_5m": "3.75",
"cache_write_1h": "6", "cache_read": "0.3"},
"effective_from": "2026-12-01T00:00:00Z"}'
resolve/ answers priced with the price, or unpriced. Other endpoints: GET / (list and
filter), GET /history/?provider=&model=, GET /providers/, GET, PATCH and DELETE /{id}/,
and POST /seed/ to load the bundled list.
Every change is written to the audit log.
Air-gapped installs¶
The bundled list is part of the image; nothing is downloaded. Enter or correct prices by hand as needed.