Skip to content

Idempotency and retries

Networks fail. A request can time out after UniPay has already recorded the payment, and your side can’t tell. UniPay is built so that retrying is always safe — provided you retry the right way.

Every payment you report carries an rrn (retrieval reference number): your unique reference for that payment, up to 50 characters. UniPay uses it to recognise a repeat:

You send UniPay answers
An rrn it hasn’t recorded Records the payment. "successful": true, "isNewRecord": true
An rrn it has already recorded, for the same payment Records nothing new. "successful": true, "isNewRecord": false
An rrn it has already recorded, for a different bill, account, amount or currency Refuses it: "successful": false, RRN 'X' was already used for a different payment.
An rrn it refused before (e.g. the date was wrong) Processes it afresh — a corrected retry isn’t blocked by the earlier refusal.

References are per processor: another processor using the same rrn for its own payment doesn’t affect yours.

So:

  • Generate the rrn once per payment, before the first attempt, and store it with the transaction.
  • Reuse it on every retry of that payment — after a timeout, a dropped connection, a 429 or a 5xx.
  • Treat isNewRecord: false as success. It means UniPay already had the payment.
  • Never reuse an rrn for a different payment. UniPay refuses it. Make references unique across your whole organisation — prefixing your own transaction ID works well.
Outcome Retry?
Timeout, connection reset, no response Yes, same request, same rrn. You don’t know whether it arrived.
429 Too Many Requests Yes, after a pause.
500, 502, 503, 504 Yes, with backoff.
401 Unauthorized Get a new token, retry once.
200 with "successful": false No. UniPay understood and refused; the same request gets the same answer. Fix the cause.
400, 403 No. Fix the request or your credentials.

Back off exponentially with some randomness — for example 2 s, 4 s, 8 s, 16 s, 30 s — and stop after about five attempts. If a payment still isn’t confirmed, park it for investigation rather than dropping it: the customer has paid.

Use a 10-second connect timeout and a 30-second read timeout. UniPay normally answers in well under a second; anything above five seconds is worth investigating.

Publishing a bill is also safe to repeat: sending a bill UniPay already has, unchanged, returns AlreadyExists and changes nothing. Reading the payments feed is safe to repeat too, because you choose where to resume — see Collect payments.

UniPay API v1 · build e1eb5c49 · Powered by Axis Solutions