A recharge that comes back pending is the single most common support ticket in B2B recharge integration, and also the easiest one to make worse. Treated well, pending is a normal, temporary state on the way to success or failure. Treated badly, an anxious retry can charge a customer twice for one top-up. This guide covers how a recharge integration should define its status states, secure the callback that eventually resolves each pending request, decide when polling and refunds are safe, and where a Payonclick build fits into all of it.
Two ways a recharge reaches the operator
A mobile or DTH recharge in India travels through one of two supply chains, and they behave differently enough to treat as separate integrations rather than one interface with different providers underneath.
The first is a direct operator distribution API: an aggregator holding distribution agreements with telecom operators and DTH companies, exposing its own interface over that agreement. Operator coverage, dispute handling and even the exact meaning of "pending" are whatever that aggregator's own contract says.
The second is Bharat Connect (formerly BBPS), the bill-payment network run by NPCI Bharat BillPay Ltd (NBBL). RBI's BBPS Master Direction of 29 February 2024 defines a "bill" to include a notice for recharge of prepaid services, so Mobile Prepaid and DTH appear among the payment categories listed on bharat-connect.com. Here the contract, the biller identification and the dispute process are standardised across every participant, with one central dispute-resolution system run by NBBL.
| Operator distribution API | Bharat Connect Mobile Prepaid / DTH | |
|---|---|---|
| Who you contract with | An aggregator holding operator agreements | A platform or operating unit that reaches Bharat Connect |
| Operator coverage | Whatever the aggregator carries | Only operators live on Bharat Connect for that category |
| Dispute handling | Set by the aggregator's own terms | Centralised through NBBL |
| Biller identification | Aggregator-specific operator codes | A standard Bharat Connect biller ID |
In a recharge platform, postpaid mobile, broadband and utility bills are usually handled as Bharat Connect bill payments rather than recharges. Prepaid mobile and DTH can travel either rail, so wide operator coverage plus Bharat Connect's standardised disputes can mean running both integrations side by side.
What a recharge request must carry
Whichever rail carries it, a recharge payload is short, and every field earns its place.
| Field | What it does |
|---|---|
number |
The subscriber's mobile number, or the DTH customer/subscriber ID |
operator |
The operator code. Numbers port between operators, so this cannot be guessed reliably from the number alone |
circle |
The telecom circle, required for most mobile top-ups, irrelevant for DTH |
amount |
The recharge amount, validated against the operator's own minimum and plan rules |
client_reference |
Your own unique ID for this attempt, generated once and reused on every retry of the same intent |
Never derive operator from the number range without a fallback. Number portability means a range that belonged to one operator two years ago can belong to another today, and a wrong operator code sends the top-up nowhere useful.
Success, pending and failed: why pending is not a failure
A recharge response settles into one of three states:
- Success: the operator confirmed the top-up. The debit stands.
- Failed: the operator explicitly rejected the request, for example an invalid number, an expired plan or an outage that returned a clear error.
- Pending: the request was accepted but no confirmation has arrived yet. This can resolve in seconds, or, on a bad day for one operator, take much longer.
Pending happens because the aggregator or Bharat Connect operating unit is itself waiting on the telecom operator's own systems, which do not always answer synchronously. Treating pending as a failure and immediately resubmitting under a new reference is the single most expensive habit in recharge integration: if the first attempt eventually succeeds, the customer is topped up once but billed twice, and reversing the extra charge becomes manual clean-up.
A pending recharge must resolve through a callback or a status check on the original reference, never through a fresh request. Reserve retries for requests that demonstrably never reached the operator at all.
Securing callbacks: a token per transaction, plus an IP allowlist
Most recharge providers confirm a pending transaction by calling back into your system. A callback endpoint anyone can call is riskier than it looks: a forged "success" callback can mark an unpaid recharge as paid, and a forged "failed" callback can trigger a refund for a top-up that actually went through.
Two controls close that gap, used together rather than as alternatives:
- A per-transaction signed token. Generate a unique HMAC-SHA256 token for each transaction and require it in the callback path or payload. A token for transaction A cannot be replayed against transaction B, and one that does not verify is rejected before any status change happens.
- An IP allowlist. Accept callbacks only from the provider's published IP ranges. This does not replace the token check; it removes a class of drive-by attempts before they ever reach your signature logic.
Reject a wrong token even from an allowed IP, since an allowed IP only proves the network path, not that a specific request is genuine. Log every rejection and alert on repeated failures from one source, since that pattern usually means someone is probing the endpoint rather than a one-off misconfiguration.
Polling, refunds and when a second provider is safe
Callbacks can be delayed or lost, so a status-check endpoint is not optional. It is the backup that makes the callback trustworthy.
Wait before the first check
Query too early and a provider can return "no record found" for a recharge it processes moments later. Give it a short window before the first status call.
Poll on a fixed schedule
Check on a regular interval until the transaction resolves or ages past the point your provider treats it as closed. Avoid tight loops that hammer the same endpoint.
Refund only on a confirmed failure
Move money back to the wallet only when the provider's status response says failed, never on a timeout or an assumption. A confirmed failure is a fact from the provider; a timeout is a fact about your own patience.
Route to a second provider only if the first never reached the operator
If the first provider's own gateway rejected the request before dispatch, for example on a malformed payload, trying a second provider under a fresh reference is safe. If there is any chance the request reached the operator, wait for that attempt to resolve instead.
Track each provider's health over a rolling window, flagging it as degraded after a handful of consecutive failures and pausing new traffic after more, so a struggling upstream does not keep absorbing fresh requests while nobody notices.
Daily reconciliation closes the loop
Callbacks and status checks close out individual transactions, but small gaps still slip through: a callback that arrives after you already resolved the transaction by polling, a refund that fires twice, or a provider report that disagrees with your own ledger. A daily reconciliation run compares three records for every transaction older than a day: your wallet ledger, the provider's own transaction report, and, for Bharat Connect categories, the Bharat Connect transaction reference. Anything that fails to match across all three goes into a short manual-review queue rather than being auto-corrected, because a mismatch is exactly the kind of event that deserves a human look.
How Payonclick handles this, as a platform module
Payonclick does not sell a public recharge API. Recharge is built into the Payonclick retailer web portal and Android app, using the same engineering choices set out above:
- One interface sits in front of several recharge providers, with one primary provider set per Mobile Prepaid category and per DTH category.
- Optional failover retries a request only when it provably never reached the operator, never on a pending or a timeout result, and each provider's health is tracked so a struggling one is taken out of rotation automatically.
- Callbacks carry a per-transaction HMAC token in the callback URL and are checked against the provider's IP allowlist; a wrong token is rejected even from an allowed address.
- A status job re-checks pending recharges every two minutes, from two minutes to 24 hours after they were sent, so a result is caught even when its callback never arrives.
- The amount is locked in the wallet before the provider is called and released only on a confirmed failure, once, under its own reference. If a provider later turns a success into a failure, the transaction and the wallet are reversed automatically.
For Mobile Prepaid and DTH specifically, our BBPS bill payment API already covers both as Bharat Connect categories, with the same idempotent client_reference and status endpoint described above. A broader recharge capability, covering operator-distribution recharge outside Bharat Connect, ships as a retailer-facing module inside a white-label platform or a custom build, not as a standalone API.