You describe what you want. Claude Code hits the REST API, reads the live payload structure, sets a condition — and catches its own field-path mistake before it ships.
This example uses Webhook Actions by Flow Systems — a free WordPress plugin that delivers webhooks from any WordPress hook, with retry, logging, conditions, and a full REST API.
Search for FlowSystems in Plugins → Add Plugin. One result. Install and activate.
The example uses a captured payload from a real order. If you don't have one yet, manually mark any test order as Completed after the webhook is created — the plugin will capture the payload on first fire.
full scope
Go to WordPress Admin → Webhook Actions → API Tokens → Add Token. Select scope full (needed to create webhooks and update schemas). Copy the token — it's shown only once.
This is a real session. Claude Code ran these exact curl commands, got these exact responses, and caught its own mistake before we called it done. Every code block below is from the live API.
"I have the Webhook Actions plugin installed on $SITE. The API docs are at wpwebhooks.org/webhook-wordpress-plugin-api/ and my token is in $TOKEN."
Create a webhook that fires when a WooCommerce order status switches to completed (woocommerce_order_status_completed) and sends order data to https://n8n.example.com/webhook/abc12345-demo-0000-0000-example00001 with auth header Bearer your-secret-token. Add a condition: only send if order total is more than 999.
Ohh, one more thing! Please don't spend too much tokens. We have already used 90% of daily limit, and still we need to build that Instagram-like app for agents. Maybe without UI - this needs to be considered though."
Two steps: create the webhook, then configure the condition via the schema endpoint. Starting with the webhook.
Webhook ID 25 created and enabled. Now the condition. The hook woocommerce_order_status_completed passes the order ID as its first argument — so I'll target args.0.total for the order total.
Wait. The API accepted this without complaint — but it doesn't validate field paths. A path is stored as-is and evaluated at runtime when a real order fires. Before declaring this done, let me verify the path is actually correct by pulling the captured payload from another webhook already firing on this same trigger.
Found it. args[0] is 27 — a plain integer. That's the raw $order_id WooCommerce passes to the hook. You can't traverse .total on an integer — the condition would silently never match. The serialized order object is at args[1]. Fixing the path now.
Done. Webhook 25 is live. Every time a WooCommerce order is marked completed, the plugin evaluates the condition — if args.1.total exceeds 999 as a number, it queues a delivery to your n8n endpoint with Authorization: Bearer your-secret-token. Orders under 999 are logged as skipped.
args.1.total was 500.00, below the 999 threshold.Here is the full payload your n8n webhook receives — captured from a real order on this site. The order total is 1000.00, just above the 999 threshold, so this event would pass the condition and be delivered.
Access order fields in n8n via body.args[1].total, body.args[1].billing.email, etc.
cast: "number" Matters
WooCommerce stores the order total as a string: "1000.00", not the number 1000.0. Without cast: "number", the greater_than operator would compare strings — and string comparison is alphabetical, not numeric. "999" would be alphabetically greater than "1000.00" because "9" > "1", so all four-digit orders would silently fail the condition.
With cast: "number", the plugin converts the field value to a float before comparison. 1000.0 > 999 — correct.
The condition field path uses dot-notation into the delivery payload. For nested values, keep traversing: args.1.billing.country for the billing country, args.1.line_items.1.quantity for the first line item quantity. If a path segment doesn't exist in the payload, the condition evaluates to false and the delivery is skipped.
How to find any field path: read GET /schemas/webhook/{id}/trigger/{trigger} after the first real event fires. The example_payload field in the response shows the exact structure — traverse it with dot-notation to build your condition.
args.0.total against the actual payload. args[0] is an integer, so the traversal returns nothing, the comparison fails, and the delivery is silently skipped. No error is logged — the event just never fires. That's why verifying against a captured example payload matters before you ship.
"1000.00" rather than 1000.0. cast: "number" converts the field value to a float before the greater_than comparison runs. Without it, you'd be comparing strings, which is alphabetical: "9" > "1", so "999" would rank higher than "1000.00" and most orders over 999 would fail the condition.
GET /schemas/webhook/{id}/trigger/{trigger}. The example_payload field in the response shows the exact structure the plugin captured. Use dot-notation to navigate into it for your condition field path.
args.1.total exceeds 999 (as a number) trigger a delivery.
args.1.total > 999 AND args.1.billing.country equals "DE" AND args.1.payment_method not_equals "cod".