Skip to content
OpenRelay is in early access, and the /v1 API is stable. New capabilities ship in the changelog.
GuidesInference

Pricing & billing

How inference is billed, a prepaid balance, per-token metering with distinct input, cached-input, and output rates, and the usage and cost on every response.

Inference is prepaid and metered per token. You fund your organization's balance, and each request draws down from it based on the tokens it used.

Prepaid balance

Your organization holds a balance that pays for usage. Top it up in the dashboard. When the available balance falls below the spending floor, new inference requests are refused with 402 Payment Required until you add funds:

{
  "error": {
    "message": "insufficient balance; add funds to continue",
    "type": "insufficient_quota",
    "code": "insufficient_balance"
  }
}

Discovery is free: GET /v1/models is not balance-gated. Only billable requests like POST /v1/chat/completions require a funded balance.

Per-token metering

Usage is metered across token dimensions, each with its own rate:

DimensionWhat it counts
InputFresh prompt tokens sent to the model.
Cached inputPrompt tokens served from a prompt cache (billed at a reduced rate).
Cache writeMessages-only: tokens written into the prompt cache (cache_creation_input_tokens). Not reported on Chat Completions.
OutputTokens the model generates, including any reasoning tokens.

Rates are per token and vary by model. Cached-input tokens are billed at a lower rate than fresh input tokens. The total cost of a request is the sum of each dimension's token count multiplied by that dimension's rate.

Inference tiers

The same model is sold at three rates, depending on how fast you need the answer. Each tier is a multiplier on the model's Sync rate:

TierHow it runsMultiplierApplies to
SyncReal time: chat completions, messages, embeddings, and decisions calls answered on the request.1xEvery dimension
AsyncQueued, results delivered later. Coming soon, early access only.0.8x (20% off)Input, cached input, and output
Batch, standard priorityA JSONL job through the Batch API, completed within 24 hours.0.5x (50% off)Every dimension
Batch, expedited prioritySame as standard, but asks for the next free capacity slot.1xEvery dimension

Worked example for openrelay/gemma-4-31b, which the Batch API runs, per 1M tokens:

TierInputCached inputOutput
Sync$0.99$0.99$1.49
Async$0.792$0.792$1.192
Batch (standard)$0.495$0.495$0.745

Batch runs only on batch-eligible models; the others have Sync and Async rates only.

Async

Async is for work that does not need an answer on the open connection. You submit a request, it waits in a queue for capacity, and the result is delivered later rather than returned on the request. Async is billed at 80% of the Sync rate on input, cached input, and output.

Async is coming soon and is available as early access only. There is no public Async API yet. To request access, email sales@openrelay.inc. If you need discounted asynchronous work today, use the Batch API.

DeepSeek V4.1-Flash-1017

The Sync rates for openrelay/deepseek-v4.1-flash-1017-heretic are:

Input, per 1M tokensCached input, per 1M tokensOutput, per 1M tokens
$0.30$0.006$1.20

Cached-input pricing applies to prompt tokens the engine reports as cache hits in usage.prompt_tokens_details.cached_tokens. Other prompt tokens use the fresh-input rate. Reasoning tokens use the output rate.

Input-only models

Embeddings and Decisions generate no tokens, so their models have an input rate and no output line. Their usage carries prompt_tokens and total_tokens only, with no completion_tokens, and you are billed on prompt_tokens.

ModelAPI familyInput, per 1M tokens
openrelay/bge-m3Embeddings$0.013
openrelay/layaDecisions$0.020

Current rates

Per-model, per-dimension rates for Sync, Async, and Batch are published on the inference pricing page and in the dashboard. Always treat those as the source of truth for current prices.

Usage on every response

Every completion reports the token counts it was billed on in its usage object, so you can reconcile spend yourself. This section covers the Chat Completions usage shape; Messages uses Anthropic's field names and a different cache-accounting rule, covered on that page.

{
  "usage": {
    "prompt_tokens": 1024,
    "completion_tokens": 256,
    "total_tokens": 1280,
    "prompt_tokens_details": { "cached_tokens": 768 }
  }
}

These fields map onto the billing dimensions as follows:

usage fieldBilling dimension
prompt_tokens − prompt_tokens_details.cached_tokensInput (fresh)
prompt_tokens_details.cached_tokensCached input
completion_tokensOutput

For streaming requests, the same usage object is delivered on the final chunk: usage is always reported, so streaming requests are billed exactly like unary ones.

Cost on every response

Every Sync response also says what the request costs, in an openrelay object beside its usage:

{
  "usage": {
    "prompt_tokens": 1024,
    "completion_tokens": 256,
    "total_tokens": 1280,
    "prompt_tokens_details": { "cached_tokens": 768 }
  },
  "openrelay": { "cost_nano_usd": 203520, "priced_at": "online" }
}
FieldMeaning
cost_nano_usdWhat the request is billed, in nanoUSD (1 USD = 1,000,000,000 nanoUSD): the price of its usage at the model's rates, and the same amount added to your organization's usage. An integer.
priced_atonline: priced at the model's Sync rates.

The example is 256 fresh input tokens, 768 cached and 256 output on a model priced at $0.15, $0.015 and $0.60 per 1M tokens, so it costs 256 × 150 + 768 × 15 + 256 × 600, which is 203,520 nanoUSD (about $0.0002).

  • Unary responses also send the figure as an OpenRelay-Cost-Nano-USD header, for a client that reads headers only.
  • Streams carry the object on each chunk that carries usage, with the cost of the usage reported so far: for a stream read to its end, the last one is the bill. Streams send no header, because headers go out before any usage exists. Read the cost from the last chunk or event that carries it, not from a message an SDK assembles: the OpenAI Python SDK's chat.completions.stream() helper keeps whatever the first chunk carried, and the message the Anthropic Python SDK assembles carries none. See Streaming and Messages.
  • Batch results do not carry it. Batch work is priced when the batch finalizes, at the batch rate for its priority; the batch's usage object has its cost.

The figure is the bill for a completed response. A stream that is cut off, or ends with an error, after a chunk with a cost was sent is not billed, so the figure it sent never became a charge.

Batch requests

Requests run through the Batch API are metered per token exactly like Sync requests, in exchange for asynchronous, within-24-hour completion. The price depends on the batch's priority:

  • standard (the default) bills 50% of the Sync rate. The halving is applied to each dimension's line (tokens times the Sync rate), so a line can round down by at most half a nanoUSD.
  • expedited bills the Sync rate. The batch discount does not apply.

A batch's rolled-up token counts and cost are exposed on its usage object, and each result line carries its own per-request usage.

What is and isn't charged

  • Failed requests are not charged. A non-2xx result, or a streamed response that is interrupted before it completes, is not billed.
  • Account holds. If your account is paused because its available balance dropped below $0.50, or is under review, billable requests are refused with 403. See Errors.

On this page