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.
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.
Register the capture URL
WooCommerce → Settings → Advanced → Webhooks → Add webhook. Set the delivery URL to the capture URL and pick a topic.
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 →
# 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.
| Event | What it tells you |
|---|---|
| order.created | A new order was created in the store. |
| order.updated | An order changed: status, items, notes or payment details. |
| order.deleted | An order was deleted. |
| product.updated | A product changed: price, stock or details. |
| customer.created | A 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.
Sign up with GitHub, Google or email. Two-factor authentication is required on every account, Free included, for account security.