Pricing & billing
You pay at the price listed by the provider that served your request, in the unit that request is sold in — per token for most models, and per second of audio for a transcription. There is no subscription and no markup on inference: the listed price is the billed price.
Prices and billing units
Prices are set by each provider per endpoint and published as exact decimal strings —
"0.0000004" is $0.40 per million tokens. The catalogue shows them wherever the endpoint appears, and
the model list compares them across providers. Common published billing units:
| Price key | Unit | Billed when |
|---|---|---|
prompt | token | Every uncached prompt token. |
completion | token | Every completion token, reasoning included unless priced apart. |
input_cache_read | token | Prompt tokens served from the provider's cache (cache read). |
input_cache_write | token | Prompt tokens written to the provider's cache. |
internal_reasoning | token | Reasoning tokens, when the provider prices them separately. |
request | request | A flat per-request charge. |
image_output | image | Delivered output images, at the rate selected for the supported settings. |
image_megapixel | megapixel | Delivered image area divided by 1,000,000 under a linear area tariff; a 512×512 image consumes 0.262144 units. |
video_second | second | Delivered video duration, including fractional seconds. |
mesh_output | mesh | Delivered meshes, at the rate selected for the supported settings. The face count is geometry the request chose and is billed by nothing. |
image_output_token | token | Output image tokens; a Heimdallm catalogue extension. Positive rates are refused by dedicated media routes without a finite image-token reservation bound. |
audio_second | second | Audio input, and audio an endpoint generates in a reply. Published on /models as audio_second. |
character | character | Characters of the input text a speech endpoint synthesizes, counted from your request. Seconds of audio produced are not billed. |
Three rules keep this honest:
- Cache reads are never billed above the declared price, and never silently below it. When an
endpoint publishes
cached_prompt, cached tokens are billed at that (lower) rate and reported inusage.prompt_tokens_details.cached_tokens. When it does not, cached tokens are billed at the ordinarypromptrate. - A unit without a price is never billed at zero — it is recorded as unpriced and flagged for review rather than invented into either party's favour.
- A completion you did not receive costs nothing. A reply that ends normally, reports completion tokens and delivers no content, tool call, refusal or reasoning on any channel is charged for its prompt alone: the completion and reasoning tokens are recorded as unpriced. One character of reply is a reply, and a request you cancelled or one that ended at your token limit is billed as usual.
What a request costs
Every inference response carries the exact charge in usage.cost (USD, as a JSON number), computed
from the serving endpoint's price table and the measured usage:
"usage": {
"prompt_tokens": 1204,
"completion_tokens": 96,
"total_tokens": 1300,
"prompt_tokens_details": { "cached_tokens": 1024 },
"cost": 0.0000861
}
On a streaming response the same object arrives in the final chunk before data: [DONE]. The
OpenRouter-style request flag usage: { "include": true } is accepted for compatibility, but usage
accounting is always included either way.
Each generation's full billing record — token counts, cost, latency, finish reason — can be fetched
afterwards with GET /generation?id=... using the
X-Generation-Id response header.
Failed requests are not billed for tokens. When a generation ends in an error before producing any output, its token charges are waived. Partial output that did stream before a mid-stream failure is billed for the tokens actually generated.
Credits
Billing is prepaid. Deposits credit your account balance; every request settles against it. Check the balance of the account your key belongs to:
// GET /credits
{ "data": { "total_credits": 100, "total_usage": 12.3 } }
Before a request runs, Heimdallm places a hold for a conservative estimate (your prompt plus the
completion ceiling, at the endpoint's prices) and settles the hold to the actual cost when the
request finishes. Where an endpoint prices reasoning tokens apart from completion, the completion
ceiling is held at whichever of the two rates is higher, because reasoning tokens come out of the
same ceiling and how much of it they take is not known until the answer arrives. A request whose
estimate exceeds the spendable balance — balance minus outstanding holds — is rejected with 402
before any provider is contacted:
{
"error": {
"code": 402,
"message": "Insufficient credits to run this request.",
"metadata": {
"error_type": "payment_required",
"required": "18400000000000000000000",
"spendable": "2100000000000000000000"
}
}
}
(required and spendable are integer strings in the internal 10⁻²⁴ USD unit.)
Tip: a large max_tokens raises the hold, up to the room the endpoint's window leaves beside your
prompt — the hold is taken on the request as the endpoint receives it, so a ceiling trimmed to fit is
held at its trimmed size. If small balances are being rejected on long-context requests, lower
max_tokens to what you actually need.
Every movement — deposits, usage, refunds, adjustments, referral rewards — appears in the ledger in your account, newest first. How to fund the balance is covered in Deposits; how referral rewards accrue is covered in Your account. Referral credits spend like any other credit and are never paid out.
Spend limits
Three independent ceilings can each stop a request; the request is refused when it would push any of them over:
| Scope | Set where | Typical use |
|---|---|---|
| API key | Key settings, per key | Cap one integration or one teammate. |
| Workspace | Workspace settings | Cap a project or environment. |
| Account | Account / organization settings | Cap total spend of the whole account. |
Each limit takes an optional reset window — daily, weekly or monthly, measured in UTC — or
applies to lifetime spend when no window is set. Spend counted against a window includes
outstanding holds, so parallel requests cannot overshoot a ceiling together. A breached limit
answers 402; metadata.scope names which ceiling bit (key, workspace or account) and
metadata.limit_reset its window:
{
"error": {
"code": 402,
"message": "The API key spend limit has been reached.",
"metadata": {
"error_type": "payment_required",
"scope": "key",
"limit": "10000000000000000000000000",
"used": "10020000000000000000000000",
"limit_reset": "monthly"
}
}
}
(limit and used are integer strings in Heimdallm's internal fixed-point unit, 10⁻²⁴ USD —
useful for comparing against each other, not as display values.)
GET /key reports the authenticated key's own limit, remaining allowance and usage per window —
see Key & activity.
Money is exact
Internally every amount is exact decimal arithmetic on the provider's published strings; nothing is
rounded until the number leaves the API. Where the wire shape requires JSON numbers (usage.cost,
GET /key, GET /credits), the one lossy conversion happens at serialisation. The session-plane
ledger your dashboard reads reports exact decimal strings.