Skip to content

Collect payments

UniPay doesn’t push payments to you. Your system pulls them from the payments feed (GET /api/app/service-provider/payments) as often as suits you, resuming from where it last stopped. Scopes: unipay:bills and unipay:payments.

Terminal window
# Omit afterId the first time; afterwards pass the id of the last payment you stored.
curl -sS --fail-with-body "$BASE_URL/api/app/service-provider/payments${AFTER_ID:+?afterId=$AFTER_ID}" \
-H "Authorization: Bearer $TOKEN"
# → [{"payments":[{"id":"01a0ee4f-…","rrn":"…","billNo":"…","amount":1.4,"currency":"ZWG",
# "allocatedAmount":1.4,"allocatedCurrency":"ZWG",…}],"successful":true,…}, …]
# An empty array [] means you're up to date.
flowchart LR
    A[Load last stored id] --> B["GET /payments?afterId=id"]
    B --> C{Empty?}
    C -- Yes --> D[Caught up.<br/>Try again later.]
    C -- No --> E[Store each payment,<br/>then its id]
    E --> B
  • afterId is the id of the last payment you stored. You get only payments after it, oldest first, up to 100 per call.
  • Leave afterId out on your first call to start from the beginning.
  • Keep calling until you get an empty array []: you’re caught up. Poll again later — every few minutes is plenty.
  • Store the payment, then the id, in that order and ideally in one transaction. If you crash in between, you re-read that payment next time — so make storing it idempotent on id.

The feed is a JSON array. Each element wraps one payment:

[
{
"successful": true,
"message": "Found",
"payments": [
{
"id": "01a0ee4f-b160-75ef-9036-c51fd40af1d1",
"rrn": "PX20260929000123",
"billNo": "4444INV0009",
"uniqueNo": "INV0009",
"accountNumber": "100-2345",
"serviceProvider": "4444",
"paymentDate": "2026-09-29T08:15:00Z",
"amount": 170.00,
"currency": "USD",
"allocatedAmount": 170.00,
"allocatedCurrency": "USD",
"allocationRate": null
}
]
}
]
Field Meaning
id UniPay’s ID for the payment. Use it as your checkpoint and your de-duplication key.
rrn The paying processor’s reference.
billNo, accountNumber What was paid.
uniqueNo Your reference for the bill on its first payment; the rrn on later ones.
paymentDate When the customer paid, in UTC.
amount, currency What the customer tendered.
allocatedAmount, allocatedCurrency What it settled against the bill, in the bill’s currency.
allocationRate The exchange rate used, when the tender was converted.

allocatedAmount and allocatedCurrency are null when the payment couldn’t be matched to a bill — for example, paid in a currency the account has no bill in, with no exchange rate available. Record those as unallocated and resolve them through your exceptions process; see Currencies.

A payment can be reversed after you’ve collected it. Reversals have their own feed, read exactly the same way: GET /api/app/service-provider/payment-reversals?afterId=….

[
{
"id": "01a0f0c2-…",
"paymentId": "01a0ee4f-b160-75ef-9036-c51fd40af1d1",
"rrn": "PX20260929000123",
"billNo": "4444INV0009",
"reversedAt": "2026-09-30T09:00:00Z",
"category": "…",
"reason": "…"
}
]

Match paymentId to the payment you stored and reverse it in your system. Keep a separate checkpoint for this feed. Only approved reversals appear; Reversals explains how a payment comes to be reversed.

When a processor transfers a day’s takings to you, it reports the transfer to UniPay. The processor settlements feed lists those reports — processor, settlement date, transfer reference, the account credited, gross, fee and net amounts, and the payments included — for reconciling your bank statement. Read it the same way, with its own checkpoint; it returns up to 50 per call.

UniPay API v1 · build e1eb5c49 · Powered by Axis Solutions