> For the complete documentation index, see [llms.txt](https://docs.neox.vn/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.neox.vn/docs/global/global-collections/integration/event-notification.md).

# Event Notification

Global Collections is an **event-driven** service. Many operations complete asynchronously — virtual account approval, incoming funds, payout results, refund and sub-merchant status changes are all delivered to the Merchant as **webhooks**.

This page explains how to configure and verify webhooks. The payload of each event type is documented in its own webhook page (linked below).

## Configuration

There is no self-service Merchant Portal screen for webhook configuration. Instead:

* For most event types, `webhookUrl` is supplied directly in the request body of the relevant Create API call — the URL is scoped to that specific request/entity, not managed separately. See:
  * [Onboard Sub-Merchant](/docs/global/global-collections/integration/sub-merchants/api-onboard-sub-merchant.md) for `SUBMERCHANT_ONBOARDING_RESULT`.
  * [Create Virtual Account](/docs/global/global-collections/integration/virtual-accounts/api-create-virtual-account.md) for the virtual account events.
  * [Register Beneficiary](/docs/global/global-collections/integration/beneficiaries/api-register-beneficiary.md) for `BENEFICIARY_REGISTRATION`.
  * [Create Payout Request](/docs/global/global-collections/integration/payout-requests/api-create-payout-request.md) for the payout events.
* The **collection-transaction event group** (7 event types — see the catalogue below) is the exception: it has no natural per-request origin, so its delivery URL and signing secret are **pre-configured centrally** for your merchant account rather than supplied by the Merchant. There is no self-service UI for this today — contact NeoX to have it configured. This also applies to refund status changes on trade/platform collections: although [Create Refund Request](/docs/global/global-collections/integration/refund-requests/api-create-refund-request.md) accepts a `webhookUrl` field, it is not used for webhook delivery — refund status is delivered through this same pre-configured collection-transaction channel instead. See [Refund Requests Webhook](/docs/global/global-collections/integration/refund-requests/webhook.md) for details.

## Delivery

* NeoX sends an HTTP `POST` request to the configured URL whenever a subscribed event occurs.
* The request body is `application/json`.
* The Merchant endpoint must respond with **HTTP 200** to acknowledge receipt.
* If the endpoint does not acknowledge, NeoX **retries** the delivery with a backoff schedule. Webhook handlers must therefore be **idempotent** — the same event may be delivered more than once. De-duplicate on the event's primary identifier (e.g. `requestId`, `transId`, `collectionOrderId`).

## Verifying `secureHash`

Every webhook payload includes a `secureHash` field, computed and embedded in the JSON body (never sent as a header). To verify it:

1. Take all payload fields **except** `secureHash` itself.
2. Sort the keys in alphabetical order, then concatenate their **values only** — not `key=value` pairs, just the values, in that sorted-key order.
3. Append the **Secret Key** configured for your merchant account.
4. Compute the `SHA256` hash of the resulting string and Base64-encode the digest.
5. Compare the result with the received `secureHash`. Reject the payload if they differ.

## Event catalogue

| #  | Type                              | Triggered when                                                                   | Payload reference                                                                                   |
| -- | --------------------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| 1  | `SUBMERCHANT_ONBOARDING_RESULT`   | A sub-merchant onboarding application reaches a terminal review outcome.         | [Sub-Merchants Webhook](/docs/global/global-collections/integration/sub-merchants/webhook.md)       |
| 2  | `VA_SUPPLEMENT_REQUIRED`          | A virtual account application requires supplementary KYC material.               | [Virtual Accounts Webhook](/docs/global/global-collections/integration/virtual-accounts/webhook.md) |
| 3  | `TRADE_COLLECTION_RECEIVED`       | Funds arrive in a virtual account for a trade-collection order.                  | [Collections Webhook](/docs/global/global-collections/integration/collections/webhook.md)           |
| 4  | `PLATFORM_COLLECTION_RECEIVED`    | Funds arrive in a virtual account for a platform-collection order.               | [Collections Webhook](/docs/global/global-collections/integration/collections/webhook.md)           |
| 5  | `COLLECTION_COMPLETED`            | A collection order finishes matching/review and funds are credited.              | [Collections Webhook](/docs/global/global-collections/integration/collections/webhook.md)           |
| 6  | `COLLECTION_REJECTED`             | A collection order's review is rejected.                                         | [Collections Webhook](/docs/global/global-collections/integration/collections/webhook.md)           |
| 7  | `COLLECTION_CANCEL`               | A collection transaction is cancelled.                                           | [Collections Webhook](/docs/global/global-collections/integration/collections/webhook.md)           |
| 8  | `TRADE_COLLECTION_REFUND_PROCESS` | A refund against a collection order starts processing.                           | [Refund Requests Webhook](/docs/global/global-collections/integration/refund-requests/webhook.md)   |
| 9  | `TRADE_COLLECTION_REFUND_SUCCESS` | A refund against a collection order completes successfully.                      | [Refund Requests Webhook](/docs/global/global-collections/integration/refund-requests/webhook.md)   |
| 10 | `VA_CREATION_RESULT`              | A virtual account application reaches a terminal outcome (approved or rejected). | [Virtual Accounts Webhook](/docs/global/global-collections/integration/virtual-accounts/webhook.md) |
| 11 | `VA_MATERIAL_SUPPLEMENT`          | Supplementary virtual account material is reviewed.                              | [Virtual Accounts Webhook](/docs/global/global-collections/integration/virtual-accounts/webhook.md) |
| 12 | `PAYMENT_INITIAL`                 | A payout request is accepted and initiated for processing.                       | [Payout Requests Webhook](/docs/global/global-collections/integration/payout-requests/webhook.md)   |
| 13 | `PAYMENT_RESULT`                  | A payout request (or per-payee distribution) reaches a terminal outcome.         | [Payout Requests Webhook](/docs/global/global-collections/integration/payout-requests/webhook.md)   |
| 14 | `BENEFICIARY_REGISTRATION`        | A beneficiary registration is reviewed, including supplement requests.           | [Beneficiaries Webhook](/docs/global/global-collections/integration/beneficiaries/webhook.md)       |

{% hint style="info" %}
Events #8 and #9 relate to refund outcomes and are documented on the [Refund Requests Webhook](/docs/global/global-collections/integration/refund-requests/webhook.md) page, alongside the refund flow they belong to. They are still delivered through the collection-transaction channel described above, not to a per-request `webhookUrl` — see that page for why.
{% endhint %}
