Tone docs

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

RateWhat you get
Full stack₹6.00/minTelephony + compliance + the agent
Bring your own voice₹2.50/minTelephony + compliance
Compliance onlyper verdictThe 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_reversalMoney in
call_usageOne row per call
number_purchase, number_rental, and their reversalsNumbers
compliance_usageVerdicts
adjustmentAnything 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 autoPauseBelowPaise pauses itself with pausedReason: "low_balance" and emits campaign.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.
Was this page helpful?

On this page