Developers
Collections
Create a collection
POST/api/org/v1/collections
Also at /api/school/v1/collections. 201 when made; 200 when an open one for the same externalRef and amount already exists.
N. K., S.2. 1 to 40 characters."350000"; the payer pays exactly that. null: the payer chooses any whole amount, up to 2,000,000,000 a payment.UGX or KES.Send an Idempotency-Key header (1 to 200 printable characters) to retry safely: the same key with the same body returns the same collection; the same key with another body is a 409.
curl -X POST https://wellth.example/api/org/v1/collections \
-H "Authorization: Bearer $WELLTH_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: oca-col-2026-3-ckx123-1" \
-d '{
"externalRef": "oca_stu_ckx123:term_2026_3",
"learnerLabel": "N. K., S.2",
"termLabel": "Term 3, 2026",
"amountMinor": "350000",
"currency": "UGX",
"expiresAt": "2026-12-15T00:00:00Z"
}'{
"id": "col_k2m9x4q7w1z8c5v3b6n0",
"status": "OPEN",
"payCode": "K7QM-2WXP",
"payUrl": "https://wellth.example/pay/s/SGS4p_Xc3cwxh1nSw0rkXAsin0AGSRn4oyXMomn2P0E",
"qrSvgUrl": "https://wellth.example/api/school/v1/collections/col_k2m9x4q7w1z8c5v3b6n0/qr.svg",
"amountMinor": "350000",
"currency": "UGX",
"paidMinor": "0",
"expiresAt": "2026-12-15T00:00:00.000Z"
}col_ and 20 lower-case letters and digits.OPEN, PAID, CANCELLED or EXPIRED. An open collection past its date reads EXPIRED.K7QM-2WXP. Print it on the statement./pay/s/<token>. The token is random-looking and carries no personal data. The same link comes back on every read.Sending the same externalRef again
- An open collection with the same amount: it is returned (200). Nothing new is made.
- An open collection with another amount: the old one is cancelled (you get collection.cancelled) and a new one is made (201), with a new link and pay code. Balances change during term.
- None open (paid, cancelled or expired): a new one is made.
Read a collection and its payments
GET/api/org/v1/collections/:id
The same shape, plus payments: every settled payment, oldest first. 404 if it isn't yours.
{
"payments": [
{
"wellthRef": "WP-5TR8WK3E",
"amountMinor": "350000",
"paidAt": "2026-11-02T08:14:51.000Z",
"method": "MOBILE_MONEY",
"payer": "P. K."
}
]
}method is MOBILE_MONEY, CARD, BANK, ABROAD or WELLTH_BALANCE. payer is the payer's first name and last initial as Wellth knows them (shown here as initials).
Cancel a collection
POST/api/org/v1/collections/:id/cancel
Stops the link and the pay code at once, and answers the collection (status CANCELLED). Cancelling twice is fine.
- A paid collection: 409 “This collection is already paid.” An expired one: 409 “This collection is already expired.”
- A family share with a payment on its way: 409, until that payment lands or fails.
- A payment already on its way may still land after you cancel. It is booked and reported by webhook as usual.
The QR code
GET/api/org/v1/collections/:id/qr.svg
The QR of payUrl, as image/svg+xml. Needs your key, so fetch it server-side and cache it (it is sent with Cache-Control: private, max-age=3600).
Pay codes and paying
- 8 characters from
23456789ABCDEFGHJKLMNPQRSTUVWXYZ: no 0, O, 1 or I, so nothing is misread off paper. - A payer signs in at your poster page
/s/<handle>and types it: any case, with or without the dash or spaces. Codes are looked up only within your organisation, and 10 wrong ones in an hour stop that person for the hour. - With an amount, the payer pays exactly what is left, in one payment, and the collection becomes PAID. A payment on its way (by phone or from abroad) holds it, so two people can't both pay it.
- With any amount, it stays OPEN, taking payments, until it expires or you cancel it.
- A bank transfer that arrives after someone else paid is still booked (so
paidMinorcan passamountMinor) and held for review: Tall Grass sorts out the refund, and your finance staff are told.