Billing and Rupiah
kenari bills usage in Rupiah from a prepaid balance. There are two ways to pay, depending on who owns the key that serves the request: the kenari key pool, or your own key.
Two ways to pay
Section titled “Two ways to pay”- Metered (default): the request runs on kenari’s provider key pool. Tokens are counted, then deducted from your Rupiah balance.
- BYOK: the request is served by your own key. It is free, and usage is still recorded with zero cost. See BYOK.
Prepaid balance
Section titled “Prepaid balance”Top up with QRIS from Rp 1.000, without an overseas credit card. Balance is added after payment is complete.
A paid request without enough balance returns HTTP 402. The message includes
the available balance and this request’s own worst-case reserve ceiling (input
estimate plus max_tokens times the output rate), so it’s immediately clear
whether the fix is a lower max_tokens or a top-up:
{ "error": { "code": "insufficient_balance", "message": "insufficient balance: available Rp 19,589; this request reserves up to Rp 21,500 worst-case (input estimate + max_tokens x output rate). Lower max_tokens or top up at https://kenari.id/pay" }}Payment page
Section titled “Payment page”Balance top-ups and subscription payments happen on a dedicated payment page. Each invoice has its own link, so the page can be opened again while the invoice is still valid and the payment status updates automatically.
Crypto payments
Section titled “Crypto payments”Besides QRIS, balances and subscriptions can be paid with crypto (BTC, ETH, USDT, and others). Invoices are issued in US dollars using the platform exchange rate when the invoice is created, then the Rupiah balance or subscription package is activated for the selected amount. The minimum crypto payment is USD 1. Network processing fees are paid by the payer when paying the invoice. Payments are processed by OxaPay. Balance is added automatically after the network confirms the payment (usually within a few minutes).
Money unit
Section titled “Money unit”Internally, balances and prices are stored in micro-Rupiah, which means Rupiah multiplied by 1.000.000. The dashboard and pricing page show regular Rupiah, so you do not need to calculate this conversion yourself.
Model prices
Section titled “Model prices”Prices are set in micro-Rupiah per 1 million tokens, with four dimensions:
| Dimension | Description |
|---|---|
input | prompt tokens sent |
output | tokens generated by the model |
cache-read | tokens read from cache |
cache-write | tokens written to cache |
Cost is calculated per dimension:
biaya = token * rate / 1.000.000Cache-write is billed at its own rate when set. If not set, cache-write uses the input rate.
See active prices in Models and prices, or fetch them directly from GET /v1/models.
No output, no charge
Section titled “No output, no charge”Sometimes a model does not generate anything: a content filter holds back the answer, the upstream returns an empty response, or the connection drops before one token is sent. When that happens, you are not billed.
The rule is simple. If a request finishes without any output tokens, the cost is Rp 0, even if the prompt was already processed. This applies to all payment methods: metered balance, subscription quota, and free plan allowance. The request still appears in usage history with zero cost, so you know it happened without reducing the balance.
In short, you pay for answers that arrive, not for failed attempts.
Free version
Section titled “Free version”Models with the :free suffix, for example step-3-7-flash:free, are billed at Rp 0. In exchange, there is a per-account request limit per minute. Limit details and the free model list are in Models and prices.
Free model daily quota
Section titled “Free model daily quota”Besides the per-minute limit, :free models also carry a daily request allowance with three tiers, based on account status:
| Tier | Applies to |
|---|---|
| Solo | new accounts, before any top-up reaches the threshold |
| Payer | accounts that have topped up balance past that threshold |
| Subscription | accounts with an active plan. Some plans carry their own daily quota, different from the default |
Current quota, RPM, and top-up threshold values are on the pricing page (also via GET /api/public/pricing), since the operator can tune them at any time. The Subscriptions page also shows these values. Running out of daily quota returns HTTP 429 with a Retry-After header and reason free_quota_daily.
Subscriptions (optional)
Section titled “Subscriptions (optional)”Subscription packages provide window quotas for specific models: 5 hours, weekly, or monthly. As long as the window quota remains, requests use that quota instead of balance.
When the window quota is used up and PAYG is not active, requests return HTTP 429:
{ "error": { "code": "plan_limit_reached", "message": "plan limit reached" }}Set and change packages in the dashboard.
That rejection covers every endpoint, not just chat. A package usually scopes to chat models, while embeddings, images, audio, video, rerank, System One, and document reading are always paid from balance. Once the package quota is spent and the keep-using-balance option is off, those endpoints return HTTP 429 too rather than quietly drawing down your balance. While package quota remains, they all run as usual and are still paid from balance.
Related status
Section titled “Related status”See Errors and status for details on 402 insufficient_balance and 429 plan_limit_reached.