Payout Webhook
This page walks you through how to set up and observe MoneyHash webhook notifications for payout operations. It covers both individual payout intents and bulk payout requests.
For the full list of payout webhook events, payload structures, and event descriptions, see Webhook Types.
Before you start
Payout webhooks require more setup than payment webhooks. Make sure the following are in place before testing:
- A customer with complete billing information — full name, phone, email, and billing address. This is required when using a saved payout method, and expected by most providers when submitting raw beneficiary details directly.
- A payout provider configured and active on your account. Contact MoneyHash support if you're unsure which providers are available for your integration.
- A webhook URL ready to receive events. Use webhook.site to get a free URL for testing.
Testing an individual payout webhook
1. Create a payout intent
Make a POST request to /api/v1.4/payout/intent/ and include your webhook_url:
{
"amount": 50,
"amount_currency": "egp",
"customer_id": "8c91204b-5a5b-4496-9904-76a6b72bc15d",
"webhook_url": "https://webhook.site/your-unique-url"
}
As soon as the intent is created, MoneyHash begins processing the disburse operation with the provider.
2. Watch webhook.site
Open your webhook.site page and watch for incoming events. Here is what to expect:
- If the provider requires approval before disbursing, you will first receive a
transaction.disburse.pending_approvalevent. - Once the provider processes the payout, you will receive either
transaction.disburse.successfulortransaction.disburse.failed.
3. Identify the payout in the payload
To confirm you are looking at a payout webhook (not a payment webhook), check two fields in the payload:
transaction.typewill be"payout"— distinguishing it from"payment"transactionsintent.payout_status.statusreflects the current money movement outcome — for example"DISBURSED"on success
4. What if you void the payout?
If you initiate a void via POST /api/v1.4/payout/transactions/{transaction_id}/void/ while the disburse is still in progress, you will receive either transaction.void.successful (payout cancelled, no funds moved) or transaction.void.failed (void attempt failed, disburse continues).
Note: Void availability depends on the provider. Not all providers support cancelling a payout once it is in progress. See Cancelling a payout for details.
Testing a bulk payout webhook
1. Create a bulk payout request
Make a POST request to /api/v1.4/payout/bulk/requests/ with your webhook_url and at least one item:
{
"label": "test bulk payout",
"webhook_url": "https://webhook.site/your-unique-url",
"items": [
{
"merchant_reference": "test-001",
"scheduled_date": "2026-06-01",
"payout_intent_details": {
"amount": 50,
"amount_currency": "ngn",
"customer": "8c91204b-5a5b-4496-9904-76a6b72bc15d",
"payout_method": "BANK_ACCOUNT",
"webhook_url": "https://webhook.site/your-unique-url"
}
}
]
}
2. Watch webhook.site — validation phase
Immediately after submission you will receive two events in quick succession:
payout.bulk.active— confirms the request was created. The payload includes the full items array with each item inVALIDATION_PENDINGstatus.payout.item.validation_pending— fires per item as each one enters the validation queue.
Depending on the outcome:
payout.item.scheduled— validation passed, item is scheduled for itsscheduled_datepayout.item.validation_failed— validation failed. Checkvalidation_result.errorsin the payload to see exactly which fields failed and why.
3. Watch webhook.site — execution phase
On the item's scheduled_date, execution begins. You will receive:
payout.item.intent_created— a payout intent was successfully created for this item. Standard payout lifecycle webhooks follow from this point.payout.item.intent_creation_failed— the intent could not be created. The item moves toINTENT_CREATION_FAILED. No further webhooks fire for this item.
4. After intent creation
Once an item's payout intent is created, the same individual payout webhooks fire for that intent:
transaction.disburse.pending_approval(if approval is required)transaction.disburse.successfulortransaction.disburse.failed
Use the merchant_reference field in every payload to map each webhook event back to the correct item in your system.
5. When the batch is done
Once all items have been processed — validated, executed, or failed — you will receive payout.bulk.batch_completed. The payload includes a count breakdown showing how many items ended in each status.
Updated about 2 hours ago