> For the complete documentation index, see [llms.txt](https://api.shopwaive.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://api.shopwaive.com/reference/webhooks.md).

# Webhooks

Receive HTTP POST payloads when Shopwaive events occur — webhook events, payload fields, delivery headers, and HMAC-SHA256 signature validation

Webhooks let your service receive an HTTP POST payload whenever selected events occur in Shopwaive. They are available for Shopify stores and Shopify headless sites.

{% hint style="info" %}
Webhooks require organization owner status and developer access. Contact <support@shopwaive.com> to enable developer access for your organization.
{% endhint %}

## Creating a webhook

Webhooks are configured from the Shopwaive web interface or the [REST API](https://api.shopwaive.com). In the web interface, open the avatar menu in the upper-right corner, go to the **Webhooks** settings section, and select **Add webhook**. Provide:

* **Payload URL** — the URL where you'd like to receive payloads
* **Event types** — the events to subscribe to (individual webhook actions cannot be subscribed to separately)
* **Secret** (optional, recommended) — a random string with high entropy, used to validate deliveries
* **Active** — enable the webhook immediately

Upon creation, Shopwaive sends a simple `ping` event to confirm the webhook is set up correctly. You can create up to 5 webhooks for each event on each installation target. By default, webhooks are not subscribed to any events. Payloads are capped at 25 MB. IPv6 is not currently supported.

## Events

* `available_balance` — a customer's available balance changes. The `action` field carries the cause: `created`, `adjusted`, `redeemed`, `deleted`, `refund`, `imported`, `rest_api`, or `expired`.
* Order `invoice_url` created with credit applied, and orders placed with credit.
* Customer `email` sent from an action (`campaign_sent` or `manually_sent`).

### `available_balance` payload

| Field                    | Type   | Description                                                                                                                   |
| ------------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `action`                 | string | The action performed                                                                                                          |
| `available_balance.pre`  | string | Balance prior to the event                                                                                                    |
| `available_balance.post` | string | Balance after the event                                                                                                       |
| `transaction`            | string | Associated transaction amount                                                                                                 |
| `customer_email`         | string | Customer's email address                                                                                                      |
| `order_id`               | string | Present only when `action` is `redeemed`                                                                                      |
| `organization`           | object | Present when the webhook target is an organization: `id`, `url` (required); `platform`, `currency`, `contactEmail` (optional) |

## Delivery headers

| Header                                      | Description                                                                |
| ------------------------------------------- | -------------------------------------------------------------------------- |
| `X-Shopwaive-Hook-ID`                       | The unique identifier of the webhook                                       |
| `X-Shopwaive-Event`                         | The name of the event that triggered the delivery                          |
| `X-Shopwaive-Delivery`                      | A GUID identifying the delivery                                            |
| `X-Shopwaive-Signature-256`                 | HMAC-SHA256 hex digest of the request body, signed with the webhook secret |
| `X-Shopwaive-Hook-Installation-Target-Type` | The type of resource where the webhook was created                         |
| `X-Shopwaive-Hook-Installation-Target-ID`   | The unique identifier of that resource                                     |

## Validating deliveries

If you set a secret, validate each delivery before processing it:

1. Read the `X-Shopwaive-Signature-256` header. Its value always starts with `sha256=`.
2. Compute an HMAC-SHA256 hex digest of the raw request body using your webhook secret.
3. Compare your digest to the header value with a constant-time comparison — never a plain `==` operator. Use `crypto.timingSafeEqual` (Node.js), `secure_compare` (Ruby), or `crypto.subtle.verify()` (Web Crypto API).

Test vector for verifying your implementation — secret `It's a Secret to Everybody`, payload `Hello, World!`:

```
X-Shopwaive-Signature-256: sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17
```
