Skip to content

What's changed

Changes that affect how you integrate with UniPay, newest first. Entries marked ⚠️ Breaking need action from you. Changes that don’t alter the API contract aren’t listed here.

2026-10-01 — A fiscal receipt per payment

Section titled “2026-10-01 — A fiscal receipt per payment”
  • POST /api/app/service-provider/fiscalization-result takes an optional paymentId (the Unipay payment id, as in erp-posting-result). When you send it, the receipt is recorded on that payment — every payment on a bill can carry its own — and the bill keeps the first payment’s receipt as its QR. Leave it out and nothing changes: a second payment’s receipt on the same bill is still refused with 409.

2026-09-30 — Payment references, lookup and credentials

Section titled “2026-09-30 — Payment references, lookup and credentials”
  • Payment references (rrn) are per processor. A payment whose rrn another processor has already used is now recorded normally. Re-sending one of your own payments still returns "isNewRecord": false. Re-using one of your own rrn values for a different bill, account, amount or currency is now refused with RRN 'X' was already used for a different payment — previously it was answered as a success and nothing was recorded. See Idempotency and retries.
  • POST /lookup by bill number now returns acceptedCurrencies, requestedCurrencyAccepted, rateIsStale and errorCode, as GET /bill does. Previously they came back empty. Whenever a bill exists it’s included for NotOwing and InCredit too — check bill rather than inferring it from status.
  • Credentials stay on their own side. Payment-processor endpoints refuse service-provider credentials, and service-provider endpoints refuse payment-processor credentials, with 403 and code Authorization:PartnerTypeMismatch. New credentials carry only their own side’s scopes and the client_credentials grant; existing credentials are unchanged.

These docs replace the UNIPAY Payment Processor Integration Guide PDF, and now cover service providers too. They’re served by every UniPay environment at /docs/ and always match that environment’s build.

If you integrated from the PDF, note where the API has moved on since it was written:

  • Lookup: POST /lookup finds a bill by number or by account in one call. GET /bill still works.
  • Currencies: a payment no longer has to be in the bill’s currency. Any of the provider’s acceptedCurrencies is accepted; see Currencies. The message Payment currency does not match invoice currency no longer occurs.
  • Overpayments are accepted unless the service provider has chosen to refuse them.
  • Rate limits are 10 / 60 / 300 requests a minute, counted per client IP — see Rate limits.
  • Error bodies: 401, 403 and 429 responses have an empty body; other errors use the error object described in Errors, limits and operations.
  • The legacy IP-based test address has been retired. Use https://test.unipay.co.zw.

UniPay API v1 · build e1eb5c49 · Powered by Axis Solutions