How the webhook URL works. It is a public address that records whatever is sent to it and
answers 200. An inbox keeps the 50 most recent requests, accepts bodies up to 256 KB, and is
deleted 24 hours after it was created — or sooner if you press Delete URL or our server
restarts, because requests are held in memory and never written to disk.
Anyone who has the URL can read what it received. Use sandbox and test-mode accounts, do not route production traffic or customer data through it, and delete it when you are done. Privacy details.
What is a Zapier webhook?
Zapier is not a provider with its own event stream — it is plumbing. Its built-in Webhooks by Zapier app exposes two halves. As a trigger (Catch Hook), Zapier hands you a URL under hooks.zapier.com, and any request you send there starts the Zap. As an action (POST, PUT, GET or Custom Request), a Zap sends a request to a URL of yours with whatever fields you mapped.
That means the payload is not fixed. An outbound request contains exactly the keys you typed into the Data fields, and an inbound Catch Hook accepts nearly any JSON, form or query-string body and flattens it into fields for later steps. The sample below is the outbound side — a Zap posting to you — because that is the one worth inspecting on a URL you control.
What a Zapier webhook request looks like
The request line and headers as they reach your server, followed by the body. Ids, tokens and the signature are placeholders.
POST /your/webhook/path HTTP/1.1
Host: your-server.example
Content-Type: application/json
Accept: application/json
User-Agent: Zapier
X-Webhook-Secret: put-a-long-random-value-here
{
"event": "form.submitted",
"submitted_at": "2026-01-01T12:00:00Z",
"name": "Jon Doe",
"email": "jon@example.com",
"plan": "starter",
"source": "Contact form"
}
Every key here was chosen by whoever built the Zap; there is no schema. With the default form payload type the same data arrives as event=form.submitted&name=Jon+Doe…, and unless the action's Unflatten option is on, a key written as customer__email stays flat rather than becoming a nested object.
Headers Zapier sends
| Header | Example | What it is |
|---|---|---|
Content-Type | application/json | Follows the action's Payload Type: json, form (urlencoded, the default), xml or raw. |
Accept | application/json | Sent by default. |
User-Agent | Zapier | Identifies the sender. Anyone can set the same value. |
X-Webhook-Secret | put-a-long-random-value-here | Not sent by default — a header you add in the action's Headers field so your endpoint can recognise the Zap. |
Header names are case-insensitive. Your framework may show them lower-cased, and HTTP/2 always does.
Zapier does not sign requests
There is no signature header and no shared secret. A request from a Webhooks by Zapier action is authenticated only by whatever you add to it: a custom header, Basic auth credentials in the action's Basic Auth field, or a token in the URL. Zapier sends from shared cloud address ranges, so an IP allow-list identifies "Zapier", not "my Zap".
The practical pattern is a long random value in a custom header, checked in constant time, over HTTPS. For inbound Catch Hook URLs the URL itself is the credential — anyone who has it can trigger the Zap — so treat it like a password and never commit it to a repository.
const crypto = require('crypto');
// A shared secret you put in the Zap action's Headers field
function fromMyZap(req, secret) {
const a = Buffer.from(req.headers['x-webhook-secret'] || '');
const b = Buffer.from(secret);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Responses, failures and the Catch Hook reply
For an outbound action, Zapier treats a 2xx as success and makes the response body available to later steps; a 4xx or 5xx marks the step as errored in the Zap's history. Whether an errored run is replayed depends on the account's replay settings rather than on anything your endpoint can control, so do not design around automatic retries.
For an inbound Catch Hook, Zapier answers almost immediately with a small JSON receipt — a status of success plus identifiers for the attempt and request — before the Zap has run. That 200 means "received", not "your Zap worked". The Zap's own history is where failures show up.
See exactly what your Zap sends
- Press Create webhook URL at the top of this page and copy the address.
- In your Zap, add an action step, choose Webhooks by Zapier and the POST event.
- Paste the address into URL, set Payload Type to
json, and map the Data fields. - Add any headers you plan to use in production, then run the step's test.
- The request appears in the inbox above — the real method, headers and body your endpoint will have to handle.
This is the quickest way to answer "is Zapier sending JSON or form data?" and "did my nested key unflatten?" without deploying anything.
To run a caught request against your own code, select it and press Open in API Tester: the method, headers and body are loaded into the request console, where you enter your server's public URL and send it. A body you edit will no longer match its signature — that is the signature doing its job.
Things that catch people out
- The default payload type is form, not JSON. A handler that only parses JSON sees an empty body until the action is switched.
- Catch Hook flattens and picks. Nested JSON becomes double-underscore field names, and if you post an array the Zap runs once per element. Use Catch Raw Hook when you need the untouched body and headers — for instance to verify another provider's signature inside a Code step.
- Empty values vanish. A mapped field with no value is omitted from the outbound body rather than sent as null, so do not treat "key missing" as an error.
api-tester.com is independent and is not affiliated with Zapier. Providers change header names, limits and retry schedules; treat the official Zapier documentation as the source of truth.
Related examples and tools
Slack Webhook Example
The JSON Slack's Events API posts to your Request URL, the one-time url_verification handshake, and the v0 signature that covers a timestamp as well as the body.
Discord Webhook Example
A Discord webhook runs the other way from most: you send the request, and Discord posts it in a channel.
Twilio Webhook Example
Twilio's webhooks are form posts, not JSON, and the signature covers your URL as well as the parameters.
GitLab Webhook Example
The JSON a GitLab project webhook posts on a push, the headers that describe it, and the secret token that is compared rather than computed.
Telegram Webhook Example
The Update object Telegram posts to a bot's webhook, the optional secret-token header, and the trick of answering with an API call in the response body.
Content-Type Header
JSON versus form-encoded bodies, and how a server decides which parser to run.
Curl POST Form
Send a form-encoded body like this one from a terminal.
Webhook Tester
The inbox on its own page, plus a guide to signatures, retries and idempotent handlers.
All Webhook Examples
30 providers side by side: content type, signature scheme and retry behaviour.
Other webhooks with no signature
References
- Official Zapier documentation — The provider's own guide to the requests described on this page.
- Zapier Help: trigger Zap workflows from webhooks — Setting up the Catch Hook trigger and what it accepts.
- Zapier Help: send webhooks in Zap workflows — The action that makes a request to your URL.
- Node.js: crypto.timingSafeEqual() — The constant-time comparison used in the code on this page.
These links leave api-tester.com, which is independent of the companies and projects they point to.
Zapier webhook FAQ
What does a Zapier webhook request look like?
An ordinary HTTP request with a User-Agent of Zapier and a body containing exactly the fields mapped in the action — JSON, form-encoded, XML or raw depending on the Payload Type setting.
Does Zapier sign its webhook requests?
No. There is no signature header. Authenticate the request yourself with a custom secret header, Basic auth or a token, and always use HTTPS.
What is the difference between Catch Hook and Catch Raw Hook?
Catch Hook parses the incoming body into fields for later steps. Catch Raw Hook passes the unparsed body and the request headers through, which you need for signature verification or unusual formats.
What does a Zapier Catch Hook URL return?
A 200 response with a short JSON receipt containing a success status and identifiers for the attempt and request. It is returned before the Zap runs, so it confirms receipt only.
Why is my endpoint receiving form data from Zapier instead of JSON?
Because the action's Payload Type defaults to form. Change it to json in the step's settings.