Appearance
Payouts
Single payouts attempt submission during the request. API vendors do not need per-transaction operator approval.
POST /api/v1/payouts
Requires payouts:write. First read /account and /methods. Reserve the customer's balance in your own system before sending the request.
Voucher request
json
{
"reference": "WD-VOUCHER-000123",
"amount": "100.00",
"currency": "ZAR",
"method": "voucher_1voucher",
"recipient": {
"first_name": "Alex",
"surname": "Example",
"phone": "27821234567",
"id_type": "Passport",
"id_number": "EXAMPLE123",
"country_of_issue": "ZW",
"nationality": "ZW"
},
"metadata": { "withdrawal_id": "123" }
}Cash request
json
{
"reference": "WD-CASH-000124",
"amount": "100.00",
"currency": "ZAR",
"method": "standard_bank_instant_money",
"recipient": {
"first_name": "Alex",
"surname": "Example",
"phone": "27821234567",
"id_type": "Passport",
"id_number": "EXAMPLE123",
"country_of_issue": "ZW",
"nationality": "ZW"
}
}Bank transfer request
json
{
"reference": "WD-BANK-000125",
"amount": "100.00",
"currency": "ZAR",
"method": "rtc_eft",
"recipient": {
"first_name": "Alex",
"surname": "Example",
"phone": "27821234567",
"id_type": "Passport",
"id_number": "EXAMPLE123",
"country_of_issue": "ZW",
"nationality": "ZW",
"bank_account": {
"bank_name": "Standard Bank",
"account_name": "Alex Example",
"account_number": "0000000000",
"branch_code": "051001"
}
}
}Use real recipient details in your integration. The bank account above is a placeholder, not a destination for testing live transfers.
Request rules
referenceis your idempotency key, unique per vendor across individual and batch items. It must match^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$. TheIdempotency-KeyHTTP header is not used. Keep the same body and reference for a retry; changed payloads return409 REFERENCE_CONFLICT.- A replay uses the existing record and reservation. It can submit an item that has never been attempted, but never repeats a provider submission. It returns the current outcome, not necessarily the original HTTP response.
amountis a string with exactly two decimal places, no sign or leading zeros except0.xx, and at most eight digits before the decimal point. Currency must beZAR. The effective method minimum, maximum, increment and vendor daily cap also apply. Daily caps count face value, using the gateway's configured calendar date.- Cash methods require multiples of
10.00. RTC EFT and vouchers accept cents. Do not round a customer's requested amount without their agreement. - Names are at most 80 characters.
first_nameandsurnameare required;middle_nameis optional and nullable. recipient.id_typeisRSAIDorPassport.id_numbermust be alphanumeric and at most 30 characters. RSAID additionally requires 13 digits and a valid checksum. Countries must be recognised uppercase ISO alpha-2 codes.recipient.phoneis exactly27followed by nine digits, without+or spaces.emailis optional and nullable, with at most 150 characters.date_of_birthis optional and nullable, formattedYYYY-MM-DD, before today. Its value is stored but never sent to the payment provider.bank_accountis required for RTC EFT. For other methods it may be omitted or null. When present, all four fields are required: bank and account names up to 100 characters, account number 4 to 40 digits, branch code six digits. Use strings to preserve leading zeros. No bank ID field is accepted.metadatais an optional flat object with at most 50 non-numeric keys. Values may be strings, numbers, booleans or null. Each value's string form must fit 2,000 bytes. Nested objects and arrays are rejected. Metadata is stored and echoed, never forwarded to the provider.- The generated
merchant_referenceis a separateFLUXR_PO_...identifier used with the provider.provider_referenceis the provider's identifier; for vouchers it is a Flash gateway transaction UUID. Use your ownreferencefor API lookups. This API does not guarantee bank-statement narration.
Successful response
Example 200 for a paid voucher with a token that lacks delivery access:
json
{
"success": true,
"data": {
"id": "01990000-0000-7000-8000-000000000001",
"reference": "WD-VOUCHER-000123",
"status": "paid",
"status_reason": null,
"method": "voucher_1voucher",
"amount": "100.00",
"fee": "0.00",
"currency": "ZAR",
"merchant_reference": "FLUXR_PO_01990000000070008000000000000001",
"provider_reference": "01990000-0000-7000-8000-000000000002",
"delivery": null,
"metadata": { "withdrawal_id": "123" },
"created_at": "2026-09-19T10:00:00+00:00",
"paid_at": "2026-09-19T10:00:02+00:00",
"reversal_reconciliation": null
}
}200 does not always mean paid. Cash and bank payouts can return pending, with paid_at: null; a replay of a reversed payout can return reversed. Definitive rejection returns 422 with an error envelope. An uncertain outcome returns 409 PENDING_CONFIRMATION, without a payout object. Retrieve the payout using the same reference. RTC settlement timing is not guaranteed.
delivery is populated only for paid payouts when the token also has payouts:delivery. Otherwise it is null. The separate delivery endpoint still requires that scope; it is not a way to bypass access restrictions.
reversal_reconciliation is null until finance posts a verified return to the append-only vendor ledger. When present it contains ledger_reference, returned_minor in cents, currency (ZAR), verified_by and verified_at. This is the actual returned amount, which can exclude fees or some principal. Raw reversed status alone is never evidence that money was returned. Internal statement notes remain private; the ledger reference identifies the audit record.
GET /api/v1/payouts/{reference}
Requires payouts:read. Read the current payout using your original vendor reference. URL-encode reserved characters in path references. This lookup reads stored state. Background workers check the provider; this request does not trigger a provider lookup or another payment.
For pending or PENDING_CONFIRMATION, keep the hold and poll this endpoint. Never send a replacement payment while the outcome is uncertain. See statuses and errors.
PayoutRequest fields
reference is the vendor idempotency key; the Idempotency-Key header is not used. Replay the same body and reference. RTC EFT requires recipient.bank_account. API creation requires automatic dispatch. A 200 response can be pending; only paid confirms payment.
| Field | Type | Required | Details |
|---|---|---|---|
reference | string | Yes | Pattern: ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,99}$ |
amount | string | Yes | Pattern: ^(0|[1-9][0-9]{0,7})\.[0-9]{2}$; Must meet effective method limits and increment, and the vendor daily cap. |
currency | string | Yes | ZAR |
method | string | Yes | standard_bank_instant_money, nedbank_cardless, rtc_eft, voucher_1voucher, voucher_ott, voucher_blu, voucher_easyload |
recipient | Recipient | Yes | |
metadata | Metadata | Optional |
Recipient fields
| Field | Type | Required | Details |
|---|---|---|---|
first_name | string | Yes | Maximum characters: 80 |
middle_name | string or null | Optional | Maximum characters: 80 |
surname | string | Yes | Maximum characters: 80 |
phone | string | Yes | Pattern: ^27[0-9]{9}$ |
id_type | string | Yes | RSAID, Passport |
id_number | string | Yes | Maximum characters: 30; Pattern: ^[A-Za-z0-9]+$; RSAID also requires 13 digits and a valid checksum. |
country_of_issue | string | Yes | Pattern: ^[A-Z]{2}$; Recognised uppercase ISO alpha-2 country code. |
nationality | string | Yes | Pattern: ^[A-Z]{2}$; Recognised uppercase ISO alpha-2 country code. |
email | string or null | Optional | Maximum characters: 150; Format: email |
date_of_birth | string or null | Optional | Format: date; YYYY-MM-DD before today. Stored for records; its value is never sent to the provider. |
bank_account | object or null | Optional | Required and non-null for rtc_eft; otherwise optional. All four bank fields are required when supplied. |
BankAccount fields
| Field | Type | Required | Details |
|---|---|---|---|
bank_name | string | Yes | Maximum characters: 100 |
account_number | string | Yes | Pattern: ^[0-9]{4,40}$ |
account_name | string | Yes | Maximum characters: 100 |
branch_code | string | Yes | Pattern: ^[0-9]{6}$ |
Metadata fields
Optional flat object, at most 50 non-numeric keys. Values are scalar or null, with at most 2,000 bytes when converted to strings. Never forwarded to providers.
Payout fields
| Field | Type | Required | Details |
|---|---|---|---|
id | string | Yes | |
reference | string | Yes | |
status | string | Yes | pending, paid, failed, reversed, needs_review, cancelled |
method | string | Yes | standard_bank_instant_money, nedbank_cardless, rtc_eft, voucher_1voucher, voucher_ott, voucher_blu, voucher_easyload |
amount | string | Yes | Pattern: ^(0|[1-9][0-9]*)\.[0-9]{2}$ |
fee | string | Yes | Pattern: ^(0|[1-9][0-9]*)\.[0-9]{2}$ |
merchant_reference | string | Yes | |
provider_reference | string or null | Yes | |
status_reason | string or null | Yes | |
delivery | object or null | Yes | |
metadata | Metadata | Yes | |
created_at | string | Yes | Format: date-time |
paid_at | string or null | Yes | Format: date-time |
reversal_reconciliation | object or null | Yes | |
currency | string | Yes | ZAR |

