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

# Payment Webhooks

> Receive and verify payment status callbacks from LauncX.

When a payment changes state, LauncX `POST`s a JSON callback to your registered URL from the [outbound IPs](/prerequisites#5-configure-your-webhook-endpoint).

## Payload

| Field              | Type   | Notes                                                  |
| ------------------ | ------ | ------------------------------------------------------ |
| `orderId`          | string | Payment UUID.                                          |
| `payerId`          | string | The `playerId` you supplied when creating the payment. |
| `status`           | string | `PAID` \| `EXPIRED` \| `FAILED` \| `PENDING`.          |
| `settlementStatus` | string | `PENDING` \| `COMPLETED` \| `FAILED`.                  |
| `grossAmount`      | number | Original payment amount.                               |
| `feeLauncx`        | number | Platform fee charged.                                  |
| `netAmount`        | number | `grossAmount - feeLauncx`.                             |
| `qrPayload`        | string | QRIS payload string.                                   |
| `timestamp`        | string | RFC3339 UTC, e.g. `2026-06-15T08:42:11Z`.              |
| `nonce`            | string | Unique UUID per delivery (use for replay protection).  |

```json theme={null}
{
  "orderId": "9f2c1a4b-7c3e-4d9a-b8e2-3c1d5a6f0e21",
  "payerId": "player-00123",
  "status": "PAID",
  "settlementStatus": "PENDING",
  "grossAmount": 250000,
  "feeLauncx": 1750,
  "netAmount": 248250,
  "qrPayload": "00020101021226680016ID.CO.QRIS.WWW...",
  "timestamp": "2026-06-15T08:42:11Z",
  "nonce": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}
```

<Note>
  `status` reflects the payment lifecycle; `settlementStatus` tracks settlement independently (`COMPLETED` once settled, `FAILED` if the payment expired/failed, otherwise `PENDING`).
</Note>

## Verifying the signature

Each delivery includes an HMAC signature header:

| Header                 | Value                                                  |
| ---------------------- | ------------------------------------------------------ |
| `X-Callback-Signature` | `hex( HMAC_SHA256( rawRequestBody, CallbackSecret ) )` |

Compute the HMAC-SHA256 of the **raw request body bytes** (all ten fields, exactly as received — do not re-serialize) using your Callback Secret, hex-encode it, and compare against `X-Callback-Signature`.

## Delivery & retries

* Up to **4 attempts** with backoff (immediate, 1s, 2s).
* Any `2xx` response is treated as success; respond `2xx` quickly and process asynchronously.
