The Wallet and Billing API lets your own admin portal do what the wallet page does: show the balance, take a recharge, confirm it was credited, and get told when the balance runs low. You recharge either with Razorpay Checkout on your page or with a hosted payment link you redirect to or send. Two webhooks, wallet.low_balance and wallet.recharged, tell your server what happened.
Base URL https://voice-api.edesy.in/v1. Every call is made from your server with Authorization: Bearer <API key>; the key can spend your wallet, so never put it in browser code.
Facts#
| Item | Detail |
|---|---|
| Currency | INR. The wallet holds money before GST: a Rs 500 recharge charges Rs 590 and adds Rs 500 |
| Minimum recharge | Rs 10 |
| Recharge methods | Razorpay Checkout on your page, or a hosted Razorpay payment link |
| Rate limit | Create Recharge Order and Create Payment Link share 10 a minute per account; over it returns 429 with Retry-After |
| Payment link expiry | 7 days by default; 16 minutes to 180 days with expire_in_minutes |
| Confirmation | wallet.recharged webhook, or poll Get Payment until completed |
| Low-balance threshold | Rs 100 unless agreed otherwise |
| Invoices | A GST tax invoice for every completed recharge, as HTML or PDF |
Endpoints#
| Method | Path | Description |
|---|---|---|
| GET | /billing |
Balance, this month's usage, your rates and the account state |
| POST | /billing/create-order |
Create a Razorpay order for Checkout |
| POST | /billing/verify-payment |
Optional: credit a Checkout payment straight away |
| POST | /billing/payment-links |
Create a hosted payment link |
| GET | /billing/payments/{id} |
One recharge and its status |
| GET | /billing/transactions |
The wallet ledger (.csv for an export) |
| GET | /billing/invoices |
Completed recharges with invoice numbers |
| GET | /billing/payments/{id}/invoice?format=pdf |
Download an invoice |
| POST | /webhooks/subscriptions |
Subscribe to wallet events |
Show the balance#
curl https://voice-api.edesy.in/v1/billing -H "Authorization: Bearer $EDESY_KEY"
balance is what you can spend. account_state.status tells you when to prompt a recharge: ok, low_balance (below the threshold), past_due (negative balance or an unpaid number rental) or suspended. outbound_blocked says whether outbound calls are being refused.
Recharge with Checkout#
The payer stays on your page while Razorpay's payment window opens on top of it.
curl -X POST https://voice-api.edesy.in/v1/billing/create-order \
-H "Authorization: Bearer $EDESY_KEY" \
-H "Content-Type: application/json" \
-d '{ "amount": 500 }'
{ "data": { "order_id": "order_...", "payment_id": "...", "key_id": "rzp_live_...",
"subtotal": 500, "tax_rate": 0.18, "tax_amount": 90, "total": 590, "currency": "INR" } }
- Your server creates the order.
amountis what to credit, before GST. Addgstinto print your GSTIN on the invoice. - Your page opens Razorpay Checkout with
key_id,order_idandtotal x 100(paise). Onlyorder_idandkey_idreach the browser. - When Razorpay captures the payment, the wallet is credited automatically, even if the payer closes the window. Calling POST
/billing/verify-paymentwithrazorpay_order_id,razorpay_payment_idandrazorpay_signaturefrom the success handler is optional and only makes the credit instant. Calling it twice is safe.
Create an order when the payer clicks to pay, not ahead of time: orders and links share the 10-a-minute limit.
Recharge with a payment link#
No Razorpay code on your side. You get a hosted page URL to redirect to, or to send by email or WhatsApp.
curl -X POST https://voice-api.edesy.in/v1/billing/payment-links \
-H "Authorization: Bearer $EDESY_KEY" \
-H "Content-Type: application/json" \
-d '{ "amount": 500, "callback_url": "https://admin.example.com/wallet/paid" }'
| Field | Required | Description |
|---|---|---|
amount |
yes | INR to credit, before GST. Minimum 10 |
gstin |
no | GSTIN for the tax invoice |
callback_url |
no | https:// page the payer returns to after paying |
expire_in_minutes |
no | Default 10080 (7 days); 16 minutes to 180 days |
description |
no | Shown on the payment page |
The response has short_url, payment_link_id, payment_id, the GST breakdown and expires_at. Razorpay does not SMS or email the link: delivering it is up to you.
Know when it landed#
A redirect to callback_url, or Checkout's success handler, only means the payer finished on Razorpay's side. Credit your own records on one of these:
- Webhook:
wallet.recharged, once per credited recharge, carrying thepayment_id. - Poll: GET
/billing/payments/{id}with thepayment_id, theorder_...id or theplink_...id, untilstatusiscompleted.
status |
Meaning |
|---|---|
pending |
Not paid yet |
completed |
Credited; invoice_number is set |
failed |
For example, an expired link |
refunded |
Refunded |
Wallet webhooks#
Edesy already emails the account owner when the balance runs low. Subscribe a webhook to get the same signal on your server:
curl -X POST https://voice-api.edesy.in/v1/webhooks/subscriptions \
-H "Authorization: Bearer $EDESY_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://admin.example.com/edesy/webhooks",
"event_types": ["wallet.low_balance", "wallet.recharged"],
"secret": "a-long-random-string" }'
| Event | When |
|---|---|
wallet.low_balance |
A charge takes the balance below the threshold, and again once a day while it stays below and you hold an active number |
wallet.recharged |
A recharge is credited |
{ "event": "wallet.recharged", "timestamp": "...",
"data": { "account_sid": "AC_...", "balance": 594.5, "currency": "INR", "amount": 500, "total": 590,
"payment_id": "...", "invoice_number": "...", "occurred_at": "..." } }
- List the wallet events by name in
event_types. A subscription with an empty list ("all events") receives call events only, never wallet events. Leaveformatout (orlegacy). - With a
secret, each delivery carriesX-Edesy-Signature: sha256=<hex HMAC-SHA256 of the raw body>;X-Edesy-Eventcarries the event name. See Verify Signatures. - Answer 2xx within 5 seconds. Failed deliveries are retried with backoff, up to 6 attempts, and can be replayed. See Retries and Replay.
- Use
payment_idto ignore a repeat delivery.
History and invoices#
GET/billing/transactions is the ledger, newest first: recharges, call charges, number rentals and refunds, with the balance after each. Filter with type (credit or debit), date_from, date_to (IST days) and ref_type; per_page up to 200. Call rows carry call_sid and, where possible, an itemised call_breakdown. GET/billing/transactions.csv returns the same as CSV.
GET/billing/invoices lists completed recharges with their invoice numbers. Download one with GET/billing/payments/{id}/invoice?format=pdf (HTML without format).
See also Wallet and GST Invoices for how charges are deducted.
FAQ#
Can my customers recharge without seeing my API key?#
Yes. Your server calls Edesy. The browser only ever sees a recharge's order_id and key_id, or a payment link's short_url.
Whose name appears on the Razorpay window?#
Edesy's, because Edesy issues the GST invoice for the recharge.
Do I have to call Verify Payment?#
No. Razorpay notifies Edesy directly and the wallet is credited without it, a few seconds later.
Why am I getting 429?#
More than 10 orders or links in a minute on one account. Wait for the Retry-After seconds, and create orders only when someone clicks to pay.
Can I put my GSTIN on the invoice?#
Yes. Pass gstin when you create the order or link, or set it in your billing profile.