Wallet, pricing and billing
Everything is prepaid, in paise, and the ledger is the source of truth.
Tone is prepaid. Calls, number purchases, monthly rentals and compliance verdicts all debit one wallet, and everything is in paise (₹1 = 100 paise) because money in floating point is money lost.
curl "$TONE_API/v1/wallet" -H "Authorization: Bearer $TONE_KEY"
curl "$TONE_API/v1/wallet/transactions" -H "Authorization: Bearer $TONE_KEY"
curl "$TONE_API/v1/wallet/usage?period=30d" -H "Authorization: Bearer $TONE_KEY"What a call costs
| Rate | What you get | |
|---|---|---|
| Full stack | ₹6.00/min | Telephony + compliance + the agent |
| Bring your own voice | ₹2.50/min | Telephony + compliance |
| Compliance only | per verdict | The gate, the ledger and the evidence |
Plus the monthly rental on each number.
The full-stack rate itemises as agent ₹3.50 + telephony ₹0.50 + platform ₹2.00. ⚠️ That breakdown is display, not a billing model — a call produces exactly one wallet debit at the blended rate, not three.
🔴 A BYO call bills the telephony-plus-platform subset and ignores a negotiated full-stack rate. A negotiated rate is a discount on the whole stack; applying it to a call whose agent half we never ran would charge a discounted customer more than list.
Test mode is free by environment
A tone_test_ key produces calls with billedPaise: 0. It is the environment
that makes a call free, never the channel — so a sandbox call is priced through
the same path and simply reports zero.
The ledger is the truth
GET /v1/wallet/transactions is not a report derived from a balance; it is what
the balance is computed from. It is append-only: a correction is a new
compensating row, never an edit. If a balance and its ledger ever disagreed, the
ledger would be right.
| Entry type | |
|---|---|
topup, topup_reversal | Money in |
call_usage | One row per call |
number_purchase, number_rental, and their reversals | Numbers |
compliance_usage | Verdicts |
adjustment | Anything we corrected by hand |
Adding money
Funding runs through Razorpay Checkout in a browser, from the dashboard. There is deliberately no programmatic money-in path: a card flow needs a human and a redirect, and an API that pretended otherwise would only fail in more places.
Running out
Subscribe to wallet.balance.low rather than polling. It fires once per
crossing, not repeatedly, and emails owners and admins.
What happens at zero depends on what you were doing:
- A call fails rather than being placed.
- A campaign with
autoPauseBelowPaisepauses itself withpausedReason: "low_balance"and emitscampaign.paused. Top up and resume. - A number rental starts a grace period, then suspends the number — which keeps your claim on it and reverses itself once you top up. See Phone numbers.