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

# Webhook events

> The payment lifecycle event types, delivery headers, and payload.

Each delivery is a single event for one association. Use the `X-Webhook-Event`
header as the reliable event discriminator.

## Event types

| Event type (`type`)  | `X-Webhook-Event`      | When it is sent                   |
| -------------------- | ---------------------- | --------------------------------- |
| `IntentInitiated`    | `intent.initiated`     | A payment was initiated.          |
| `IntentProcessing`   | `intent.processing`    | A payment is being processed.     |
| `IntentSuccessful`   | `intent.successful`    | A payment completed successfully. |
| `IntentFailed`       | `intent.failed`        | A payment failed.                 |
| `IntentRefunding`    | `intent.refunding`     | A refund is in progress.          |
| `IntentRefunded`     | `intent.refunded`      | A payment was refunded.           |
| `IntentRefundFailed` | `intent.refund.failed` | A refund failed.                  |
| `IntentCancelled`    | `intent.cancelled`     | A payment was cancelled.          |

These are the values you subscribe to when you [create a webhook](/webhooks/create).
`IntentSuccessful` and `IntentFailed` correspond to a transaction reaching
`completed` and `failed` respectively.

## Delivery headers

Every delivery is an HTTP `POST` with a JSON body and these headers:

* `X-Webhook-Event`: the dotted event key, for example `intent.successful`.
* `X-Zeam-Signature`: `sha256=<hex>`, an HMAC of the body keyed on
  `X-Webhook-Id`. See [Security](/webhooks/security).
* `X-Association-Id`: the association the event belongs to.
* `X-Webhook-Id`: a unique delivery id. Also the HMAC key. Use it to
  de-duplicate retries.
* `X-Webhook-Ts`: delivery timestamp as Unix milliseconds (UTC). Use it
  to reject stale deliveries. See [Security](/webhooks/security).
* `Content-Type: application/json`.

## Payload

<ResponseField name="type" type="string">
  The event type. Prefer the `X-Webhook-Event` header as the discriminator.
</ResponseField>

<ResponseField name="intentId" type="string">
  The payment intent identifier for this event.
</ResponseField>

<ResponseField name="associationId" type="string">
  The association the event belongs to.
</ResponseField>

<ResponseField name="description" type="string">
  A human-readable description of the event.
</ResponseField>

<ResponseField name="created" type="string">
  ISO 8601 timestamp of when the event was created.
</ResponseField>

<ResponseField name="metaData" type="object">
  Event-specific detail. Treat the shape as event-defined and read fields
  defensively.
</ResponseField>

<ResponseField name="externalReference" type="string | null">
  Your own reference from the original request, when present. Use it to reconcile
  the event with your records.
</ResponseField>

<ResponseField name="transactionHash" type="string | null">
  The Stellar transaction hash, once the payment is on-chain.
</ResponseField>

```json Example delivery theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "type": "IntentSuccessful",
  "intentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "associationId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "description": "Payment intent completed successfully.",
  "created": "2026-01-15T10:32:07.512Z",
  "metaData": {},
  "externalReference": "order-9931",
  "transactionHash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
```

## Reconcile the event

The payload does not include the amount or final status. Use `intentId` or your
`externalReference` to look the payment up with
[`GET /v1/transactions/{transactionId}`](/api-reference/introduction) (the
`transactionRecordId` you received in the `202` response) and act on the
authoritative record.
