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

# Webhook

> POST alerts to your own endpoint as JSON, with optional request signing

Choose **Webhook** on an alert to POST it to a URL you control, as JSON. It is the channel for wiring alerts into your own systems, or into a no-code tool like Zapier, Make or Power Automate, which is also how you reach a destination Stockful has no channel for yet.

There is nothing to connect. Unlike Slack and Discord, the destination is the URL itself, so an alert can deliver as soon as it has one.

## Setup

Enter your endpoint's **URL**. Each alert is sent as a `POST` with `Content-Type: application/json`.

The URL must be `https`, and must be reachable from the public internet. An address on a private network is refused when you save.

Optionally generate a **signing secret** so your endpoint can verify a request came from Stockful (see [Verifying requests](#verifying-requests)). It is shown once, so copy it then; regenerate it if you lose it. A secret can only be generated on a saved alert.

**Send test** posts a sample alert on demand, so you can confirm your endpoint receives it before waiting for a real one.

## Payload

```json theme={null}
{
  "alert": { "ruleId": 34, "ruleName": "Out of stock", "triggerType": "out_of_stock" },
  "shop": { "domain": "your-store.myshopify.com" },
  "generatedAt": "2026-08-31T10:54:27.428Z",
  "message": {
    "emoji": "🔴",
    "title": "Out of Stock Alert",
    "subtitle": null,
    "fields": [
      { "label": "Product", "value": "Bamboo Cutting Board", "url": "https://admin.shopify.com/..." },
      { "label": "Variant", "value": "Small | SKU: BRD-BMB-SMALL" },
      { "label": "Location", "value": "Main Warehouse" },
      { "label": "Quantity", "value": "0 units" }
    ],
    "body": null,
    "actions": [
      { "label": "Create purchase order", "url": "https://admin.shopify.com/...", "primary": true }
    ],
    "footer": "Alert: Out of stock · Sent by Stockful"
  },
  "text": "Out of Stock Alert: Bamboo Cutting Board at Main Warehouse (0 units)"
}
```

`message` is the alert in structured form, the same content Slack renders as blocks and Discord as an embed. Read whichever parts you need: `fields` carries the label/value pairs, and a field with a `url` links its value. `actions` are the links a person would click.

`text` is the whole alert as one line. If you only want something to display or forward, use that and ignore the rest.

A [summary](/user-guide/alerts/index) sends one POST for the period rather than one per alert, with the entries in `message.body` and its own trigger type of `digest`.

## Verifying requests

If the alert has a signing secret, each POST carries an **`X-Stockful-Signature`** header: the HMAC-SHA256 of the raw request body, hex-encoded, keyed with your secret.

```
X-Stockful-Signature == hex( hmac_sha256(secret, rawRequestBody) )
```

Sign the raw request body bytes, before any JSON parsing, so they match what Stockful signed. Requests are unsigned until you generate a secret.

## Retries

A request that fails because your endpoint is busy or unreachable (a `429`, a `5xx`, a timeout) is retried up to three times with a growing wait, and a `Retry-After` header is honoured.

Anything else is treated as a refusal rather than a hiccup: the alert is recorded as failed and the cooldown stops it being re-sent on every stock change. So an endpoint returning `400` because it dislikes the payload stops receiving that alert until you fix it, rather than being hammered.

## When it stops working

If the endpoint is removed or starts refusing requests, the alert is recorded as failing rather than going quiet, and Stockful emails you the first time it happens rather than on every attempt. The alert itself stays as it is: correct the URL, or the endpoint, and it resumes.
