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

# Validate Shopify webhook delivery and payloads

> Capture Shopify order, product, and customer webhooks, verify X-Shopify-Hmac-Sha256 signatures, and replay events to staging after a downstream fix.

Shopify signs every webhook delivery with a Base64 HMAC-SHA256 value in the `X-Shopify-Hmac-Sha256` header. Use the Webhook Debugger to verify your shared secret, inspect order and inventory events, and replay individual deliveries to staging — without waiting for real customer activity to trigger a new event.

## Configure the actor for Shopify

Start the actor with the following input. Replace `shopify_shared_secret` with the client secret from your Shopify app or the shared secret shown in your store's webhook settings.

```json theme={null}
{
  "urlCount": 2,
  "retentionHours": 72,
  "authKey": "shopify-launch-key",
  "enableJSONParsing": true,
  "maskSensitiveData": true,
  "redactBodyPaths": [
    "body.customer.email",
    "body.billing_address.phone"
  ],
  "signatureVerificationSecret": "shopify_shared_secret",
  "signatureVerification": {
    "provider": "shopify"
  },
  "defaultResponseCode": 200,
  "defaultResponseBody": "{\"ok\":true}",
  "forwardUrl": "https://staging.example.com/webhooks/shopify",
  "forwardHeaders": true,
  "alerts": {
    "slack": {
      "webhookUrl": "https://hooks.slack.com/services/AAA/BBB/CCC"
    }
  },
  "alertOn": ["signature_invalid", "5xx"]
}
```

Using two webhook IDs lets you route separate topics — for example, one for `orders/*` traffic and one for `inventory/*` or `fulfillment/*` — without mixing events in the same log view.

Shopify verification runs against the preserved raw request body before JSON parsing, so `signatureValid` is accurate even with `enableJSONParsing` enabled.

After the actor starts, call `/info` to confirm both webhook IDs before updating Shopify.

## Register the endpoint in Shopify

<Steps>
  <Step title="Open webhook settings">
    In your Shopify admin, go to **Settings → Notifications** (or **Settings → Webhooks** for newer admin versions).
  </Step>

  <Step title="Create a webhook">
    Click **Create webhook** and select the event topic you want to test, such as `orders/create`.
  </Step>

  <Step title="Paste the endpoint URL">
    Copy a `/webhook/:id` URL from `/info` and paste it into the **URL** field. Repeat for each topic using the appropriate webhook ID.
  </Step>

  <Step title="Set the format">
    Set the format to **JSON**.
  </Step>

  <Step title="Save and send a test notification">
    Save the webhook and use the **Send test notification** button to verify the endpoint is reachable and the signature check passes.
  </Step>
</Steps>

<Note>
  Keep `forwardHeaders: true` if your downstream receiver also validates `X-Shopify-Hmac-Sha256`. The actor preserves the original signature header when forwarding.
</Note>

## Test order, product, and customer events

After Shopify delivers a webhook, query `/logs` to see what was captured. Filter by topic using the `X-Shopify-Topic` header:

```bash theme={null}
GET /logs?webhookId=wh_abc123&headers.x-shopify-topic=orders/create&signatureValid=true
```

A captured order event looks like this:

```json theme={null}
{
  "id": "evt_8m2L5p9xR",
  "webhookId": "wh_abc123",
  "timestamp": "2026-01-30T12:00:00.000Z",
  "method": "POST",
  "statusCode": 200,
  "signatureValid": true,
  "signatureProvider": "shopify",
  "headers": {
    "x-shopify-topic": "orders/create",
    "x-shopify-shop-domain": "yourstore.myshopify.com"
  },
  "body": {
    "id": 820982911946154500,
    "financial_status": "paid",
    "total_price": "59.99"
  }
}
```

To check for signature failures:

```bash theme={null}
GET /logs?webhookId=wh_abc123&signatureValid=false
```

To check the forwarding sync status, call `/system/metrics` to see error counts and the last sync time.

## Inspect and replay captured events

If a delivery reached the actor but failed downstream, replay the original captured event to staging after fixing the handler:

```bash theme={null}
curl -X POST \
  "https://<run-id>.runs.apify.net/replay/wh_abc123/evt_8m2L5p9xR?url=https%3A%2F%2Fstaging.example.com%2Fwebhooks%2Fshopify"
```

The replay sends the original method and payload. If the body was offloaded to storage due to size, the actor hydrates it automatically before sending.

<Tip>
  Set `responseDelayMs` to simulate slow acknowledgements and observe how Shopify retries. Append `?__status=503` to the webhook URL to force a temporary failure without changing the saved input.
</Tip>

## Common failure patterns

| Signal                  | What it usually means                                                    | What to do                                                                                          |
| :---------------------- | :----------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------- |
| `signatureValid=false`  | Shared secret mismatch or body modification before validation            | Re-check the Shopify app secret and compare the raw captured body against the expected payload      |
| Duplicate order entries | Shopify retried after a delayed or failed acknowledgement                | Use the captured event ID and your order ID mapping to confirm idempotency logic                    |
| Forwarding failures     | The original webhook was accepted but forwarding to staging failed later | Check `/system/metrics` for error counts, fix the downstream target, then replay the original event |
