WooCommerce
Put a WooCommerce store in a flow: find, create and update orders, products and stock, customers and coupons with the action node, and fire a flow when any of them changes with the trigger. The action node can also be handed to an AI Node as an AI toolkit.
Connect a store
Type the store's address and click Connect WooCommerce — in the node's credential picker or in Settings → Credentials. A window opens on your own WordPress: log in as an administrator and approve a Read/Write key for HostWebhook. The key comes back on its own and the credential is saved. One credential is one store.
Already have a key? Choose Paste API keys instead and fill in the store URL, the consumer key (ck_…) and the consumer secret (cs_…). Either way, the key is tested against the store before it is saved.
- HTTPS only. WooCommerce hands out keys over https, and the node only talks to the store over https.
- Permalinks must not be “Plain” (WordPress → Settings → Permalinks). With plain links the REST API has no address, and connecting says so.
- WordPress in a subfolder works: connect
https://example.com/shop. - Some hosts strip the
Authorizationheader. That is detected when the key is saved, and the key is then sent the other way WooCommerce accepts — nothing to set.
Store moved, or the key stopped working? Open the credential in Settings → Credentials and use Reconnect under Store connection: change the address if it moved, approve the key again in WordPress, and this same credential gets the new address and key. Nodes keep pointing at it — don't delete it and create another, or every node that used it is left without a store. Triggers keep their webhooks when it is the same store at a new address; after switching to a different store, pause and activate them again.
The action node
Sixteen operations, in four groups: the ones worth automating in a store.
| Group | Operation | What it does | Store |
|---|---|---|---|
| Orders | Find orders | Search by customer, status, product or date — newest first. | reads |
| Orders | Get order | One order whole: items, totals, payment, customer, addresses and status. | reads |
| Orders | Create order | An order with its items. It charges nobody: mark it paid only if the money already came in. | writes |
| Orders | Update order status | Move an order to another status. WooCommerce sends the emails your store has on for it. | writes |
| Orders | Add order note | A note on the order — private, or emailed to the customer. | writes |
| Orders | Cancel order | Cancels it; WooCommerce puts the stock back. | irreversible |
| Orders | Refund order | Part or all of it. Only recorded, unless it goes through the payment gateway. | irreversible |
| Products & stock | Find products | Search by name, SKU, status or stock — with variations if you want. | reads |
| Products & stock | Get product | Price, stock, status, categories and images — and its variations. | reads |
| Products & stock | Create product | A simple product. It starts as a draft unless you say otherwise. | writes |
| Products & stock | Update product | Price, stock, status or text of a product or one of its variations. | writes |
| Customers | Find customers | Registered customers by name or email. | reads |
| Customers | Get customer | Name, email, addresses, orders placed and total spent. | reads |
| Customers | Add or update customer | Looked up by email: updated if found, created if not. | writes |
| Coupons | Create coupon | A percentage or fixed discount code, with limits if you want. | writes |
| Coupons | Find coupons | By code, with their discount, uses and expiry. | reads |
Every field takes a template: {{payload.id}} for the order that fired the flow, {{payload.body.billing.email}} from the WooCommerce trigger. Numbers too — stock and quantities are checked when the node runs.
Orders
Create order takes the items as JSON — the product, and the variation when there is one:
[
{ "product_id": 93, "quantity": 1 },
{ "product_id": 22, "variation_id": 23, "quantity": "{{payload.qty}}" }
]The billing and shipping addresses are written one field per line, or as JSON: first_name, last_name, address_1, city, postcode, country and, for billing, email and phone.
Update order status moves an order to pending, processing, on hold, completed or failed. Cancelling and refunding are their own operations on purpose: neither can be undone, and in toolkit mode both start blocked — a status change must not be a way around that.
Products & stock
Update product only changes what you fill in. Give it a Variation ID to change one size or colour instead of the whole product. Setting the sale price to none removes the sale.
Categories are picked, not typed. Finding products of a category, or creating a product in several, lists the store's categories with their path (Clothing / T-shirts) and how many products each has. To take them from the flow, choose Type IDs or a template under the list.
Customers
Add or update customer looks the email up first — in every role, not only customers — and updates that account, or creates a new customer when there is none. Guests who checked out without an account are not customers in WooCommerce: find them through their orders.
AI toolkit mode
Once the store is connected, the node asks for a Mode. AI toolkit turns it into sixteen tools that an AI Node — or an MCP client, through one of your MCP servers — calls by name.
| Tool | Arguments |
|---|---|
| search_woocommerce_orders | search? · status? · customer_id? · product_id? · after? · before? · per_page? · page? |
| get_woocommerce_order | order_id |
| create_woocommerce_order | line_items · customer_id? · billing? · shipping? · status? · set_paid? · payment_method? · payment_method_title? · customer_note? |
| update_woocommerce_order_status | order_id · status |
| add_woocommerce_order_note | order_id · note |
| cancel_woocommerce_order | order_id |
| refund_woocommerce_order | order_id · amount · reason? · through_gateway? |
| search_woocommerce_products | search? · sku? · status? · stock_status? · category? · include_variations? · per_page? · page? |
| get_woocommerce_product | product_id · include_variations? |
| create_woocommerce_product | name · regular_price? · sale_price? · sku? · stock_quantity? · description? · short_description? · categories? · image_urls? |
| update_woocommerce_product | product_id · variation_id? · regular_price? · sale_price? · stock_quantity? · stock_status? · status? · name? · description? |
| search_woocommerce_customers | search? · email? · per_page? · page? |
| get_woocommerce_customer | customer_id |
| upsert_woocommerce_customer | email · first_name? · last_name? · phone? · billing? · shipping? |
| create_woocommerce_coupon | code · discount_type · amount · date_expires? · usage_limit? · usage_limit_per_user? · minimum_amount? · email_restrictions? · individual_use? · free_shipping? · description? |
| search_woocommerce_coupons | search? · code? · per_page? · page? |
What you control
- Cancel and refund start blocked. Neither can be undone. Unblock them in the node's tool list if the agent should have them.
- Email order notes to the customer. Off by default: a note the model adds stays private, for the store team. The model has no argument to change it.
- New products. Created as a draft by default, so nothing reaches shoppers until someone publishes it. You can pick pending review, private or published instead; the model can't.
- Refunds through the gateway only when the model asks for it explicitly with
through_gateway: true. - Characters per call sent to the model. 20,000 by default. Lists that don't fit are cut whole items at a time, with a
notesfield saying how many were left out.
Testing a tool
operation in their payload that names another tool is refused.{ "operation": "search_woocommerce_orders", "status": "processing" }The trigger
Pick a store credential, then pick what fires it:
| Resource | Events |
|---|---|
| Orders | created · updated · deleted · restored |
| Products | created · updated · deleted · restored |
| Customers | created · updated · deleted |
| Coupons | created · updated · deleted · restored |
Activating creates one webhook per event in your store — you'll see them in WooCommerce → Settings → Advanced → Webhooks, named after the trigger. Each delivery is signed with a secret that belongs to this trigger, and HostWebhook checks the signature before anything runs. Deactivating deletes the webhooks.
- Order updated also arrives right after many new orders: checkout creates the order and then moves it to its first status. Listening to both means both arrive.
- Deleted covers moving to the trash too, and the event only carries the ID — the record is gone.
- Customers are registered accounts. A guest checkout fires an order event, not a customer one.
If the store disables a webhook
WooCommerce disables a webhook after more than five failed deliveries in a row, and only tells the store admin. HostWebhook checks every night: a webhook the store disabled is turned back on, one deleted in the store is created again, and the trigger's log says so — events in between were lost. A webhook you paused in WooCommerce stays paused.
What the trigger sends downstream
The delivery details on top, and the record whole under body — exactly what WooCommerce's REST API returns for it:
{
"id": "order.created:1042:9d7f…",
"topic": "order.created",
"resource": "order",
"event": "created",
"store": "https://your-store.com",
"webhookId": "31",
"deliveryId": "9d7f…",
"resourceId": "1042",
"occurredAt": "2026-09-28T15:14:02Z",
"body": { "id": 1042, "status": "processing", "total": "47.00", "billing": { "…": "…" }, "line_items": [ "…" ] }
}Reach anything with {{payload.body.whatever}} — {{payload.body.billing.email}}, {{payload.body.line_items}}. A deletion's body is just { "id": 1042 }.
Trying it out
The trigger's Test push reads the latest orders, products, customers and coupons of your store and shows them exactly as a delivery will arrive — WooCommerce builds its webhooks from the same API — without running the flow. Deletions can't be read back, so they show an example. To see a real delivery, activate the trigger and place a test order.
Good to know
Use the store's final address
The node never follows a redirect with your key attached. If the store answers from another address — http to https, with or without www — the call fails and says where it was sent: reconnect with that address.
Busy or rate limited
WooCommerce itself has no rate limit on this API, but many hosts do. When the store answers that it is busy or down, the node waits and retries before giving up.