WooCommerce sits on WordPress, which means many of your automations ultimately depend on one thing: being told promptly when something happens. A new order should reach the warehouse, a refund should reach accounting and a stock change should reach the marketplace. The mechanism WooCommerce offers for that is the webhook, and it is useful and fussier than it looks.
This guide explains how webhooks work in WooCommerce, how to set them up and secure them, what delivery looks like, why they sometimes stop firing and how to design the receiving side. It complements Shopify webhooks explained, since the principles carry over, and duplicate orders and idempotency. Check WooCommerce’s documentation for current options, as versions differ.
What a webhook is
A webhook is a message from one system to another, sent when an event occurs. Instead of your automation asking WooCommerce every minute whether anything changed, WooCommerce sends the details the moment it happens. The message is an HTTP POST to a URL you supply, carrying the resource as JSON and headers that identify the event and carry a signature.
| Approach | How it works | Pros | Cons |
|---|---|---|---|
| Webhook | WooCommerce pushes the event to your URL | Fast, efficient, event-driven | Delivery can fail or repeat; endpoint must be available |
| Polling the REST API | You ask for changes on a schedule | Simple and under your control | Delay, more load, easy to miss changes between runs |
| Hooks in custom code | A plugin reacts inside WordPress | No network hop | Needs development and maintenance |
| Both | Webhook for speed, scheduled check for safety | Resilient | Slightly more to build |
Available topics
WooCommerce provides topics for common resources: orders, products, customers and coupons, each with created, updated, deleted and restored events, and you can add custom action topics. Choose the narrowest topic that serves the purpose. An “order updated” webhook fires on many changes, including status transitions, notes and edits, so your handler needs to ignore ones that do not matter.
| Topic | Use it for | Watch for |
|---|---|---|
| Order created | Sending new orders to fulfilment or accounting | May fire before payment completes, depending on gateway and status |
| Order updated | Status changes, refunds, edits | Fires often; compare status before acting |
| Order deleted | Cleaning external records | Trashing versus permanent deletion |
| Product updated | Syncing catalogue changes to feeds and marketplaces | Stock changes may not trigger it in all cases |
| Customer created | Syncing contacts | Consent and privacy rules |
| Coupon events | Syncing discount codes | Rarely needed |
Create a webhook
- In the WordPress admin, open WooCommerce settings, Advanced, then Webhooks, and add a webhook.
- Give it a clear name, such as “Orders to fulfilment (production)”.
- Set the status to Active. Choose the topic.
- Enter the delivery URL, which must be reachable by your server over HTTPS.
- Set a strong secret and store it securely in the receiving system.
- Select the API version that your receiving code expects.
- Save, then trigger a test event, such as a test order, and confirm delivery.
Use separate webhooks for staging and production, and separate secrets. A webhook that sends test orders to a live fulfilment system is a classic and expensive mistake.
Verify the signature
Anyone who finds your endpoint URL can send it data. WooCommerce signs each delivery with a header containing a hash of the body made with your secret. The receiving code recomputes the hash from the raw body and compares it, using a constant-time comparison, before doing anything. Verify against the raw bytes received, not a re-serialised version of the JSON, because even a harmless difference in spacing changes the hash. Reject requests that fail, and log them. Also keep the endpoint URL non-obvious, restrict methods and avoid exposing details in error messages.
Receive and respond
- Read the raw body and headers.
- Verify the signature.
- Check the topic header and the event id or resource id.
- Write the event to a queue or table.
- Return a 200 response quickly.
- Process from the queue in a worker, with retries and logging.
Doing slow work inside the request, such as calling several APIs, risks a timeout, which WooCommerce counts as a failure. Accept first, process after. If you use a tool such as n8n, Make or Zapier as the receiver, the same principle applies: respond early where the tool allows and keep downstream steps robust. See n8n with Shopify for patterns that apply equally to WooCommerce.
Delivery, failures and disabling
WooCommerce delivers webhooks through its background scheduling system, so delivery is not instantaneous and depends on that system running. If the receiving URL returns an error or does not respond, WooCommerce records the failure and retries, and after a number of consecutive failures it can set the webhook to disabled. A disabled webhook silently stops sending events, which explains many reports of webhooks that “stopped working”. Check the webhook list for status and review the logs.
| Symptom | Likely cause | Fix |
|---|---|---|
| Webhook status is disabled | Repeated delivery failures | Fix the endpoint, then set it to active |
| No deliveries at all | Scheduler not running, WP-Cron disabled without a real cron, or caching/security plugin blocking | Run the scheduler on a real cron; check logs |
| Delay of several minutes | Scheduler runs on traffic or low frequency | Use a system cron to trigger the scheduler regularly |
| Receiver sees duplicates | Retries, multiple updates or two webhooks configured | Idempotent handling; remove duplicate webhooks |
| Signature mismatch | Wrong secret or re-serialised body | Use raw body and the correct secret |
| Endpoint blocked | Firewall, bot protection or rate limiting | Allow the sender or use a non-blocked route |
| Payload missing data | Event fired before data was saved | Fetch the full resource through the API when needed |
Make handlers safe to run twice
Assume every event can arrive more than once, out of order or late. Store the resource id and a version or modified time, and skip events older than what you have already processed. Use the order id as the unique key when creating records elsewhere. For actions with side effects, such as sending an email or creating a purchase order, record that you did it and check first.
Add a safety net
Even a well-built webhook setup will occasionally miss an event. A scheduled job that asks the REST API for orders modified in the last hour and compares them with what you have processed catches the gaps. It is cheap, simple and the difference between occasional silent loss and none. Alert if the number of webhook events in a period is much lower than the number of orders. Our guide to monitoring store automations shows how to build such checks.
Security and privacy
- Use HTTPS endpoints only.
- Keep secrets out of code repositories and logs.
- Send only the topics and fields the receiver needs; avoid forwarding personal data to systems that do not require it.
- Restrict who can create and edit webhooks in the admin.
- Rotate secrets when staff leave.
- Delete webhooks you no longer use.
Testing a webhook setup before you rely on it
Before you trust a webhook with real orders, run a short test plan in a staging copy of your store. Place a test order and confirm that the delivery arrives, that the signature verifies and that the payload contains the fields you expect. Change the order status and check that the update event arrives once, not three times. Take your receiving endpoint offline for ten minutes, create two orders and confirm that your catch-up check finds them afterwards. Disable the scheduler on purpose to see how long deliveries are delayed. Record the results in your runbook. These small tests take an afternoon and show you exactly how the system behaves when something goes wrong, which is when you will need that knowledge.
A worked example
A WooCommerce store with 40 orders a day sends “order created” and “order updated” to its fulfilment system. A hosting change disabled the background scheduler, and webhooks stopped for two days before anybody noticed. Orders worth about $4,800 were delayed by one to two days, leading to roughly 12 complaints and four refunds of $60. Adding a scheduled check that compares recent orders with fulfilled ones, plus an alert if no webhook has arrived in two hours during the day, would cost an afternoon of work and would have flagged the issue in two hours. The numbers are illustrative; the lesson is the value of an independent check.
When to get help
Simple webhooks to an automation platform are within reach of most store owners. Once money, stock or customer messages depend on them, a documented build with signature checks, queues, retries and monitoring is worth having. See our ecommerce workflow automation and automation and data integrations services.
Sources and further reading
Figures and rules in this guide come from the primary pages below. Platform limits and prices change, so open the page before you build on a number.
- WooCommerce Docs: webhooks, creating and managing webhooks
- WooCommerce REST API documentation, API resources and webhook objects
- WordPress Developer Resources: WP-Cron, how scheduled tasks run in WordPress