{"id":280953,"date":"2026-02-16T21:00:04","date_gmt":"2026-02-16T21:00:04","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/webhook-actions\/"},"modified":"2026-07-07T12:02:41","modified_gmt":"2026-07-07T12:02:41","slug":"flowsystems-webhook-actions","status":"publish","type":"plugin","link":"https:\/\/emoji.wordpress.org\/plugins\/flowsystems-webhook-actions\/","author":23439561,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.1.1","stable_tag":"2.1.1","tested":"7.0","requires":"6.0","requires_php":"8.0","requires_plugins":null,"header_name":"Webhook Actions - build automations and integrations with AI help","header_author":"Mateusz Skorupa","header_description":"Trigger HTTP webhooks from WordPress actions (do_action). Easily connect WordPress with n8n, Zapier, Make, or custom workflows.","assets_banners_color":"34403f","last_updated":"2026-07-07 12:02:41","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wpwebhooks.org\/wordpress-webhook-plugin","header_author_uri":"https:\/\/flowsystems.pl","rating":5,"author_block_rating":0,"active_installs":0,"downloads":1670,"num_ratings":2,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"mateuszflowsystems","date":"2026-02-16 21:00:27"},"1.0.1":{"tag":"1.0.1","author":"mateuszflowsystems","date":"2026-02-18 22:35:51"},"1.1.0":{"tag":"1.1.0","author":"mateuszflowsystems","date":"2026-02-28 21:08:40"},"1.1.1":{"tag":"1.1.1","author":"mateuszflowsystems","date":"2026-03-01 12:48:16"},"1.10.0":{"tag":"1.10.0","author":"mateuszflowsystems","date":"2026-05-03 21:47:57"},"1.11.0":{"tag":"1.11.0","author":"mateuszflowsystems","date":"2026-05-06 16:15:26"},"1.12.0":{"tag":"1.12.0","author":"mateuszflowsystems","date":"2026-05-12 20:51:43"},"1.12.1":{"tag":"1.12.1","author":"mateuszflowsystems","date":"2026-05-12 21:07:31"},"1.12.2":{"tag":"1.12.2","author":"mateuszflowsystems","date":"2026-05-14 14:50:23"},"1.13.0":{"tag":"1.13.0","author":"mateuszflowsystems","date":"2026-05-18 16:12:11"},"1.13.1":{"tag":"1.13.1","author":"mateuszflowsystems","date":"2026-05-21 13:58:15"},"1.14.0":{"tag":"1.14.0","author":"mateuszflowsystems","date":"2026-06-03 21:50:04"},"1.14.1":{"tag":"1.14.1","author":"mateuszflowsystems","date":"2026-06-05 21:31:16"},"1.15.0":{"tag":"1.15.0","author":"mateuszflowsystems","date":"2026-06-07 21:59:00"},"1.16.0":{"tag":"1.16.0","author":"mateuszflowsystems","date":"2026-06-22 21:24:22"},"1.2.0":{"tag":"1.2.0","author":"mateuszflowsystems","date":"2026-03-07 20:42:42"},"1.2.1":{"tag":"1.2.1","author":"mateuszflowsystems","date":"2026-03-07 21:21:55"},"1.3.0":{"tag":"1.3.0","author":"mateuszflowsystems","date":"2026-03-15 21:22:43"},"1.3.1":{"tag":"1.3.1","author":"mateuszflowsystems","date":"2026-03-15 21:56:44"},"1.3.2":{"tag":"1.3.2","author":"mateuszflowsystems","date":"2026-03-15 22:36:07"},"1.4.0":{"tag":"1.4.0","author":"mateuszflowsystems","date":"2026-03-22 21:17:47"},"1.5.0":{"tag":"1.5.0","author":"mateuszflowsystems","date":"2026-03-23 16:43:47"},"1.6.0":{"tag":"1.6.0","author":"mateuszflowsystems","date":"2026-03-28 22:56:32"},"1.6.1":{"tag":"1.6.1","author":"mateuszflowsystems","date":"2026-03-28 23:00:04"},"1.6.2":{"tag":"1.6.2","author":"mateuszflowsystems","date":"2026-04-05 13:22:48"},"1.7.0":{"tag":"1.7.0","author":"mateuszflowsystems","date":"2026-04-27 17:44:53"},"1.8.0":{"tag":"1.8.0","author":"mateuszflowsystems","date":"2026-04-27 22:49:00"},"1.9.0":{"tag":"1.9.0","author":"mateuszflowsystems","date":"2026-05-03 15:18:40"},"2.0.0":{"tag":"2.0.0","author":"mateuszflowsystems","date":"2026-07-06 13:01:36"},"2.1.0":{"tag":"2.1.0","author":"mateuszflowsystems","date":"2026-07-06 22:48:10"},"2.1.1":{"tag":"2.1.1","author":"mateuszflowsystems","date":"2026-07-07 12:02:41"}},"upgrade_notice":[],"ratings":{"1":0,"2":0,"3":0,"4":0,"5":2},"assets_icons":{"icon-128x128.gif":{"filename":"icon-128x128.gif","revision":3598331,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.gif":{"filename":"icon-256x256.gif","revision":3598331,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3598331,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3598331,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3599007,"resolution":false,"location":"assets","locale":"","contents":"{\"landingPage\":\"\\\/wp-admin\\\/admin.php?page=fswa-webhook-actions#\\\/webhooks\",\"preferredVersions\":{\"php\":\"8.2\",\"wp\":\"latest\"},\"features\":{\"networking\":true},\"steps\":[{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"flowsystems-webhook-actions\"},\"options\":{\"activate\":true}},{\"step\":\"activatePlugin\",\"pluginPath\":\"flowsystems-webhook-actions\\\/flowsystems-webhook-actions.php\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"woocommerce\"}},{\"step\":\"activatePlugin\",\"pluginPath\":\"woocommerce\\\/woocommerce.php\"},{\"step\":\"login\",\"username\":\"admin\",\"password\":\"password\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Seed: a SYNCHRONOUS webhook on the `profile_update` trigger, delivering to\\n * httpbin, with a field mapping that strips credentials from the payload.\\n *\\n * Runs once (guarded by empty(getAll())). The profile_update payload is the RAW\\n * hook args, so the password \\\/ activation key live at:\\n *   args.1.data.* = old WP_User object   (3rd-arg userdata is args.2.*)\\n *   args.2.*      = new userdata array\\n * We intentionally do NOT seed example_payload \\u2014 the first real dispatch\\n * auto-captures the true payload shape for the admin field picker, and\\n * SchemaRepository::upsert() preserves this field_mapping through that capture.\\n *\\\/\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\n\\nif ( ! class_exists( '\\\\FlowSystems\\\\WebhookActions\\\\Repositories\\\\WebhookRepository' ) ) {\\n    return;\\n}\\n\\n$repo = new \\\\FlowSystems\\\\WebhookActions\\\\Repositories\\\\WebhookRepository();\\n\\n\\\/\\\/ Idempotent: only seed on a fresh install.\\nif ( ! empty( $repo->getAll() ) ) {\\n    return;\\n}\\n\\n$webhookId = $repo->create([\\n    'name'           => 'Demo \\u2014 Profile Update \\u2192 httpbin',\\n    'endpoint_url'   => 'https:\\\/\\\/httpbin.org\\\/post',\\n    'http_method'    => 'POST',\\n    'is_synchronous' => 1,\\n    'is_enabled'     => 1,\\n    'triggers'       => ['profile_update'],\\n]);\\n\\nif ( $webhookId && class_exists( '\\\\FlowSystems\\\\WebhookActions\\\\Repositories\\\\SchemaRepository' ) ) {\\n    $schemaRepo = new \\\\FlowSystems\\\\WebhookActions\\\\Repositories\\\\SchemaRepository();\\n    $schemaRepo->upsert( (int) $webhookId, 'profile_update', [\\n        'field_mapping' => [\\n            'mappings'        => [],\\n            'excluded'        => [\\n                'args.1.data.user_pass',\\n                'args.1.data.user_activation_key',\\n                'args.2.user_pass',\\n                'args.2.user_activation_key',\\n            ],\\n            'includeUnmapped' => true,\\n        ],\\n    ] );\\n}\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Seed: create an example subscriber and update their profile, which fires the\\n * `profile_update` trigger and produces one real (synchronous) delivery + log,\\n * so the Logs view is populated on landing.\\n *\\n * This MUST be a separate runPHP step (= separate request) from the webhook seed\\n * above: the trigger listener is attached on `init` from the stored triggers, so\\n * the webhook + trigger row must already exist in the DB before this request runs\\n * wp_update_user(). wp_insert_user() does NOT fire profile_update; wp_update_user()\\n * on an existing user does.\\n *\\\/\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\n\\n$uid = username_exists( 'jane.customer' );\\n\\nif ( ! $uid ) {\\n    $uid = wp_insert_user([\\n        'user_login'  => 'jane.customer',\\n        'user_pass'   => wp_generate_password(),\\n        'user_email'  => 'jane.customer@example.com',\\n        'first_name'  => 'Jane',\\n        'last_name'   => 'Customer',\\n        'role'        => 'subscriber',\\n        'description' => 'Example customer account for the webhook demo.',\\n    ]);\\n}\\n\\nif ( $uid && ! is_wp_error( $uid ) ) {\\n    wp_update_user([\\n        'ID'          => $uid,\\n        'first_name'  => 'Jane',\\n        'last_name'   => 'Customer (updated)',\\n        'description' => 'Profile updated by the live preview to fire a synchronous webhook delivery.',\\n    ]);\\n}\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Seed: a WooCommerce \\\"order fulfilment pipeline\\\" that showcases CONDITIONS +\\n * CHAINS together.\\n *\\n *   [woocommerce_order_status_completed]\\n *        \\u2502  condition: order total > 100  (only high-value orders pass)\\n *        \\u25bc\\n *   Webhook A  \\\"Order Completed \\u2192 CRM\\\"   \\u2500\\u2500chain\\u2500\\u2500\\u25b6  Webhook B  \\\"High-Value Order \\u2192 Fulfilment\\\"\\n *   (synchronous, POST httpbin)                      (synchronous, POST httpbin)\\n *\\n * Webhook A maps the raw WC_Order into a tidy CRM payload and only fires when the\\n * order total exceeds 100. On a successful 2xx delivery the chain forwards to\\n * Webhook B, which receives A's sent payload + upstream response and maps a\\n * compact fulfilment notification.\\n *\\n * The actual orders are placed in the next step (40-fire-woo-orders.php) \\u2014 they\\n * MUST be a later runPHP request so the webhook + trigger rows already exist in\\n * the DB when WooCommerce's order-status hook fires (listeners attach on `init`).\\n *\\n * Idempotent: guarded by the chain name so long-lived previews don't duplicate.\\n *\\\/\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\n\\nuse FlowSystems\\\\WebhookActions\\\\Repositories\\\\WebhookRepository;\\nuse FlowSystems\\\\WebhookActions\\\\Repositories\\\\SchemaRepository;\\nuse FlowSystems\\\\WebhookActions\\\\Repositories\\\\ChainRepository;\\nuse FlowSystems\\\\WebhookActions\\\\Repositories\\\\ChainLinkRepository;\\n\\nif ( ! class_exists( ChainRepository::class ) || ! class_exists( WebhookRepository::class ) ) {\\n    return;\\n}\\n\\n\\\/\\\/ WooCommerce activation queues a redirect to its setup wizard on the next\\n\\\/\\\/ admin load \\u2014 drop it so the preview lands straight on the Webhooks screen.\\ndelete_transient( '_wc_activation_redirect' );\\n\\n$chainRepo = new ChainRepository();\\n\\n\\\/\\\/ Idempotent: only seed on a fresh install.\\nif ( $chainRepo->findByName( 'Order Fulfilment Pipeline' ) ) {\\n    return;\\n}\\n\\n$webhookRepo = new WebhookRepository();\\n$schemaRepo  = new SchemaRepository();\\n$linkRepo    = new ChainLinkRepository();\\n\\n\\\/\\\/ --- Webhook A: order completed \\u2192 CRM (conditional, mapped) -----------------\\n$sourceId = $webhookRepo->create([\\n    'name'           => 'Order Completed \\u2192 CRM',\\n    'endpoint_url'   => 'https:\\\/\\\/httpbin.org\\\/post',\\n    'http_method'    => 'POST',\\n    'is_synchronous' => 1,\\n    'is_enabled'     => 1,\\n    'triggers'       => ['woocommerce_order_status_completed'],\\n]);\\n\\nif ( ! $sourceId ) {\\n    return;\\n}\\n\\n\\\/\\\/ WooCommerce passes ($order_id, $order); Dispatcher::normalizeValue() expands the\\n\\\/\\\/ WC_Order via get_data(), so the order lives at args.1 with .total \\\/ .billing.* etc.\\n\\\/\\\/ We leave example_payload empty \\u2014 the first real order auto-captures the true\\n\\\/\\\/ shape and SchemaRepository::upsert() preserves this mapping through that capture.\\n$schemaRepo->upsert( (int) $sourceId, 'woocommerce_order_status_completed', [\\n    'conditions' => [\\n        'enabled' => true,\\n        'type'    => 'and',\\n        'rules'   => [\\n            [\\n                'field'    => 'args.1.total',\\n                'operator' => 'greater_than',\\n                'value'    => '100',\\n                'cast'     => 'number',\\n            ],\\n        ],\\n    ],\\n    'conditions_evaluate_on' => 'original',\\n    'field_mapping' => [\\n        'mappings' => [\\n            [ 'source' => 'args.1.id',                 'target' => 'order_id' ],\\n            [ 'source' => 'args.1.status',             'target' => 'status' ],\\n            [ 'source' => 'args.1.total',              'target' => 'order_total' ],\\n            [ 'source' => 'args.1.currency',           'target' => 'currency' ],\\n            [ 'source' => 'args.1.billing.email',      'target' => 'customer_email' ],\\n            [ 'source' => 'args.1.billing.first_name', 'target' => 'customer_first_name' ],\\n            [ 'source' => 'args.1.billing.last_name',  'target' => 'customer_last_name' ],\\n        ],\\n        'excluded'        => [],\\n        'includeUnmapped' => false,\\n    ],\\n] );\\n\\n\\\/\\\/ --- Webhook B: chain target \\u2192 fulfilment notification ----------------------\\n$targetId = $webhookRepo->create([\\n    'name'           => 'High-Value Order \\u2192 Fulfilment',\\n    'endpoint_url'   => 'https:\\\/\\\/httpbin.org\\\/post',\\n    'http_method'    => 'POST',\\n    'is_synchronous' => 1,\\n    'is_enabled'     => 1,\\n    \\\/\\\/ No WP trigger \\u2014 fired only via the chain link (synthetic trigger added below).\\n    'triggers'       => [],\\n]);\\n\\nif ( ! $targetId ) {\\n    return;\\n}\\n\\n\\\/\\\/ --- Wire the chain: A \\u2500\\u2500\\u25b6 B ------------------------------------------------\\n$chainId = $chainRepo->create([\\n    'name'        => 'Order Fulfilment Pipeline',\\n    'description' => 'When a high-value order is sent to the CRM, notify fulfilment with the order + CRM response.',\\n]);\\n\\nif ( ! $chainId ) {\\n    return;\\n}\\n\\n\\\/\\\/ create() also inserts the synthetic `fswa_chain_link:{linkId}` trigger row for B.\\n$linkId = $linkRepo->create( (int) $chainId, (int) $sourceId, (int) $targetId );\\n\\nif ( $linkId ) {\\n    \\\/\\\/ The chain hands B the full post-dispatch context as args[0]: A's sent\\n    \\\/\\\/ (mapped) payload, the upstream response, and chain metadata. Map a compact\\n    \\\/\\\/ fulfilment notification from it.\\n    $schemaRepo->upsert( (int) $targetId, 'fswa_chain_link:' . $linkId, [\\n        'field_mapping' => [\\n            'mappings' => [\\n                [ 'source' => 'args.0.payload.order_id',       'target' => 'order_id' ],\\n                [ 'source' => 'args.0.payload.order_total',    'target' => 'order_total' ],\\n                [ 'source' => 'args.0.payload.customer_email', 'target' => 'customer_email' ],\\n                [ 'source' => 'args.0.source_webhook.name',    'target' => 'triggered_by' ],\\n                [ 'source' => 'args.0.response.code',          'target' => 'crm_response_code' ],\\n                [ 'source' => 'args.0.chain.depth',            'target' => 'chain_depth' ],\\n            ],\\n            'excluded'        => [],\\n            'includeUnmapped' => false,\\n        ],\\n    ] );\\n}\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Seed: place TWO real WooCommerce orders and mark them completed, firing\\n * `woocommerce_order_status_completed` so the fulfilment pipeline (seed 30) runs\\n * end to end and the Logs view is populated on landing.\\n *\\n *   Order #1  \\\"Premium Widget\\\"  $120.00  \\u2192 total > 100  \\u2192 condition PASSES\\n *             \\u2192 Webhook A delivers (success) \\u2192 chain \\u2192 Webhook B delivers (success)\\n *   Order #2  \\\"Sticker Pack\\\"     $25.00  \\u2192 total \\u2264 100  \\u2192 condition FAILS\\n *             \\u2192 Webhook A logged as SKIPPED, no delivery, no chain\\n *\\n * This MUST be a separate runPHP step (= separate request) from seed 30: the\\n * trigger listener for `woocommerce_order_status_completed` is attached on `init`\\n * from the stored webhook triggers, which only exist after seed 30 has run.\\n *\\n * Idempotent: guarded by an option flag so long-lived previews don't re-order.\\n *\\\/\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\n\\nif ( ! function_exists( 'wc_create_order' ) || ! class_exists( 'WC_Product_Simple' ) ) {\\n    return; \\\/\\\/ WooCommerce not active \\u2014 nothing to do.\\n}\\n\\nif ( get_option( 'fswa_demo_woo_orders_seeded' ) ) {\\n    return;\\n}\\n\\n\\\/**\\n * Create a published simple product and place a completed order for it.\\n *\\\/\\n$place_completed_order = static function ( string $name, string $price, array $billing ): void {\\n    $product = new \\\\WC_Product_Simple();\\n    $product->set_name( $name );\\n    $product->set_regular_price( $price );\\n    $product->set_price( $price );\\n    $product->set_status( 'publish' );\\n    $product->set_catalog_visibility( 'visible' );\\n    $productId = $product->save();\\n\\n    $order = wc_create_order();\\n    $order->add_product( wc_get_product( $productId ), 1 );\\n    $order->set_address( $billing, 'billing' );\\n    $order->calculate_totals();\\n    $order->save();\\n\\n    \\\/\\\/ Transition to \\\"completed\\\" \\u2014 fires woocommerce_order_status_completed($id, $order).\\n    $order->update_status( 'completed', 'Live preview demo order.', true );\\n};\\n\\n\\\/\\\/ Order #1 \\u2014 high value, passes the > 100 condition (fires A \\u2192 chain \\u2192 B).\\n$place_completed_order( 'Premium Widget', '120.00', [\\n    'first_name' => 'Jane',\\n    'last_name'  => 'Customer',\\n    'email'      => 'jane.customer@example.com',\\n    'country'    => 'US',\\n    'city'       => 'Austin',\\n    'state'      => 'TX',\\n] );\\n\\n\\\/\\\/ Order #2 \\u2014 low value, fails the condition (Webhook A is logged as skipped).\\n$place_completed_order( 'Sticker Pack', '25.00', [\\n    'first_name' => 'Sam',\\n    'last_name'  => 'Shopper',\\n    'email'      => 'sam.shopper@example.com',\\n    'country'    => 'US',\\n    'city'       => 'Denver',\\n    'state'      => 'CO',\\n] );\\n\\nupdate_option( 'fswa_demo_woo_orders_seeded', 1, false );\"}]}"}},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1","1.1.0","1.1.1","1.10.0","1.11.0","1.12.0","1.12.1","1.12.2","1.13.0","1.13.1","1.14.0","1.14.1","1.15.0","1.16.0","1.2.0","1.2.1","1.3.0","1.3.1","1.3.2","1.4.0","1.5.0","1.6.0","1.6.1","1.6.2","1.7.0","1.8.0","1.9.0","2.0.0","2.1.0","2.1.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3597783,"resolution":"1","location":"assets","locale":"","width":1641,"height":880},"screenshot-10.png":{"filename":"screenshot-10.png","revision":3597783,"resolution":"10","location":"assets","locale":"","width":794,"height":785},"screenshot-11.png":{"filename":"screenshot-11.png","revision":3597783,"resolution":"11","location":"assets","locale":"","width":822,"height":925},"screenshot-12.png":{"filename":"screenshot-12.png","revision":3597783,"resolution":"12","location":"assets","locale":"","width":809,"height":878},"screenshot-13.png":{"filename":"screenshot-13.png","revision":3597783,"resolution":"13","location":"assets","locale":"","width":1638,"height":865},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3597783,"resolution":"2","location":"assets","locale":"","width":1641,"height":798},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3597783,"resolution":"3","location":"assets","locale":"","width":841,"height":902},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3597783,"resolution":"4","location":"assets","locale":"","width":824,"height":900},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3597783,"resolution":"5","location":"assets","locale":"","width":822,"height":888},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3597783,"resolution":"6","location":"assets","locale":"","width":713,"height":874},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3597783,"resolution":"7","location":"assets","locale":"","width":1635,"height":840},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3597783,"resolution":"8","location":"assets","locale":"","width":1635,"height":840},"screenshot-9.png":{"filename":"screenshot-9.png","revision":3597783,"resolution":"9","location":"assets","locale":"","width":1650,"height":765}},"screenshots":{"1":"Build with AI \u2014 describe the integration in chat; the agent plans, builds, and tests it step by step, with progress in the sidebar and one-click enable when the build completes","2":"Webhooks list view","3":"Webhook configuration screen","4":"Selecting WordPress action triggers","5":"Payload mapping configuration","6":"Webhook delivery logs with replay and retry controls","7":"Queue status overview","8":"Settings configuration screen","9":"REST API Tokens configuration screen","10":"Conditional webhook dispatch \u2014 conditions editor","11":"Test webhook drawer \u2014 send a test delivery and inspect request details inline","12":"Webhook Chains \u2014 pick an existing chain or create a new one, then select which upstream webhooks should fire this one on their 2xx response","13":"Credentials Vault \u2014 store reusable authentication secrets (Bearer, Basic, API key, custom) encrypted at rest and reference them from webhooks instead of pasting raw Authorization headers"}},"plugin_section":[],"plugin_tags":[2353,569,597,243637,34953],"plugin_category":[45],"plugin_contributors":[255989],"plugin_business_model":[],"class_list":["post-280953","plugin","type-plugin","status-publish","hentry","plugin_tags-ai","plugin_tags-automation","plugin_tags-integration","plugin_tags-n8n","plugin_tags-webhooks","plugin_category-ecommerce","plugin_contributors-mateuszflowsystems","plugin_committers-mateuszflowsystems"],"banners":{"banner":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/banner-772x250.png?rev=3598331","banner_2x":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/banner-1544x500.png?rev=3598331","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/icon-128x128.gif?rev=3598331","icon_2x":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/icon-256x256.gif?rev=3598331","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-1.png?rev=3597783","caption":"Build with AI \u2014 describe the integration in chat; the agent plans, builds, and tests it step by step, with progress in the sidebar and one-click enable when the build completes"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-2.png?rev=3597783","caption":"Webhooks list view"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-3.png?rev=3597783","caption":"Webhook configuration screen"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-4.png?rev=3597783","caption":"Selecting WordPress action triggers"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-5.png?rev=3597783","caption":"Payload mapping configuration"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-6.png?rev=3597783","caption":"Webhook delivery logs with replay and retry controls"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-7.png?rev=3597783","caption":"Queue status overview"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-8.png?rev=3597783","caption":"Settings configuration screen"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-9.png?rev=3597783","caption":"REST API Tokens configuration screen"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-10.png?rev=3597783","caption":"Conditional webhook dispatch \u2014 conditions editor"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-11.png?rev=3597783","caption":"Test webhook drawer \u2014 send a test delivery and inspect request details inline"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-12.png?rev=3597783","caption":"Webhook Chains \u2014 pick an existing chain or create a new one, then select which upstream webhooks should fire this one on their 2xx response"},{"src":"https:\/\/ps.w.org\/flowsystems-webhook-actions\/assets\/screenshot-13.png?rev=3597783","caption":"Credentials Vault \u2014 store reusable authentication secrets (Bearer, Basic, API key, custom) encrypted at rest and reference them from webhooks instead of pasting raw Authorization headers"}],"raw_content":"<!--section=description-->\n<p><strong>Describe the integration you want. The AI builds it.<\/strong> Webhook Actions ships with <strong>Build with AI<\/strong> \u2014 an in-admin agent that turns a plain-language request like <em>\"When a Contact Form 7 form is submitted, send it as JSON to my n8n webhook\"<\/em> into a working, tested automation. The agent proposes a plan you can review and edit, then creates the webhook, captures a real example payload from your site, maps the fields, sets dispatch conditions, probes your endpoint, and sends a test delivery. Nothing goes live without your confirmation \u2014 new webhooks are always created disabled, and you can undo the last change with one click.<\/p>\n\n<p>\ud83d\udcd6 <a href=\"https:\/\/wpwebhooks.org\/docs\/\">Full documentation at wpwebhooks.org\/docs\/<\/a><\/p>\n\n<h4>Bring your own AI \u2014 free options included<\/h4>\n\n<ul>\n<li><strong>WordPress 7.0 AI Client<\/strong> \u2014 if your site already has an AI provider connected (Settings \u2192 Connectors), the builder uses it directly; the plugin stores no keys<\/li>\n<li><strong>Your own API key<\/strong> \u2014 connect Anthropic, OpenAI, or Google in the builder; keys are encrypted in the Credentials Vault and never returned over the API<\/li>\n<li><strong>Free to run<\/strong> \u2014 a free Google AI Studio key gives you Gemini at no cost: <a href=\"https:\/\/wpwebhooks.org\/docs\/get-google-ai-studio-api-key\/\">step-by-step tutorial<\/a><\/li>\n<li><strong>Automatic fallback<\/strong> \u2014 if a provider is rate-limited mid-build, the agent switches to another connected provider and keeps going<\/li>\n<\/ul>\n\n<h4>What the AI works from<\/h4>\n\n<p>The agent doesn't guess \u2014 it works from your site's real data. It maps fields against actually captured payloads, edits existing webhooks by name or id instead of duplicating them, validates endpoints with a guarded probe (SSRF-protected, secrets always redacted), and verifies the result with a real test delivery. Every operation is also published as a WordPress Ability, so external AI tools (Claude Code, Cursor) can drive the same toolset over MCP with scoped API tokens.<\/p>\n\n<h4>The engine underneath (free)<\/h4>\n\n<ul>\n<li>Turn any WordPress do_action into a first-class automation trigger your CRMs, n8n flows, AI agents, and internal services can consume<\/li>\n<li>Persistent delivery queue with smart retry and exponential backoff \u2014 powered by WP-Cron, auto-upgrades to Action Scheduler or System Cron when available, <strong>(Pro)<\/strong> External Cron for guaranteed reliability<\/li>\n<li>Per-event UUID and ISO 8601 timestamp \u2014 enable downstream deduplication<\/li>\n<li>Delivery logs with full attempt history, request\/response inspection, replay, and bulk retry<\/li>\n<li>Synchronous execution mode \u2014 fire inline without queue delay<\/li>\n<li>Payload mapping \u2014 rename, restructure, exclude, and type-cast fields with dot-notation paths<\/li>\n<li>Conditional dispatch \u2014 filter events by payload field values before dispatch<\/li>\n<li>HTTP method, custom headers, and URL query parameters per webhook<\/li>\n<li>Dynamic endpoint URLs \u2014 <code>{{ field.path }}<\/code> placeholders resolved at dispatch time (free via <code>fswa_webhook_url<\/code> filter)<\/li>\n<li>Webhook Chains \u2014 wire 2xx completions to downstream webhooks with full observability<\/li>\n<li>Credentials Vault \u2014 store reusable auth secrets (Bearer, Basic, API key, custom) encrypted at rest; reference them from webhooks instead of pasting raw Authorization headers. Secrets are write-only over the API \u2014 never returned, only a masked hint<\/li>\n<li>Activity History \u2014 persistent audit log of every admin and API-token action<\/li>\n<li>Built-in CF7 and IvyForms integrations \u2014 structured payloads, no extra plugins<\/li>\n<li>Action Scheduler auto-detection \u2014 more reliable delivery on high-traffic sites<\/li>\n<li>Fully translatable \u2014 the entire admin interface and all server-side strings are internationalized; ships with Polish, Simplified Chinese, and Dutch, and is compatible with WPML and Polylang String Translation<\/li>\n<li>Full REST API with scoped API token authentication (<code>read<\/code> \/ <code>operational<\/code> \/ <code>full<\/code> \/ <code>agent<\/code>) \u2014 the <code>agent<\/code> scope grants full write access for AI assistants while never exposing stored secrets<\/li>\n<li>Developer extensibility \u2014 16 filters and 7 action hooks (<a href=\"https:\/\/wpwebhooks.org\/docs\/\">reference<\/a>)<\/li>\n<\/ul>\n\n<h4>Pro features<\/h4>\n\n<ul>\n<li>AI writes Code Glue for you \u2014 the agent drafts PHP snippets, test-runs them against your real captured payloads, and assigns them to webhooks (with your confirmation) for pre-dispatch payload enrichment or post-dispatch side effects<\/li>\n<li>AI sets advanced conditions \u2014 with Pro the agent can propose multi-rule AND\/OR condition groups instead of a single rule<\/li>\n<li>Code Glue \u2014 attach PHP snippets to any webhook+trigger (pre-dispatch payload enrichment, post-dispatch side effects)<\/li>\n<li>External Cron \u2014 replace unreliable visitor-triggered WP-Cron with a managed external pinger, provisioned automatically on license activation. Two modes: plugin queue endpoint (down to 20 s interval, configurable batch size) or WP-Cron endpoint (60 s, covers all WordPress background work). No server crontab or external dashboard \u2014 controlled entirely from wp-admin, with a live heartbeat chart and inline error alerts<\/li>\n<li>Unlimited conditions per trigger with AND\/OR groups<\/li>\n<li>Per-webhook retry limit and backoff strategy overrides<\/li>\n<li>Dynamic URL templates \u2014 <code>{{ }}<\/code> syntax with no custom PHP required<\/li>\n<\/ul>\n\n<p><a href=\"https:\/\/wpwebhooks.org\/pricing\/\">See pricing and upgrade \u2192<\/a><\/p>\n\n<h4>Examples<\/h4>\n\n<ul>\n<li><a href=\"https:\/\/wpwebhooks.org\/examples\/cf7-to-webhook\/\">Send Contact Form 7 submissions to a webhook (n8n demo)<\/a><\/li>\n<li><a href=\"https:\/\/wpwebhooks.org\/examples\/gravity-forms-webhooks\/\">Send Gravity Forms Submissions to n8n<\/a><\/li>\n<li><a href=\"https:\/\/wpwebhooks.org\/examples\/ivyforms-to-webhook\/\">Send IvyForms submissions to a webhook (n8n demo)<\/a><\/li>\n<li><a href=\"https:\/\/wpwebhooks.org\/examples\/woocommerce-order-webhook-claude-code\/\">WooCommerce orders to n8n on completion \u2014 wired up with a Claude Code agent<\/a><\/li>\n<li><a href=\"https:\/\/wpwebhooks.org\/examples\/hubspot-woocommerce-integration\/\">WooCommerce to HubSpot integration \u2014 sync orders, contacts, and deals with no custom code<\/a><\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin files to the <code>\/wp-content\/plugins\/flowsystems-webhook-actions<\/code> directory, or install the plugin through the WordPress plugins screen.<\/li>\n<li>Activate the plugin through the 'Plugins' screen in WordPress.<\/li>\n<li>Navigate to Webhook Actions in the admin menu \u2014 it opens on <strong>Build with AI<\/strong>.<\/li>\n<li>Connect an AI provider (or use your WordPress 7.0 AI connectors) and describe the integration you want \u2014 or skip the AI and configure webhooks manually under the Webhooks tab.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"does%20the%20ai%20builder%20need%20an%20api%20key%3F%20is%20it%20free%20to%20use%3F\"><h3>Does the AI Builder need an API key? Is it free to use?<\/h3><\/dt>\n<dd><p>The AI Builder needs a model to talk to, and you have free options. If your WordPress 7.0 site already has an AI provider connected (Settings \u2192 Connectors), the builder uses it with no extra setup. Otherwise connect your own Anthropic, OpenAI, or Google key \u2014 a free Google AI Studio key gives you Gemini at no cost. <a href=\"https:\/\/wpwebhooks.org\/docs\/get-google-ai-studio-api-key\/\">Here's how to get one in two minutes \u2192<\/a><\/p><\/dd>\n<dt id=\"is%20my%20data%20safe%20with%20the%20ai%20builder%3F\"><h3>Is my data safe with the AI Builder?<\/h3><\/dt>\n<dd><p>Yes. Your provider API keys are encrypted in the Credentials Vault and never returned over the API. Stored webhook credentials are never sent to the AI model, and captured payload values whose field names look sensitive (passwords, tokens, keys) are redacted before any prompt is built. The agent's changes run locally in the plugin \u2014 the model only proposes the plan.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20free%3F\"><h3>Is this plugin free?<\/h3><\/dt>\n<dd><p>Yes. The core plugin is completely free and licensed under GPL. Webhook Actions Pro is an optional paid upgrade that adds unlimited conditions, per-webhook retry and backoff settings, Code Glue snippets, External Cron (activated automatically on license activation), and more. <a href=\"https:\/\/wpwebhooks.org\/pricing\/\">Learn more \u2192<\/a><\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20woocommerce%2C%20n8n%2C%20make%2C%20zapier%2C%20and%20ai%20agents%3F\"><h3>Does it work with WooCommerce, n8n, Make, Zapier, and AI agents?<\/h3><\/dt>\n<dd><p>Yes. Any WordPress or WooCommerce action can be a trigger. The plugin delivers to any HTTP endpoint \u2014 n8n, Make, Zapier webhook nodes, internal services, or AI agent APIs. Scoped API tokens let Claude Code, Cursor, or any automation tool read logs, retry deliveries, and toggle webhooks without WordPress credentials.<\/p><\/dd>\n<dt id=\"do%20i%20need%20extra%20plugins%20for%20contact%20form%207%20or%20ivyforms%3F\"><h3>Do I need extra plugins for Contact Form 7 or IvyForms?<\/h3><\/dt>\n<dd><p>No. Both integrations are built in. When CF7 or IvyForms is active, submissions are automatically normalized into clean JSON payloads \u2014 no additional plugins or custom code required.<\/p><\/dd>\n<dt id=\"how%20does%20retry%20work%3F\"><h3>How does retry work?<\/h3><\/dt>\n<dd><p>5xx and 429 responses retry automatically with exponential backoff (delays of ~30s, 60s, 120s, 240s, 480s, capped at 1 hour). 4xx and 3xx responses are marked <code>permanently_failed<\/code> immediately \u2014 bad payloads are not worth retrying. Default maximum is 5 attempts; override with the <code>fswa_max_attempts<\/code> filter or <strong>(Pro)<\/strong> per-webhook settings.<\/p><\/dd>\n<dt id=\"can%20i%20access%20the%20rest%20api%20without%20a%20wordpress%20login%3F\"><h3>Can I access the REST API without a WordPress login?<\/h3><\/dt>\n<dd><p>Yes. Create a token from the API Tokens screen and pass it as <code>X-FSWA-Token: &lt;token&gt;<\/code> (or <code>Authorization: Bearer<\/code>). Four scopes available \u2014 <code>read<\/code>, <code>operational<\/code>, <code>full<\/code>, and <code>agent<\/code> (full write access for AI assistants that never exposes stored secrets) \u2014 so you can grant exactly the access each integration needs. Full API reference at <a href=\"https:\/\/wpwebhooks.org\/webhook-wordpress-plugin-api\/\">wpwebhooks.org\/webhook-wordpress-plugin-api\/<\/a><\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<p>For the full release history see <a href=\"https:\/\/wpwebhooks.org\/changelog\/\">wpwebhooks.org\/changelog\/<\/a><\/p>\n\n<h4>2.1.1<\/h4>\n\n<ul>\n<li>Improved: AI Builder chat shows live progress while the agent gathers site data \u2014 each read round appears as it runs instead of a silent spinner<\/li>\n<li>Fixed: a failed AI provider call mid-conversation no longer loses the turn \u2014 everything gathered so far is saved, and retrying resumes from there without re-running the reads<\/li>\n<li>Fixed: the agent now detects captured example payloads with no usable fields (captured by older plugin versions), shows what the capture contains, and asks for a fresh test event instead of inventing field paths<\/li>\n<li>Fixed: AI test deliveries now run pre-dispatch Code Glue snippets (with Pro), matching real dispatches, and report whether a snippet ran<\/li>\n<li>Improved: the trigger-catalog read supports search with capped results, and older read results are trimmed from the model's context \u2014 faster responses and fewer provider timeouts<\/li>\n<li>Improved: AI provider requests allow up to 120 seconds (new <code>fswa_ai_http_timeout<\/code> filter) instead of timing out at 60 on large conversations<\/li>\n<li>Added: copy-to-clipboard buttons in the AI Dev Trace panel \u2014 full trace entry as JSON, system prompt, messages, raw request and response<\/li>\n<li>Fixed: AI trace logging no longer stops silently when the day's log file was created by a CLI session<\/li>\n<\/ul>","raw_excerpt":"Describe what you want in chat \u2014 the built-in AI agent plans, builds, and tests your WordPress webhooks, integrations, and automations.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/280953","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=280953"}],"author":[{"embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/mateuszflowsystems"}],"wp:attachment":[{"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=280953"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=280953"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=280953"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=280953"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=280953"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/emoji.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=280953"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}