Webhook Types
MoneyHash uses a variety of webhooks to notify you regarding every action that happens on our integration side. The webhook types are listed below. Use each link to access the details regarding each existing type:
Intent
Transaction
Card Token
Customer
Methods
Subscription
Historical Transaction
Payout
Bulk Payout
Intent Webhooks
The intent webhook will be received on your app whenever an intent changes status. These webhook types will be in the form of intent.{status}. The table below shows the events available for this webhook:
| Event | Webhook Type | Description |
|---|---|---|
| Intent Processed | intent.processed | The intent was processed and reached the final state. Users can't take any new action with the intent. |
| Intent Time Expired | intent.time_expired | Intent expires after the specified amount of seconds set by expires_after_seconds User can't take any action with the intent. |
| Intent Closed | intent.closed | Intent gets closed, and the User can't take any new action with the intent. |
Sample Intent Webhook
1 {
2 "type": "intent.processed",
3 "intent_type": "PAYMENT",
4 "data": {
5 "intent_id": "gQlovBL",
6 "intent": {
7 "id": "gQlovBL",
8 "status": "PROCESSED",
9 "amount": 50,
10 "amount_currency": "USD",
11 "type": "Payin",
12 "account": "4L2W2bg",
13 "custom_fields": null,
14 "billing_data": {
15 "first_name": "",
16 "last_name": "",
17 "email": "",
18 "phone_number": ""
19 },
20 "active_transaction": {
21 "id": "c5a09deb-5f7c-499f-85b7-143218591dbc",
22 "custom_fields": null,
23 "created": "2023-01-15T11:58:09.458587Z",
24 "status": "SUCCESSFUL",
25 "amount": "50.00",
26 "amount_currency": "USD",
27 "billing_data": null,
28 "external_action_message": [],
29 "payment_method": "CARD",
30 "payment_method_name": "Card",
31 "custom_form_answers": null,
32 "custom_message": "",
33 "service_provider": "XZOkmZ8",
34 "account": "4L2W2bg",
35 "provider_transaction_fields": {},
36 "provider_signature_match": false
37 },
38 "transactions_history": [
39 {
40 "id": "c5a09deb-5f7c-499f-85b7-143218591dbc",
41 "custom_fields": null,
42 "created": "2023-01-15T11:58:09.458587Z",
43 "status": "PENDING",
44 "amount": "50.00",
45 "amount_currency": "USD",
46 "billing_data": null,
47 "external_action_message": [],
48 "payment_method": "CARD",
49 "payment_method_name": "Card",
50 "custom_form_answers": null,
51 "custom_message": "",
52 "service_provider": "XZOkmZ8",
53 "account": "4L2W2bg",
54 "provider_transaction_fields": {},
55 "provider_signature_match": false
56 }
57 ],
58 "flow": null,
59 "is_live": false,
60 "created": "2023-01-15T11:58:01.313334Z"
61 }
62 },
63 "api_version": "1.1"
64 }
Transactions Webhooks
The transaction webhook will be received on your app whenever an operation inside the transaction changes status. Each event will also carry the status of the current payment flow to indicate its current state.
These webhook types will be in the form of transaction.{operation}.{status}. Below, you will find more about the possible operation types, the possible statuses for these operations, and the available webhook events per operation type:
Operation types
| Operation | Description |
|---|---|
| Authorize | When you authorize a payment, some checks will happen with the card issuing bank to confirm the card cardholder’s ability to pay the requested amount and that there are sufficient funds to complete the purchase, ensure that the card issuing bank will hold the amount, and it will be available when you request capturing them using capture operation. |
| Capture | After authorizing the required amount, capturing them to your merchant account will be available. You can capture the authorized amount multiple times, or you can do it once by executing the capture operation. You have a limit to the authorized amount and can't capture an amount greater than the authorized amount. |
| Purchase | If your business doesn't require the auth and capture flow, and you need to get the full amount automatically without holding it for some time, you should use the purchase operation instead of the authorized operation |
| Void / Cancel | When you decide not to complete the authorization process and don't need to capture the authorized amount anymore, you can release the funds you authorized on your customer's card by voiding the authorization using the void command. Even if your authorization automatically expires, you should consider canceling the authorization you hold on your client's card if they decide not to make their purchase. Doing so gives your customer faster access to their funds. |
| Refund | If you captured the full amount or part of it, and you need to refund either the full captured amount or a part of it, then you need to consider using the refund operation. Also, you can do multiple partial refunds as long as you don't exceed the full amount. |
Operation Statuses
| Operation Statuses | Description |
|---|---|
| Pending | The operation is awaiting processing. |
| Pending Authentication | Awaiting authentication or verification. |
| Pending External Action | Awaiting an action from an external source. |
| Pending Online External Action | Awaiting an online action from an external source. |
| Successful | The operation has been completed successfully without errors or issues. |
| Failed | The operation has encountered an error or failure during processing. |
| Increase purchase | Indicates an increase in the purchase amount for this specific transaction and doesn't impact the intent amount |
Available Webhook events per Operation type
| pending | successful | failed | Pending Authentication | Pending External Action | Pending Online External Action | Increase purchase | |
|---|---|---|---|---|---|---|---|
| Purchase | transaction.purchase.pending | transaction.purchase.successful | transaction.purchase.failed | transaction.purchase.pending_authentication | transaction.purchase.pending_external_action | transaction.purchase.pending_online_external_action | transaction.increase_purchase.successful |
| Authorize | transaction.authorize.pending | transaction.authorize.successful | transaction.authorize.failed | transaction.authorize.pending_authentication | Not Applicable | Not Applicable | Not Applicable |
| Capture | transaction.capture.pending | transaction.capture.successful | transaction.capture.failed | Not Applicable | Not Applicable | Not Applicable | Not Applicable |
| Void | transaction.void.pending | transaction.void.successful | transaction.void.failed | Not Applicable | Not Applicable | Not Applicable | Not Applicable |
| Refund | transaction.refund.pending | transaction.refund.successful | transaction.refund.failed | Not Applicable | Not Applicable | Not Applicable | Not Applicable |
Sample Transaction Webhook
1 {
2 "type": "transaction.purchase.successful",
3 "status_id": "gMpKN2L",
4 "intent": {
5 "id": "ZvwG5Y9",
6 "created": "2022-12-08 13:50:48.298834+00:00",
7 "custom_fields": null,
8 "custom_form_answers": null,
9 "amount": {
10 "value": 50,
11 "currency": "USD"
12 }
13 },
14 "account": {
15 "id": "YVglAZx"
16 },
17 "transaction": {
18 "type": "payment",
19 "id": "ff21dfa2-48c3-4f1b-a1bb-f7d3597f1ef3",
20 "created": "2022-12-08 13:51:01.900745+00:00",
21 "status": "purchase.successful",
22 "billing_data": {
23 "first_name": "Joe",
24 "last_name": "Doe",
25 "email": "[email protected]",
26 "phone_number": null,
27 "apartment": null,
28 "floor": null,
29 "building": null,
30 "street": null,
31 "city": null,
32 "state": null,
33 "country": null,
34 "postal_code": null
35 },
36 "external_action_message": [],
37 "operations": [
38 {
39 "id": "gXoANML",
40 "type": "purchase",
41 "status": "successful",
42 "amount": {
43 "value": 50,
44 "currency": "USD"
45 },
46 "statuses": [
47 {
48 "id": "gMpKN2L",
49 "value": "successful",
50 "created": "2022-12-08 13:51:01.949061+00:00"
51 }
52 ]
53 }
54 ],
55 "custom_message": "",
56 "method": {
57 "id": "W9KWv9X",
58 "display_name": "Demo - Card",
59 "service_provider": {
60 "id": "qYLP2Z3"
61 }
62 }
63 },
64 "api_version": "1.1"
65 }
Card Token Webhooks
The card token webhook will be received on your app whenever a card tokenization changes status.
These webhook types will be in the form of card_token.{event}. The table below shows the events available for this webhook:
| Event | Webhook Type | Description |
|---|---|---|
| Card token created | card_token.created | A new card token has been created and associated with a customer entity. |
| Card token updated | card_token.updated | A card token has been updated. |
| Card token deleted | card_token.deleted | A card token has been removed. |
Sample Card Token Webhook
1 {
2 "type": "card_token.updated",
3 "data": {
4 "intent_id": "98B8jMg",
5 "card_token": {
6 "id": "b1cbd010-78fc-4bac-ac55-880149907c99",
7 "brand": "MasterCard",
8 "card_holder_name": null,
9 "last_4": "2346",
10 "expiry_month": "01",
11 "expiry_year": "25",
12 "country": null,
13 "custom_fields": {
14 "user_uid": "b836b4b7-1c2d-40b7-bb85-36f10500cca7",
15 "customer_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
16 },
17 "provider_token_data": [
18 {
19 "last_4": "1234",
20 "service_provider_id": "eZAVN9x",
21 "pay_in_method": "jgxNP9r",
22 "provider_specific_data": {
23 "payment_token": "93e50bb163c640910506de431ce13d607f8d187be6c0f4f5f38145f5"
24 }
25 }
26 ]
27 }
28 }
29 }
Customer Webhooks
The customer webhook will be received on your app whenever the entity of a customer changes status.
These webhook types will be in the form of customer.{event}. The table below shows the events available for this webhook:
| Event | Webhook Type | Description |
|---|---|---|
| Customer Created | customer.created | A new customer entity has been created. |
Sample Customer Webhook
1 {
2 "type": "customer.created",
3 "data": {
4 "customer_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
5 "customer": {
6 "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
7 "organization": "demo org",
8 "name": null,
9 "email": "[email protected]",
10 "phone_number": "+201064610000",
11 "description": null,
12 "address": null,
13 "is_live": false,
14 "wallets": {}
15 }
16 }
17 }
Methods Webhooks
The method webhook will be received on your app whenever a payment method is activated or deactivated on an Account.
These webhook types will be in the form of account.method.{event}. The table below shows the events available for this webhook:
| Payment method event | Webhook Type | Description |
|---|---|---|
| Payment Method Activated | account.method.active | A payment method has been activated on an account |
| Payment Method Deactivated | account.method.inactive | A payment method has been deactivated on an account. |
Sample Methods Webhook
1 {
2 "type": "account.method.active",
3 "account": {
4 "id": "1Zv0zLB",
5 "name": "Merchant Account X"
6 },
7 "service_provider": {
8 "id": "8LVE39r",
9 "display_name": "Network International",
10 "code": "NETWORK_INTERNATIONAL"
11 },
12 "method": {
13 "id": "A9eqX9m",
14 "type": "PayIn",
15 "code": "NETWORK_INTERNATIONAL.PayIn.CARD",
16 "active": true
17 }
18 }
Subscription Webhooks
The subscription webhook will be received on your app whenever a subscription status is updated.
These webhook types will be in the form of subscription.current_status. The table below shows the events available for this webhook:
| Subscription Status | Description |
|---|---|
| NEW | The initial status for any subscription before its start date. |
| TRIAL | The trial period is in progress. |
| INCOMPLETE | The first recurring cycle is due, and the customer payment details are missing. |
| ACTIVE | There aren't any pending invoices, and the last cycle was paid. |
| PAST_DUE | There is an overdue invoice that wasn't paid. |
| PENDING_CANCELLATION | The subscription received a request to be canceled and is waiting for the recurring date. |
| CANCELLED | The subscription was canceled. |
| ENDED | The end date of the subscription was reached. |
Sample Subscription Webhook
1 {
2 "type": "subscription",
3 "id": "Yz98Bgy",
4 "account": {
5 "id": "YVglAZx",
6 "name": "Demo Account"
7 },
8 "plan": {
9 "id": "wA9eY9m",
10 "name": "test plan"
11 },
12 "current_status": {
13 "id": "akLnog3",
14 "value": "INCOMPLETE",
15 "created": "2023-01-16 14:24:53.824895+00:00"
16 },
17 "statuses": [
18 {
19 "id": "o19zj9Y",
20 "value": "NEW",
21 "created": "2023-01-16 14:24:53.819900+00:00"
22 },
23 {
24 "id": "akLnog3",
25 "value": "INCOMPLETE",
26 "created": "2023-01-16 14:24:53.824895+00:00"
27 }
28 ],
29 "start_date": "2023-01-16",
30 "customer": {
31 "id": "d1aa2379-c74c-4886-bc6b-8f491a3e331e",
32 "name": "Subscription Test Customer"
33 },
34 "charge_automatically": false,
35 "remaining_recurring_cycles": null,
36 "remaining_discount_cycles": null,
37 "configuration": {
38 "amount": 10,
39 "one_time_fee": null,
40 "trial_period": null,
41 "recurrency": 1,
42 "recurring_cycles": null,
43 "discount_amount": null,
44 "discount_percentage": null,
45 "discount_cycles": null
46 },
47 "webhook_url": "https://webhook.site/8fb2166e-a0c4-4d64-a20e-7d89a31e2d43",
48 "custom_fields": {},
49 "due_invoices": [
50 {
51 "id": "AXZOML8",
52 "subscription_id": "Yz98Bgy",
53 "status": {
54 "id": "voZpKgM",
55 "value": "DUE",
56 "created": "2023-01-16 14:24:53.843352+00:00"
57 },
58 "amount": 10,
59 "currency": "EGP",
60 "due_date": "2023-01-16",
61 "is_live": false,
62 "payment_intent_url": "https://dev-embed.moneyhash.io/embed/payment/yoZoVgp",
63 "statuses": [
64 {
65 "id": "6eZAeZx",
66 "value": "NEW",
67 "created": "2023-01-16 14:24:53.839221+00:00"
68 },
69 {
70 "id": "voZpKgM",
71 "value": "DUE",
72 "created": "2023-01-16 14:24:53.843352+00:00"
73 }
74 ]
75 }
76 ],
77 "next_recurring_cycle_invoice": {
78 "id": "yW9KvZX",
79 "subscription_id": "Yz98Bgy",
80 "status": {
81 "id": "7lgajZ3",
82 "value": "OPEN",
83 "created": "2023-01-16 14:24:53.859019+00:00"
84 },
85 "amount": 10,
86 "currency": "EGP",
87 "due_date": "2023-02-16",
88 "is_live": false,
89 "payment_intent_url": "https://dev-embed.moneyhash.io/embed/payment/K1ZvzZB",
90 "statuses": [
91 {
92 "id": "q7L5d9d",
93 "value": "NEW",
94 "created": "2023-01-16 14:24:53.855159+00:00"
95 },
96 {
97 "id": "7lgajZ3",
98 "value": "OPEN",
99 "created": "2023-01-16 14:24:53.859019+00:00"
100 }
101 ]
102 },
103 "all_invoices": [
104 {
105 "id": "AXZOML8",
106 "subscription_id": "Yz98Bgy",
107 "status": {
108 "id": "voZpKgM",
109 "value": "DUE",
110 "created": "2023-01-16 14:24:53.843352+00:00"
111 },
112 "amount": 10,
113 "currency": "EGP",
114 "due_date": "2023-01-16",
115 "is_live": false
116 },
117 {
118 "id": "yW9KvZX",
119 "subscription_id": "Yz98Bgy",
120 "status": {
121 "id": "7lgajZ3",
122 "value": "OPEN",
123 "created": "2023-01-16 14:24:53.859019+00:00"
124 },
125 "amount": 10,
126 "currency": "EGP",
127 "due_date": "2023-02-16",
128 "is_live": false
129 }
130 ],
131 "is_live": false,
132 "end_date": null,
133 "created": "2023-01-16T14:24:53.813988Z"
134 }
Create a Historical Transaction Webhook
After creating the Create a Historical Transaction with an API call, you will receive a webhook that confirms that the operation has been successfully processed.
Sample Historical Transaction Webhook
1 {
2 "intent": "2L3RE9m",
3 "status": "SUCCESSFUL",
4 "message": "This Transaction history intent has been processed successfully"
5 }
Payout Webhooks
Payout webhooks are fired when a disburse or void operation changes status on a payout intent. These events follow the same transaction webhook pattern but are scoped to payout operations.
These webhook types take the form transaction.{operation_type}.{status}. Disburse operations may pass through intermediate states before reaching a terminal outcome.
| Event | Webhook Type | Terminal? | Description |
|---|---|---|---|
| Disburse pending approval | transaction.disburse.pending_approval | No | The disburse operation is awaiting approval before execution proceeds. |
| Disburse successful | transaction.disburse.successful | Yes | Funds have been disbursed successfully. The payout intent moves to processed. |
| Disburse failed | transaction.disburse.failed | Yes | The disbursement failed. The payout intent remains unprocessed. |
| Void successful | transaction.void.successful | Yes | The payout was cancelled before funds were disbursed. The intent moves to processed. |
| Void failed | transaction.void.failed | Yes | The void attempt failed. The disburse operation continues. |
Sample Payout Webhook
{
"type": "transaction.disburse.successful",
"status_id": "v02QJad",
"operation_id": "LYp5ek0",
"intent": {
"id": "9eQVWzj",
"created": "2026-05-22 08:13:38.259170+00:00",
"custom_fields": null,
"custom_form_answers": null,
"amount": {
"value": "50.00",
"currency": "EGP",
"formatted": 50,
"display_value": "50.00 EGP"
},
"payout_status": {
"status": "DISBURSED"
}
},
"account": {
"id": "4L2W2bg"
},
"transaction": {
"type": "payout",
"id": "7ec43ca6-96ca-45b6-82ef-b6d2c1777c21",
"created": "2026-05-22 08:13:43.405692+00:00",
"status": "disburse.successful",
"billing_data": {
"issuer": "vodafone",
"last_name": "Doe",
"first_name": "John",
"phone_number": "+201111111111"
},
"external_action_message": [],
"provider_transaction_fields": {
"paymob_transaction_id": null
},
"provider_unique_reference": null,
"operations": [
{
"id": "LYp5ek0",
"type": "disburse",
"status": "successful",
"amount": {
"value": "50.00",
"currency": "EGP",
"formatted": 50,
"display_value": "50.00 EGP"
},
"latest_status": {
"id": "v02QJad",
"value": "successful",
"code": "6000",
"provider_error_code": null,
"provider_error_message": null,
"message": "Successful",
"localized_message": "Successful"
},
"statuses": [
{
"id": "8jW5PGr",
"value": "pending",
"code": "8000",
"message": "Pending",
"localized_message": "Pending",
"created": "2026-05-22 08:13:43.436840+00:00"
},
{
"id": "v02QJad",
"value": "successful",
"code": "6000",
"message": "Successful",
"localized_message": "Successful",
"created": "2026-05-22 08:14:37.081263+00:00"
}
]
}
],
"method": {
"id": "gqwWO79",
"display_name": "PaymobPayout - Mobile Wallet",
"service_provider": {
"id": "Vg6lNY9",
"display_name": "Paymob"
}
}
},
"api_version": "1.4"
}
Bulk Payout Webhooks
Bulk payout webhooks are fired at two levels: the bulk request level (status of the overall batch) and the item level (status of each individual payout). Both are delivered to the webhook_url provided when creating the bulk request.
Bulk request events
These events reflect the overall status of the bulk payout request.
| Event | Webhook Type | Description |
|---|---|---|
| Bulk request active | payout.bulk.active | The bulk request has been created and items are queued for validation. Payload includes the full items array with initial statuses. |
| Bulk request cancelled | payout.bulk.cancelled | The bulk request was cancelled. All eligible items that had not yet entered processing are moved to CANCELLED. |
| Bulk request batch completed | payout.bulk.batch_completed | All items in the batch have been processed — validation and execution are complete. Includes item count breakdown per status. |
Sample Bulk Request Webhook
{
"type": "payout.bulk.active",
"data": {
"id": "wgjJ3wg",
"label": "test bulk payout request",
"source": "API",
"status": "ACTIVE",
"items_count": 1,
"validation_pending_items_count": 1,
"scheduled_items_count": 0,
"validation_failed_items_count": 0,
"cancelled_items_count": 0,
"intent_created_items_count": 0,
"intent_creation_failed_items_count": 0,
"active_at": "2026-05-22T09:12:33.859011Z",
"completed_at": null,
"cancelled_at": null,
"created": "2026-05-22T09:12:33.859198Z",
"items": [
{
"id": "jgxdwag",
"merchant_reference": "1234567890",
"bulk_payout_request_id": "wgjJ3wg",
"status": "VALIDATION_PENDING",
"scheduled_date": "2026-06-20T00:00:00Z",
"payout_intent_details": {
"amount": 50,
"webhook_url": "https://webhook.site/b959c817",
"payout_method": "BANK_ACCOUNT",
"amount_currency": "NGN",
"merchant_reference": "1234567890"
},
"validation_result": {},
"linked_intent_id": null,
"created": "2026-05-22T09:12:33.864169Z"
}
]
}
}
Item validation events
These events reflect the validation outcome for each individual item.
| Event | Webhook Type | Description |
|---|---|---|
| Item validation pending | payout.item.validation_pending | The item is queued and waiting for validation. |
| Item scheduled | payout.item.scheduled | Validation passed. The item is scheduled for execution on its scheduled_date. |
| Item validation failed | payout.item.validation_failed | Validation failed. The validation_result field in the payload describes the errors. |
Sample Item Validation Webhook
{
"type": "payout.item.validation_failed",
"data": {
"id": "jgxdwag",
"merchant_reference": "1234567890",
"bulk_payout_request_id": "wgjJ3wg",
"status": "VALIDATION_FAILED",
"scheduled_date": "2026-06-20T00:00:00Z",
"payout_intent_details": {
"amount": 50,
"webhook_url": "https://webhook.site/b959c817",
"payout_method": "BANK_ACCOUNT",
"amount_currency": "NGN",
"merchant_reference": "1234567890"
},
"validation_result": {
"status": "error",
"errors": {
"account_number": ["Invalid key"]
}
},
"linked_intent_id": null,
"created": "2026-05-22T09:12:33.864169Z",
"validation_failed_at": "2026-05-22T09:12:35.316634Z"
}
}
Item execution events
These events are fired on the item's scheduled_date when execution begins.
| Event | Webhook Type | Description |
|---|---|---|
| Intent created | payout.item.intent_created | A payout intent was successfully created for this item. Payout lifecycle webhooks will follow. |
| Intent creation failed | payout.item.intent_creation_failed | The payout intent could not be created. The item moves to INTENT_CREATION_FAILED. Retry in a new bulk request. |
Sample Item Execution Webhook
{
"type": "payout.item.intent_created",
"data": {
"id": "L2WVlAg",
"merchant_reference": "1234567890",
"bulk_payout_request_id": "jZBnOWZ",
"status": "INTENT_CREATED",
"scheduled_date": "2026-05-24T00:00:00Z",
"payout_intent_details": {
"amount": 50,
"webhook_url": "https://webhook.site/b959c817-4188-450c-a4de-e40ded0d4f5a",
"billing_data": {
"name": "MoneyHash",
"bank_account": "035",
"account_number": "0001234567"
},
"payout_method": "BANK_ACCOUNT",
"amount_currency": "NGN",
"merchant_reference": "1234567890"
},
"validation_result": {
"status": "success"
},
"linked_intent_id": "ZdbvNvX",
"created": "2026-05-24T13:38:25.714298Z",
"scheduled_at": "2026-05-24T13:38:26.863991Z",
"cancelled_at": null,
"validation_failed_at": null,
"intent_created_at": "2026-05-24T13:40:00.464801Z",
"intent_creation_failed_at": null
}
}
Payout intent lifecycle events
Once an item creates a payout intent, standard payout webhooks are fired for that intent's disburse and void operations:
transaction.disburse.pending_approvaltransaction.disburse.successfultransaction.disburse.failedtransaction.void.successfultransaction.void.failed
See Payout Webhooks above for event details and payload structure.
Updated 7 days ago