Webhook Trigger
A webhook trigger gives a flow a URL that an outside service can POST to. The request body becomes$.trigger, the flow runs, and the response goes back to the caller.
Underneath, it is a gateway mapping pointed at your flow — the same machinery as the HTTP Request trigger. The difference is that the webhook trigger generates the path for you, opens it to the public, and hides the tuning controls.
Creating one
Add a Webhook trigger from the Add Node panel. A Create Webhook dialogue opens showing the URL that will be created, a Public / Secure pill, a Security section for issuing an API key, and — if your account has more than one gateway — a gateway to pick. Press Create. The pill reports the state rather than setting it: issue a key and it reads Secure. See Security. The URL is fixed. It is built from your flow’s own identifiers and there is nothing to type.The URL
<your-gateway-host> is your own gateway’s hostname — a subdomain of the platform’s API host, unique to that gateway. It is not api.quiva.ai, and there is no shared webhook host that every account posts to.
Calling it
POST only, with a JSON body or none at all. The method is not configurable on the trigger.x-api-key. There is no query-string form. Keys issued from a trigger panel are restricted keys — they carry an msr- prefix and are valid for that one endpoint and method only.
A body that is present must be valid JSON, and one that is not comes back as 400 with a JSON error body naming the parse failure. Form-encoded (application/x-www-form-urlencoded) and multipart bodies are refused on the same grounds, so a service that cannot send JSON cannot drive a webhook trigger.
An empty body is fine, though: a POST carrying nothing starts the run with $.trigger set to null.
Query parameters do reach the flow — not on $.trigger, but as headers. See Query parameters below.
Security
A webhook with no key is public — anyone who knows the URL can run your flow. Both the create dialogue and the trigger node let you fix that. At creation. The Create Webhook dialogue has a Security section. Set Expiry (days) (365 by default) and press Generate API Key; the webhook is then created secured rather than public. The key is shown once, in that dialogue, and cannot be retrieved after it closes — copy it before pressing Create. If a key for this webhook’s name already exists on the account, the dialogue surfaces that one instead and the webhook is created secured against it. Afterwards. Open the webhook trigger node. It carries a Public URL toggle and a Security section that is always present, whichever state the webhook is in. Generating a key there also clears Public URL, since a key on a public endpoint protects nothing. Press Save — the toggle lives on the gateway mapping, not on the node, and Save writes both. There is no regenerate. Rotating means deleting the key and generating a new one, which invalidates the old one at once.Reading the request
$.trigger is the raw request body, unwrapped and with nothing added.
For this body:
Request headers are on
$.env.headers, flattened to strings:
Two different casings live in this map. A header the caller sent arrives in
canonical form —
Content-Type, User-Agent, X-Api-Key — because Go’s HTTP
server normalises it on the way in. A header the platform added for you is
lower-case: x-method, x-url, x-account-id and every x-param-*. Nothing
after the gateway re-cases either, so match what you see here exactly.Query parameters
Anything in the query string arrives as a header named after it:
A repeated parameter is comma-joined into one value. A parameter that was not sent is absent, and reading it resolves to
[].
The response
The caller waits for the flow and gets back JSON:result is every step’s output by default. Set the flow’s Final Response Mapping (in the flow’s settings) to a JSONPath object and result becomes exactly that instead — the usual way to hand a sender the shape it expects.
There is no
executionId, no executionTime and no error.code envelope. A run that errors still returns this shape; the failure shows in status and in Monitoring.Draft and published flows
A webhook always runs the published flow. The mapping is created against the published subject even when you build it on a draft, so:- Before the flow’s first publish, calls arrive with nothing to run.
- Editing and pressing Save changes nothing about what the webhook executes. Press Publish.
What runs after the trigger is decided by each step’s outcome, not by the arrows in the editor. A Condition step’s outcome names the step IDs to run next — one, several (they start at the same time), or the reserved
RESOLVE_SUCCESS / RESOLVE_ERROR to end the run. A line drawn between two steps that no outcome names is decoration.Troubleshooting
The sender reports 400 invalid_request_body
The sender reports 400 invalid_request_body
The body is not valid JSON.
details.reason in the response carries the parser’s own message. A sender that posts form-encoded data hits this every time.401 or 403
401 or 403
The webhook is secured and the caller is not sending
x-api-key, or the key has expired. Keys default to a 365-day expiry.The URL 404s
The URL 404s
Check the flow has been published at least once. Then re-copy the Full URL from the trigger node rather than trusting a URL written down earlier.
The flow ran but a step read nothing
The flow ran but a step read nothing
$.trigger is the request body with nothing wrapped around it, so a path that assumed a wrapper resolves to []. Open the run in Monitoring and read the recorded trigger.Only some events should start the flow
Only some events should start the flow
All of them do. Put a Condition step first and branch on a field of
$.trigger.A browser call is blocked by CORS
A browser call is blocked by CORS
Add the site’s origin under Allowed Hosts on an HTTP Request trigger. That list is a property of your account’s gateway, shared by every endpoint on it — it is not per-trigger.
Next Steps
HTTP Request Trigger
The same endpoint with the settings exposed
Condition Step
Filter events and branch the run
Variable Mapping
Reading the request body in later steps
Triggers Overview
Every way a flow can start