uttapen

LLM API pricing in toman: pay only for real token usage

Per-million-token prices in toman, charging on each request's real usage, free failed requests, the hold-and-settle cycle, and the usage report API.

Updated: September 7, 2026

Every request is priced in toman and paid from your wallet. There is no monthly subscription, no minimum spend and no hidden fee: you top up, and each request deducts exactly what it used. No international card and no foreign currency account are involved. This page explains where the prices live, how they are applied, and where to look up what you have spent.

Per-model pricing

Each model has its own price for input tokens and output tokens, shown on the models pages in toman per one million tokens. Some models have additional components: a price per input image, a price per generated image, a flat price per request (web search, for example), and a separate price for reasoning tokens. All of them are listed on the same page.

Toman prices are not fixed forever — they are refreshed as market conditions and the models' own list prices change. Every request settles at the price that was in effect the moment it was sent; a price change mid-request never affects it. A price history is kept per model so any invoice can be defended.

The same numbers are available from the API, for when you want to estimate cost in your own code or automatically pick the cheaper model:

curl https://api.uttapen.ir/v1/models/openai/gpt-5-mini
{
  "id": "openai/gpt-5-mini",
  "context_length": 400000,
  "pricing_currency": "IRT",
  "pricing": {"prompt": "…", "completion": "…"},
  "uttapen_pricing": {
    "prompt_toman_per_1m": "…",
    "completion_toman_per_1m": "…",
    "image_toman": "0",
    "image_output_toman": "0",
    "request_toman": "0",
    "cache_read_toman_per_1m": "…",
    "is_free": false,
    "updated_at": "2026-09-06T22:19:22Z"
  }
}

pricing is the toman price of a single token (for exact arithmetic), and uttapen_pricing is the same figure per one million tokens, the way you see it on the model page. Values are strings so decimals are never lost. GET /v1/models works without a key and is cached for 5 minutes.

Real usage, not an estimate

The final amount for a request is computed from the usage the model itself reports for that request: input and output tokens, reasoning tokens, cached tokens (which are cheaper), images and every other component. We do not count tokens ourselves and we do not recompute them, because each provider counts with its own tokenizer and may apply tiered pricing or caching. The usage object in the response is exactly what you paid for.

A practical consequence: the same model consumes more tokens for Persian than for English (1.5 to 3 times as many, depending on the tokenizer). Before committing to a model, send one realistic sample and look at usage.prompt_tokens.

Hold, settle, release

The life cycle of money inside one request:

  1. Hold. Before the request goes to the model, an amount is set aside from your available balance as a ceiling on what the request could cost. It is a deliberately conservative estimate, so it is normally larger than the final charge; reasoning requests get extra headroom. If your available balance is below that amount you get 402 insufficient_balance and the request is never sent upstream.
  2. Response. Until the response finishes, the held amount sits in held_toman and your main balance is untouched.
  3. Settle. When usage arrives, the real amount is deducted from the balance and the whole hold is released. This happens in a single atomic transaction.
  4. Error. If the model returns an error or no response arrives, the hold is released in full and nothing is charged.
  5. Disconnect mid-response. Only the usage up to the moment of the cut is settled; if the usage report does not arrive immediately, a background job asks the provider for it and settles within a few minutes. Until then the amount stays in held_toman.

So available_toman (which is balance_toman minus held_toman) is the number that decides whether your next request goes through — not balance_toman. If you run several streams at once, the holds add up.

When the final charge exceeds the hold

The hold is an estimate. If the model produces more tokens than expected — you left max_tokens unset and the model wrote up to its own limit — the real amount can end up above the hold. The real amount is still deducted in full, and the balance can go briefly negative. Until your next top-up every request, free models included, returns 402. The prevention is simple: send a realistic max_tokens, which also keeps the hold small.

Seeing the cost of each request

Non-streaming — on the response:

X-Uttapen-Cost-Toman: 6.659688
X-Uttapen-Balance-Toman: 97564.413809
X-Uttapen-Request-Id: 01a078dd-853e-7480-aa83-262d3239e6a2

Streaming — send X-Uttapen-Include-Meta: 1 and a uttapen.meta event arrives before [DONE] with cost_toman, balance_toman and hold_toman (streaming).

Amounts are stored and reported with 6 decimal places; a small request can cost less than one toman. Rounding happens only in the dashboard display, never in the accounting.

Usage reports through the API

curl "https://api.uttapen.ir/v1/uttapen/usage?from=2026-09-01&to=2026-09-08&group_by=model" \
  -H "Authorization: Bearer $UTTAPEN_API_KEY"
{
  "from": "2026-09-01T00:00:00Z",
  "to": "2026-09-08T00:00:00Z",
  "group_by": "model",
  "data": [
    {"bucket": "openai/gpt-5-nano", "requests": 89, "prompt_tokens": 4719345, "completion_tokens": 1969, "charge_toman": "2231.443689"},
    {"bucket": "openai/gpt-5", "requests": 3, "prompt_tokens": 30, "completion_tokens": 72, "charge_toman": "99.895314"}
  ]
}
  • group_by is one of day, model, key. With day each bucket is a Gregorian date in UTC; with key it is the key id (the UUID you see on the keys page), plus the value chat for usage from the dashboard chat.
  • Only settled requests are counted; open holds live in held_toman.
  • from and to take a date or an ISO timestamp; the default range is the last 30 days up to now.
  • A key only sees the requests of its own user, but the report covers all of your keys.
  • The same data is charted in dashboard → usage, and every individual transaction (top-up, charge, refund) is listed in the wallet.

Top-ups and invoices

Top-ups go through the Zibal payment gateway with Iranian bank cards, minimum 50,000 and maximum 50,000,000 toman per transaction. After a successful payment the amount lands in balance_toman immediately and a printable invoice appears in dashboard → invoices. If for any reason a payment goes through but the balance does not move, send the payment id from the wallet page to support: a Zibal payment that has been verified is never applied twice and never lost.

Summary

  • Each model's toman price per 1M input/output tokens is on its model page and in GET /v1/models.
  • You are charged for the real usage reported for that specific request.
  • Hold before, settle after, errors free.
  • X-Uttapen-Cost-Toman or uttapen.meta per request, GET /v1/uttapen/usage for aggregates.