Webhook Events and Delivery
Subscribe to a subset using eventTypes, or set subscribeToAll: true to receive all event types. Event type names are not case-sensitive. Use only the event types listed below.
| Category | Event type | Sent when |
|---|---|---|
| Payment | Payment.Created | A payment has been created |
| Payment | Payment.Completed | A payment has been completed |
| FX contract | Contract.Created | An FX contract has been created |
| FX contract | Contract.Cancelled | An FX contract has been cancelled |
| FX contract | Contract.Completed | An FX contract has been completed |
| Mass payment | Batch.Created | A mass payment batch has been created and is under review with status as Processing |
| Mass payment | Batch.StatusChanged | A mass payment batch is ready for review and can have one of three statuses 1. Contract Unconfirmed 2. Payment Issues 3. Quote Required |
| Mass payment | Batch.Approved | A mass payment batch has been approved |
| Mass payment | Batch.Completed | A mass payment batch has been completed |
| Mass payment | Batch.Deleted | A mass payment batch has been deleted |
Event delivery
- Xe sends each event as an HTTP
POSTto the URL you registered, withContent-Type: application/json. - Your endpoint should respond with a
2xxstatus code to acknowledge the event. Respond promptly: Xe waits up to 30 seconds for a response. - Any custom headers you configured at registration are included with every delivery.
- Events are sent only to registrations with status
Active, and only for the event types you subscribed to (or all events if you subscribed to all).
Authenticating deliveries
Deliveries are not signed. To confirm that a request came from Xe, configure a custom header when you register the webhook (for example an API key) and check that header on every request your endpoint receives.
- Use a long, random value and keep it secret.
- Do not log request headers in your own systems.
- To rotate the value, delete the old registration. register a new webhook with the new header.
- Always serve your endpoint over HTTPS. Registrations over any other scheme are rejected.
Retries
| Response from your endpoint | What Xe does |
|---|---|
2xx | Delivered. No retry. |
408, 429, 5xx, a timeout, or a connection failure | Retried later with increasing delays. |
Any other 4xx | Treated as permanent. Not retried. |
Retries start 1 minute after the failed attempt and the delay doubles each time (1, 2, 4, 8 ... 1024 minutes), for up to 11 retries over roughly 34 hours. If every retry fails, the event is dropped.
Handling duplicates and ordering
- Every event has a unique
EventId. The same event is sent with the sameEventIdon each retry, so use it to ignore duplicates. - A retried event can arrive after events that occurred later. Do not rely on arrival order.
Event payload
Every event has the same envelope. Property names are PascalCase.
| Field | Type | Description |
|---|---|---|
EventId | string | Unique identifier of the event. Identical across retries. |
EventName | string | The event type, for example Payment.Created. |
Timestamp | string | When the notification was created, ISO 8601 in UTC. |
Data | object | Event details. The fields depend on the event type. |
All Data values are strings. If a value is not available, it is sent as an empty string ("") rather than omitted. Status fields are sent as strings, never numbers.
Payment events (Payment.*)
| Field | Type | Description |
|---|---|---|
ClientNumber | string | Your client number. |
ContractNumber | string | Reference of the contract the payment belongs to. |
PaymentNumber | string | Reference of the payment. |
PaymentReference | string | The reference you supplied for the payment. |
PaymentStatus | string | Current status of the payment (see below). |
PaymentStatus values: Approved, AwaitingApproval, Sent, Cancelled, Processing
{
"EventId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"EventName": "Payment.Completed",
"Timestamp": "2026-10-13T10:30:00.123Z",
"Data": {
"ClientNumber": "XEMT11224455",
"ContractNumber": "C12345",
"PaymentNumber": "P1001",
"PaymentReference": "ref_abc123",
"PaymentStatus": "Sent"
}
}FX contract events (Contract.*)
| Field | Type | Description |
|---|---|---|
ClientNumber | string | Your client number. |
ContractNumber | string | Reference of the contract. |
ClientTransferNumber | string | Your transfer number for the contract. |
ContractStatus | string | Current status of the contract. |
{
"EventId": "1cd5dcac-23e8-6c19-b9e4-ad510bd41b2d",
"EventName": "Contract.Created",
"Timestamp": "2026-10-28T23:44:58.3453477Z",
"Data": {
"ClientTransferNumber": "916d581e-b86c-4a78-bc68-4ab9603ac6a",
"ContractStatus": "AwaitingFunds",
"ClientNumber": "XEMT11223344",
"ContractNumber": "C16769019"
}
}Mass payment events (Batch.*)
| Field | Type | Description |
|---|---|---|
ClientNumber | string | Your client number. |
ContractNumber | string | Reference of the batch. |
BatchStatus | string | Current status of the batch. |
{
"EventId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"EventName": "Batch.Completed",
"Timestamp": "2026-10-13T10:30:00.123Z",
"Data": {
"ClientNumber": "XEMT112233445",
"ContractNumber": "MPT121345",
"BatchStatus": "Completed"
}
}Notes
- The status in an event is the status at the time the notification was prepared, which can be later than the moment the event occurred. For the latest state, query the Pay API using the references in the payload.
- New fields may be added to
Datain the future. Ignore fields you do not recognize.