Skip to main content

Overview

Discovery and payment are asynchronous, so polling is not an optimisation — it is the mechanism. Everything you need to know about a transaction is in its status, read from Get Transaction by ID.
Bill Payment does not push notifications to you. Polling is how outcomes arrive, for both discoveries and payments.

The state machine

Every transition a transaction can make: SUCCESS, FAILED and REFUNDED are final — a transaction never leaves them. These are starting points, not guarantees. Measure your own traffic and adjust.
“Give up” means stop the foreground poll, not “decide the payment failed”. A transaction you stopped watching still has a real outcome; move it to a background reconciliation job that keeps checking.
Grow the interval instead of hammering a fixed one. A payment that has not finished in three seconds will not finish faster because you asked again.

A production-grade poller

The same shape in four languages: an initial interval, growth up to a ceiling, an overall deadline, and one branch per status.

Acting on each status

One branch per status, and no default that assumes failure.

Handling UNKNOWN

UNKNOWN means the outcome has not been confirmed. It is not a failure, and it is not a success. It resolves on its own to SUCCESS or REFUNDED.
While a transaction is UNKNOWN:
  • Never refund your own customer.
  • Never resend the payment.
  • Never show “payment failed” in your interface.
Doing any of these turns an uncertain payment into a certain loss — either you refund a bill that was actually paid, or you pay it twice.
What to do instead:
1

Hold the customer's funds

Keep the amount reserved on your side and show a neutral state — “payment being confirmed”, not “failed”.
2

Slow the poll right down

Move to a 30-second cadence, or to a background job that checks periodically. Frequent polling does not speed up a review.
3

Act only on the resolution

SUCCESS — settle and keep the receipt. REFUNDED — release the funds. Only then tell the customer.

Handling REFUNDED

REFUNDED means the payment was charged and then returned in full. The customer-facing outcome is the same as FAILED — the bill is not paid — but your accounting differs: money left and came back, so both movements belong in your ledger. error.code explains why the payment did not stick: The same four codes appear on FAILED. Branch on code, never on message.

Handling transient errors while polling

A poll that fails is not a transaction that failed.
Never let a failed poll change your order state. Only a real status from a successful read may do that.

What never to do

Best practices

One poller, one transaction

Follow a transaction by its identifier. Repeatedly listing transactions to find it is slower and heavier.

Grow the interval

Start at a few seconds, grow to about ten. Slow to 30 seconds once a transaction is UNKNOWN.

Hand over, do not give up

When the foreground poll times out, queue the transaction for background reconciliation.

Log the requestId

Every poll returns one. Keep the last one against your order — it is what support needs.

Next step

Step 5: Receipts and reconciliation

Store the proof of payment and reconcile your ledger daily

Get Transaction by ID

The transaction object and the field matrix

Polling Strategies

Cross-product polling guidance

Paying Bills

What to do before the payment

Sandbox Testing

Reproduce UNKNOWN and REFUNDED on demand