> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpaylabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XPayLabs Webhook Event Types — Complete Reference

> Complete reference for all XPayLabs webhook event types — order events (PENDING, SUCCESS, EXPIRED, FAILED) and collection events (PENDING, SUCCESS, FAILED).

XPayLabs sends webhook notifications based on the `NotifyType` enum. Each notification corresponds to a change in state of an order or a collection sweep.

## Event Types

| Event Type                   | Triggered When                                                  | Payload       |
| ---------------------------- | --------------------------------------------------------------- | ------------- |
| `ORDER_PENDING`              | A new order is created and is awaiting customer payment         | NotifyOrder   |
| `ORDER_PENDING_CONFIRMATION` | A blockchain transaction is detected but awaiting confirmations | NotifyOrder   |
| `ORDER_SUCCESS`              | Payment confirmed and order completed successfully              | NotifyOrder   |
| `ORDER_EXPIRED`              | Order expired before payment was received                       | NotifyOrder   |
| `ORDER_FAILED`               | Payment transaction failed                                      | NotifyOrder   |
| `COLLECT_PENDING`            | Collection sweep (hot-to-cold transfer) is initiated            | NotifyCollect |
| `COLLECT_SUCCESS`            | Collection sweep completed successfully                         | NotifyCollect |
| `COLLECT_FAILED`             | Collection sweep failed                                         | NotifyCollect |

***

## Order Events (`ORDER_*`)

### `ORDER_PENDING`

Sent when a collection or payout order is created and is awaiting the next action (customer payment for collections, processing for payouts).

```json theme={null}
{
  "sign": "a1b2c3d4e5f6...",
  "timestamp": 1717000000,
  "nonce": "nonce_001",
  "notifyType": "ORDER_PENDING",
  "data": {
    "orderId": "order_1042",
    "uid": "user_42",
    "orderType": "COLLECTION",
    "status": "PENDING",
    "reason": null,
    "amount": "250.00",
    "actualAmount": null,
    "fee": "0.00",
    "transaction": null
  }
}
```

### `ORDER_PENDING_CONFIRMATION`

Sent when a blockchain transaction is detected but has not yet reached the required number of block confirmations. The `transaction` field is populated with the detected transaction details.

```json theme={null}
{
  "sign": "a1b2c3d4e5f6...",
  "timestamp": 1717000050,
  "nonce": "nonce_002",
  "notifyType": "ORDER_PENDING_CONFIRMATION",
  "data": {
    "orderId": "order_1042",
    "orderType": "COLLECTION",
    "status": "PENDING_CONFIRMATION",
    "amount": "250.00",
    "actualAmount": "250.00",
    "fee": "0.00",
    "transaction": {
      "chain": "TRON",
      "symbol": "USDT",
      "txid": "a1b2c3d4e5f6...",
      "from": "TXyz...",
      "to": "TWkKZkmuB8DpVeiMoHiKf99ZoFHzk73CqR",
      "amount": "250.00",
      "blockNum": 12345678,
      "confirmedNum": 1,
      "status": "PENDING",
      "timestamp": 1717000045
    }
  }
}
```

### `ORDER_SUCCESS`

Sent when the payment is fully confirmed (required block confirmations reached) or a payout completes successfully.

```json theme={null}
{
  "sign": "a1b2c3d4e5f6...",
  "timestamp": 1717000100,
  "nonce": "nonce_003",
  "notifyType": "ORDER_SUCCESS",
  "data": {
    "orderId": "order_1042",
    "orderType": "COLLECTION",
    "status": "SUCCESS",
    "amount": "250.00",
    "actualAmount": "250.00",
    "fee": "0.00",
    "transaction": {
      "chain": "TRON",
      "symbol": "USDT",
      "txid": "a1b2c3d4e5f6...",
      "from": "TXyz...",
      "to": "TWkKZkmuB8DpVeiMoHiKf99ZoFHzk73CqR",
      "amount": "250.00",
      "confirmedNum": 19,
      "status": "SUCCESS",
      "timestamp": 1717000045
    }
  }
}
```

### `ORDER_EXPIRED`

Sent when an order reaches its expiry time without receiving the required payment.

```json theme={null}
{
  "sign": "a1b2c3d4e5f6...",
  "timestamp": 1717086401,
  "nonce": "nonce_004",
  "notifyType": "ORDER_EXPIRED",
  "data": {
    "orderId": "order_1042",
    "orderType": "COLLECTION",
    "status": "EXPIRED",
    "reason": "Order expired",
    "amount": "250.00",
    "actualAmount": null,
    "fee": "0.00",
    "transaction": null
  }
}
```

### `ORDER_FAILED`

Sent when a payout transaction fails or a collection transaction is rejected by the blockchain.

```json theme={null}
{
  "sign": "a1b2c3d4e5f6...",
  "timestamp": 1717000200,
  "nonce": "nonce_005",
  "notifyType": "ORDER_FAILED",
  "data": {
    "orderId": "payout_001",
    "orderType": "PAYOUT",
    "status": "FAILED",
    "reason": "Insufficient balance",
    "amount": "50.00",
    "actualAmount": "0.00",
    "fee": "0.00",
    "transaction": null
  }
}
```

***

## Collection Events (`COLLECT_*`)

Collection events are sent when the gateway performs automatic hot-to-cold wallet sweeps (settlement). These are distinct from order events — they relate to the internal movement of funds between the gateway's wallets.

| Event Type        | Triggered When                                              |
| ----------------- | ----------------------------------------------------------- |
| `COLLECT_PENDING` | A sweep from the hot wallet to the cold wallet is initiated |
| `COLLECT_SUCCESS` | The sweep transaction confirmed on-chain                    |
| `COLLECT_FAILED`  | The sweep transaction failed                                |

***

## Best Practices

1. **Respond with `200` quickly.** Return `200 OK` immediately and process the event asynchronously in a background worker.

2. **Verify the signature.** Always validate the `sign` field using your `webhook-secret` before acting on any event.

3. **Deduplicate with `nonce`.** The same event may be delivered more than once. Store processed nonces in your database and skip duplicates.

4. **Check `notifyType` first.** Route to different handlers based on the event type.

5. **Handle `ORDER_PENDING_CONFIRMATION`.** Use this event to show "payment detected" in your UI before the transaction is fully confirmed.
