Overview
FossaPay supports business-funded payouts directly from your permanent NGN master wallet, as well as the existing customer-funded transfer APIs. Choose the flow based on who owns the source funds.Use the Master Wallet Payout API when the funds belong to the business. It derives the source wallet from your API key, so you do not provide a
customerId, source wallet ID, or source account number.Prerequisites
- A verified FossaPay business
- An active production API key with full permission
- An active permanent NGN master wallet
- Sufficient available balance for the payout amount and any applicable fee
- A webhook endpoint configured with your webhook secret
How Master Wallet Routing Works
FossaPay looks up the submitted destination account number before moving funds.Same business
When the destination is an active customer wallet owned by your business:routeissame_businessfeeis0.00totalDebitedequalsamount- the transfer can complete immediately
Another FossaPay business
When the destination is an active FossaPay wallet owned by another business:routeisfossapay_cross_business- the configured payout fee applies
- the payout is processed through the charged payout rail
External bank
When the destination account is not a FossaPay wallet:routeisexternal_bank- the configured payout fee applies
- a final provider result is delivered asynchronously
Validate the Beneficiary
Retrieve supported banks and perform a name enquiry before creating the payout.Create a Payout
Generate one idempotency key for each logical payout and persist it with your reference.amount. For charged routes, your master wallet is debited by amount + fee, exposed as totalDebited.
Handle the Initial Status
HTTP202 means the request was accepted—not necessarily that the beneficiary has received the money.
- If
data.statusiscompleted, the payout is final and successful. - If it is
processing, storepayoutId,transactionId,reference, andproviderReference, then wait for a webhook or retrieve the payout. - Never submit a second payout with a new idempotency key because the first request timed out.
Reconcile a Payout
Retrieve by FossaPay payout ID:Endpoint map
Process Payout Webhooks
Master-wallet payouts emit:payout.completedpayout.failedpayout.reversed
JSON.stringify(body.data) with HMAC-SHA256. See Webhook Verification for complete Node.js and Python examples.
Idempotency Rules
Reuse the key only for the same request
Reuse the key only for the same request
The same request body and idempotency key return the existing payout. A different body with that key returns HTTP
409.Keep references unique
Keep references unique
A payout reference is unique per merchant. Use your own order, invoice, or withdrawal identifier so support and reconciliation are straightforward.
Resolve ambiguous responses before retrying
Resolve ambiguous responses before retrying
If the connection fails after submission, retrieve by reference. If found, continue tracking that payout. If it is not found, retry the identical body with the original idempotency key.
Terminal States
Do not deliberately retry a terminal payout under a new reference without making a new business decision in your own system.
Go-Live Checklist
- Use a verified business and a full-permission live API key.
- Keep API keys server-side only.
- Validate the beneficiary before creating a payout.
- Generate and persist a unique reference and idempotency key.
- Store the payout ID, your reference, and the returned transaction identifiers.
- Treat
processingas non-terminal. - Verify webhook signatures before processing events.
- Deduplicate webhook deliveries using
eventId. - Reconcile delayed webhooks with the GET endpoints.
- Test same-business, cross-business, and external-bank routing with controlled amounts.
Next Steps
Create Master Wallet Payout
Send directly from your business funds
Get Payout by ID
Retrieve the latest payout status
Wallet-to-Wallet Transfer
Customer-funded transfers within one business
Webhook Events
See complete payout event payloads
Bulk Payouts
Submit and reconcile immediate CSV payout batches

