Your plan is metered by its monthly usage limit, shown as a percentage in your dashboard. Chat on any model, image, audio and video generation, text-to-speech and dictation all count toward it; you do not need credits for any of them.
Credits are extra usage: they keep you going past your plan’s limit when you switch extra usage on. A credit is priced in your own currency (₹100 in India), and you can buy any whole number from 5 on the Billing page.
How a request is charged#
The three chat models are priced per token: input tokens, output tokens, and thinking tokens if you asked for reasoning. Image, audio and video generation are priced per job.
- A reservation is held before the request runs, so a call cannot start that you cannot pay for.
- When the turn finishes, the reservation is settled against the real token counts. The settled figure is almost always lower.
- A request that fails is refunded and logged at zero. You are not billed for our outages.
No model is free
Every model is metered against your plan’s usage limit — Bala is the cheapest, not free. When the limit is reached the next request returns402 with code: "usage_cap_reached", unless extra usage is on and you have credits.Seeing what a call cost#
| Endpoint | Where the cost appears |
|---|---|
| Chat, non-streaming | credits_used and credits_remaining in the response body. |
| Chat, streaming | The final usage chunk — you must send stream_options.include_usage. |
| Images, transcription | credits_used in the body. |
| Speech | Headers X-Credits-Used and X-Credits-Remaining — the body is audio. |
| Async media jobs | credits_reserved on the 202, credits_charged when you poll the task. |
X-Credits-Reserved: 0.40 # held before the request runsX-Credits-Used: 0.31 # what it actually cost (media routes)X-Credits-Remaining: 12.19
Reserved is not charged
X-Credits-Reserved is the hold, not the price. If you bill your own customers, use the settled credits_used — the reservation is deliberately generous and will overcharge them.Checking your balance#
curl https://ai.upfyn.com/v1/me \-H "Authorization: Bearer $UPFYN_API_KEY"
{"plan_id": "ultra","plan_active": true,"total_credits": 12.50, // credits you can spend on extra usage"subscription_credits": 0.00, // plans are metered by their usage limit, not credits"topup_credits": 12.50, // bought separately, does not expire monthly"credits_reset_at": "2026-09-01T00:00:00.000Z","requests_30d": 1842,"credits_used_30d": 7.50}
Your usage limit and your credits
- Usage limit — your plan’s monthly allowance, measured as a percentage. It resets each cycle.
- Credits — bought separately, priced in your currency. They pay for extra usage past the limit, and do not expire with the cycle.
Running out#
Reaching your plan’s limit returns 402 with code: "usage_cap_reached". A request past the limit with extra usage on, when you have no credits, returns 402 with code: "insufficient_credits". Both carry an action_url you can send the user to. Neither is an auth error — retrying will not help, and neither will a new key.
Watch the balance, not the errors
Readcredits_remaining off responses you are already making and alert on a threshold. Finding out you are empty from a 402 in production is finding out too late.Attributing spend#
- Separate API keys per service or environment — the cleanest split, and it shows up in your logs.
upfyn_tagon a request (or theX-Upfyn-Tagheader) tags it for your own reporting. It is never sent to the model.X-Upfyn-Appattributes usage to one of your developer apps.
Per-day and per-model breakdowns live at /v1/me/usage/daily?by=model, and the same numbers are on your Usage and Logs pages.
Spending less#
- Use the smallest model that works. Bala is a fraction of Rishi for text.
- Do not set a reasoning effort on tasks with nothing to reason about — extraction and classification pay for thinking they do not use.
- Cap
max_tokens. It bounds the worst case rather than trusting the model to be brief. - Bound your tool loops. A runaway agent is the most expensive bug you can ship.
