Provider guide

WooCommerce webhooks, kept properly.

WooCommerce webhooks come from your own WordPress install, which is the whole difference. There is no provider infrastructure retrying on your behalf: if the store is busy, wedged, or mid-update, the delivery is simply not made.

Field notes

How WooCommerce behaves, and where it bites

Self-hosted means the sender is your own site, with your own uptime and your own cron.

How WooCommerce sends

WooCommerce POSTs JSON with the topic in X-WC-Webhook-Topic (order.created, product.updated), a delivery id, the source URL, and a base64 HMAC in X-WC-Webhook-Signature.

Where it bites

  • The sender is your own site. Delivery depends on WordPress cron and on the store being up. A slow host loses webhooks quietly, and nobody upstream is retrying.
  • Webhooks disable themselves. After consecutive failures WooCommerce flips a webhook to disabled and stops. It stays that way until somebody notices.
  • Plugins change the payload. The body reflects whatever plugins were active that day, so historical deliveries are the only record of the old shape.

The vault under it

Point a WebhookVault endpoint at WooCommerce and every delivery is stored in full: headers verbatim, bodies byte-for-byte, labelled with its topic and searchable. Forward it onward to your own handler if you want the relay pattern, replay any delivery once the bug is fixed, and let a Watchdog notice the day it stops arriving.

01

Create an endpoint

Name it woo-orders. Turn on forwarding to your own handler if you want the vault in front of it rather than beside it.

02

Register the capture URL

WooCommerce → Settings → Advanced → Webhooks → Add webhook. Set the delivery URL to the capture URL and pick a topic.

03

Keep everything

Every delivery from here on is on the shelf: searchable, replayable, and watched for the day it goes quiet.

Verify from the record, not just at the door

WooCommerce signs the raw body with the secret you set on the webhook, base64-encoded, in the same family as Shopify's. The vault verifies every capture against it.

The vault stores the signature headers verbatim with every request, so a delivery from last month can still be checked today. Verdicts are part of Solo and up. How verification works →

captured · order.created✓ verified
# headers, stored verbatim
"X-WC-Webhook-Topic": "order.created"
"X-WC-Webhook-Signature": "9Kd2sV…="

{
  "id": 727,
  "status": "processing",
  "currency": "ZAR",
  "total": "49.00",
  "payment_method_title": "Credit card",
  "line_items": [
    { "name": "Field notebook", "quantity": 2 }
  ]
}

Event catalogue

WooCommerce webhook events you'll see

A few of the events WooCommerce sends, not the full list: WooCommerce's own documentation has every one. Each arrives in the vault labelled with its topic.

EventWhat it tells you
order.createdA new order was created in the store.
order.updatedAn order changed: status, items, notes or payment details.
order.deletedAn order was deleted.
product.updatedA product changed: price, stock or details.
customer.createdA customer account was created.

Questions

WooCommerce webhook questions, answered

The three that come up most when WooCommerce is wired to a new endpoint.

Does WooCommerce retry failed webhooks?

Not the way hosted providers do. WooCommerce counts consecutive failed deliveries, and after five (the default) it sets the webhook to Disabled and stops sending until someone switches it back on. A WebhookVault capture URL answers as soon as the delivery is stored, so a slow handler of yours never counts against the webhook.

How do I verify X-WC-Webhook-Signature?

It is a base64 HMAC-SHA256 of the raw request body, keyed with the secret set on the webhook. Recompute it over the bytes as received and compare in constant time. On Solo and up the vault does this at capture and puts the verdict on every row.

Why do my WooCommerce webhooks arrive late, or not at all?

Deliveries are queued and sent by WordPress's scheduler, which by default only runs when the site gets traffic. A quiet store, a switched-off WP-Cron or a stuck queue delays them, and a disabled webhook stops them. WooCommerce → Status → Scheduled Actions shows pending deliveries, and a Watchdog (Solo and up) notices when order.created goes quiet.

Put a vault in front of your store.

Free tier, no card. Point one webhook at it and see what your site is really sending.