In most WordPress setups, webhooks are hardcoded in PHP, configured manually in a plugin UI, and tightly coupled to deployments. If you want to change an endpoint, disable an integration, or create webhooks dynamically — you edit code, redeploy, and hope nothing breaks.
Modern systems don't work like this. You control integrations via API.
Most articles about WordPress webhooks focus on sending them — how to fire an HTTP request when an order is placed, a form is submitted, or a user registers. The sending part is well-covered.
The missing piece is the control layer: there is no standard way to create webhooks remotely, update their endpoints, toggle integrations on and off, or manage them across multiple environments without logging into each site individually.
Without API control, webhooks are static. You write them once in PHP and they stay there until someone edits the code. When an endpoint changes, you deploy. When a staging environment should not fire to production, you comment out code. When a client's integration needs to be paused, you log in and click through the admin UI.
This is the difference between hardcoded integrations and API-driven infrastructure. The delivery layer — retry, replay, monitoring — is one part of the picture. The control layer is the other: how you create and manage what gets sent, and where.
Base URL: https://your-site.com/wp-json/fswa/v1
Auth header: X-FSWA-Token: <token> — requires full scope
A webhook needs two things: a name and an endpoint URL. Everything else is optional — triggers (which WordPress actions fire this webhook), auth header (sent with each delivery), and whether it starts enabled.
id is the webhook identifier used in all subsequent operations. triggers maps to WordPress action hook names — use GET /wp-json/fswa/v1/triggers to browse all available hooks grouped by category (WooCommerce, Contact Form 7, WordPress core, etc.).
If the receiving endpoint requires authentication, pass it as auth_header. It will be sent as the Authorization header with every delivery.
Listing webhooks requires only a read scope token — you don't need write access to audit what's configured. This is the right token scope for monitoring scripts, dashboards, and read-only tooling.
PATCH /webhooks/{id} accepts any subset of fields — you only send what you want to change. Requires full scope.
POST /webhooks/{id}/toggle flips the is_enabled flag. No request body required. This endpoint needs only operational scope — not full.
Toggle requires only operational scope. This is intentional: CI pipelines and deployment scripts that need to pause integrations during a migration don't need full write access — they just need to flip a switch. Create a dedicated operational token for these workflows.
Remove a webhook entirely. Requires full scope. This cannot be undone — the webhook and its configuration are deleted permanently.
During a deployment pipeline, create environment-specific webhooks automatically. Point staging to a test endpoint, production to the live one. Disable all webhooks before a database migration, re-enable after it completes. No one logs into wp-admin during a deployment window.
If you're building a product that integrates with customer WordPress sites, you can register webhooks programmatically during onboarding. No manual configuration. No asking customers to copy-paste an endpoint URL into a form. The webhook is created, the trigger is registered, the integration is live — from a single API call in your onboarding flow.
When building flows in n8n or similar platforms, endpoint URLs change as you move between test and production workflows. Instead of updating WordPress manually every time, your automation can call the PATCH endpoint to update the webhook URL when a workflow is promoted to production. The endpoint stays in sync with the automation, not the other way around.
For a practical example of sending CF7 form data to n8n, see the Contact Form 7 → webhook example.
Managing webhooks across ten client sites means ten separate wp-admin logins to push a configuration change. With API control, one script handles all of them. Standardize webhook configuration across environments, audit what's enabled on each site, roll out endpoint changes without browser tabs.
Webhook infrastructure has two distinct concerns. Most systems handle only one of them.
Control Layer (this article) Delivery Layer (linked below)
────────────────────────────────── ─────────────────────────────────
POST /webhooks create retry POST /logs/{id}/retry
GET /webhooks list replay POST /logs/{id}/replay
GET /webhooks/{id} inspect monitor GET /health
PATCH /webhooks/{id} update GET /queue/stats
POST /webhooks/{id}/toggle on/off inspect GET /logs?status=error
DELETE /webhooks/{id} remove recover POST /logs/bulk-retry
The control layer (this article) handles what exists: which webhooks are registered, where they point, and whether they're active. The delivery layer handles what happened: did events reach their destination, what failed, how to recover.
Together they give you webhooks that are both reliable and controllable. The delivery layer is covered in the companion article: WordPress Webhooks REST API: Retry, Replay and Monitor Events Programmatically.
Flow Systems Webhook Actions exposes both layers via the same authenticated REST API. The full reference — all endpoints, request/response schemas, and scope requirements — is in the API documentation.
Tokens are issued per-site from the plugin admin panel under API Tokens. Each token carries one scope. Use the minimum scope required for the operation — don't give a monitoring script write access.
| Scope | Permitted Operations | Typical Use |
|---|---|---|
| read | GET /webhooks, GET /webhooks/{id}, GET /logs, GET /health, GET /queue/stats | Monitoring, dashboards, auditing |
| operational | All read operations, plus: POST /webhooks/{id}/toggle, POST /logs/{id}/retry, POST /logs/bulk-retry, POST /logs/{id}/replay | CI/CD pipelines, recovery scripts |
| full | All operational operations, plus: POST /webhooks (create), PATCH /webhooks/{id} (update), DELETE /webhooks/{id} | Onboarding scripts, provisioning |
The token is passed in the X-FSWA-Token header. Alternatively, use Authorization: Bearer <token> if your HTTP client expects a Bearer auth format, or append ?api_token=<token> as a query parameter for tools that don't support custom headers.
Tokens are independently revocable. If a token is exposed in a log or a script, revoke it from the plugin settings without disrupting other integrations.
POST /wp-json/fswa/v1/webhooks creates a new webhook from a JSON payload. Required fields are name and endpoint_url. Optional fields include triggers (array of WordPress action hook names), is_enabled (boolean, defaults to true), and auth_header (authorization value sent with each delivery).full scope. The response includes the webhook id, which you use for all subsequent update, toggle, and delete operations.
PATCH /wp-json/fswa/v1/webhooks/{id} to update any field — endpoint URL, name, triggers, auth header. All fields are optional, so you can patch only what changed. Requires full scope.POST /webhooks/{id}/toggle — this only requires operational scope, making it safe for CI pipelines. To remove a webhook entirely, use DELETE /webhooks/{id} with a full scope token.
full scope token. Toggling a webhook on or off requires only operational scope — useful for CI/CD pipelines that pause integrations during deployments without needing full write access. Listing and inspecting webhooks requires only read scope.read. Deployment scripts that only toggle webhooks should use operational. Provisioning scripts that create and configure webhooks need full.
GET /wp-json/fswa/v1/webhooks with an X-FSWA-Token header carrying a read scope token. The response is a JSON array where each item includes id, name, endpoint_url, is_enabled, triggers, created_at, and updated_at.?only_enabled=true to filter to active webhooks only. To get a single webhook by ID, use GET /webhooks/{id}.