# Webhook Events

This page catalogs webhook event types, payload shapes, and delivery behavior. For registration, headers, and security, start with [Webhooks](/docs/developers/webhooks). For HMAC verification steps, see [Webhook Signature Verification](/docs/developers/webhook-signature-verification).

## Envelope format

Every delivered webhook uses the same top-level structure:

```json
{
  "data": {
    "notification_type": "...",
    ...
  }
}
```

Fluxis signs the **entire parsed JSON body** (the object containing `data`), not the inner `data` object alone and not raw request bytes. Optional fields omitted from the payload (Go `omitempty`) affect the signature—always verify against the JSON you actually received.

### Delivery headers

| Header | Description |
| ------ | ----------- |
| `X-Request-Signature` | Hex-encoded HMAC-SHA256 |
| `X-Request-Timestamp` | Unix timestamp (seconds) |
| `Content-Type` | `application/json` |

Reject requests older than **300 seconds**. See the [signature verification guide](/docs/developers/webhook-signature-verification) for the full algorithm.

## Event types

Webhooks are registered **per account** via `POST /v1/account/{accountID}/webhook`. Each registration subscribes to one `event_type`:

| `event_type` | `notification_type` in payload | Delivery status |
| ------------ | ------------------------------ | --------------- |
| `payment_request` | `payment_request_status_update` | **Active** |
| `refund` | `refund_status_update` | **Active** (on refund create) |
| `incoming_transfer` | — | **Reserved / future** |

::::info
`incoming_transfer` can be registered in the API today, but **no production code path dispatches this event yet**. Do not build integrations that depend on it until Fluxis announces availability.
::::

---

## `payment_request` events

Subscribe with `"event_type": "payment_request"`.

### When they fire

Fluxis sends a webhook when the payment request status changes to:

| Status | Trigger |
| ------ | ------- |
| `processing` | On-chain deposit detected; finality check queued |
| `completed` | Full payment received |
| `underpaid` | Payment received but below requested amount |
| `overpaid` | Payment received above requested amount |

Statuses such as `pending`, `created`, `expired`, `failed`, and `confirmed` do **not** trigger `payment_request` webhooks today.

### Payload fields

```json
{
  "data": {
    "notification_type": "payment_request_status_update",
    "payment_request_id": "aa5d6c80-0b0b-4a2a-bbc8-14a41e6245bf",
    "payment_request_type": "fixed",
    "external_reference_id": "order-123",
    "status": "completed",
    "point_of_sale_id": "3cc1f7ca-c017-4e7e-b00d-aca0da6e464e",
    "account_id": "c87464d1-c54a-48c3-80c9-bee4fddf593d"
  }
}
```

| Field | Description |
| ----- | ----------- |
| `notification_type` | Always `payment_request_status_update` |
| `payment_request_id` | Fluxis payment request UUID |
| `payment_request_type` | `fixed`, `dynamic`, `pre_loaded`, or `open` |
| `external_reference_id` | Your order reference (optional; omitted when unset) |
| `status` | Current payment request status |
| `point_of_sale_id` | POS that created the payment request |
| `account_id` | Owning account (optional; omitted when unset) |

### Integration guidance

- Treat `processing` as "payment detected" — wait for a terminal status before fulfilling goods
- Handle `underpaid` and `overpaid` per your POS configuration; you may need to issue a [refund](/docs/developers/refunds)
- Use `external_reference_id` to map events back to your order system

---

## `refund` events

Subscribe with `"event_type": "refund"`.

### When they fire

A webhook is sent when a refund is **created** via `POST /v1/refunds/payment-request/{paymentRequestID}`. Additional status updates (`completed`, `failed`) will fire once on-chain refund execution is implemented.

### Payload fields

```json
{
  "data": {
    "notification_type": "refund_status_update",
    "refund_request_id": "123e4567-e89b-12d3-a456-426614174000",
    "payment_request_id": "aa5d6c80-0b0b-4a2a-bbc8-14a41e6245bf",
    "status": "processing",
    "amount": "50.00"
  }
}
```

| Field | Description |
| ----- | ----------- |
| `notification_type` | Always `refund_status_update` |
| `refund_request_id` | Fluxis refund UUID |
| `payment_request_id` | Original payment request |
| `status` | `processing`, `completed`, or `failed` |
| `amount` | Refund amount as decimal string |

::::warning
On-chain refund execution is not yet implemented. Expect `status: "processing"` on create until outbound transfers are live. See [Refunds](/docs/developers/refunds).
::::

---

## `incoming_transfer` (reserved)

Subscribe with `"event_type": "incoming_transfer"`.

This event type is defined in the API and can be registered, but **Fluxis does not dispatch `incoming_transfer` webhooks in production code today**. It is reserved for a future feature (direct inbound transfers not tied to a payment request flow).

::::note
If you register an `incoming_transfer` webhook, it will remain idle until Fluxis enables delivery. Monitor release notes before building against this event.
::::

---

## Testing webhooks

Send a signed test payload to your endpoint:

```
POST /v1/account/{accountID}/webhook/{webhookID}/test
```

The test uses a sample `payment_request_status_update` body. Verify it with the same algorithm as production events—see [Webhook Signature Verification](/docs/developers/webhook-signature-verification).

## Status → webhook matrix

| Payment request status | Webhook sent? |
| ---------------------- | ------------- |
| `pending` | No |
| `created` | No |
| `processing` | Yes |
| `completed` | Yes |
| `underpaid` | Yes |
| `overpaid` | Yes |
| `confirmed` | No |
| `expired` | No |
| `failed` | No |

## Related documentation

- [Webhooks](/docs/developers/webhooks) — registration, secrets, best practices
- [Webhook Signature Verification](/docs/developers/webhook-signature-verification) — HMAC-SHA256 verification
- [Payment Requests](/docs/key-concepts/payment-request) — full status lifecycle
- [Refunds](/docs/developers/refunds) — refund API and statuses
