How to test a webhook with Postman
Postman tests the receiving half of a webhook. You build a POST request that looks exactly like a real delivery, point it at your endpoint, and assert on the response. The one thing Postman cannot do is give you a public URL that captures deliveries from a third party, so pair it with a tunnel or a capture tool.
Build the request
Start from a real payload rather than one you invented. Every provider dashboard keeps a log of deliveries it has attempted; open a recent one, copy the JSON body and the headers, and you have a specimen that matches production byte for byte. Guessing at the shape of a payload is how you end up with a handler that passes its tests and fails on the first real event.
In Postman, create a request with the method set to POST and the URL set to your webhook endpoint, which during local development is usually http://localhost:3000/webhooks. Set the body to Raw with the JSON type so Postman sends Content-Type: application/json, and paste the payload in. Add the provider's metadata headers by hand: the event ID, the timestamp, and the event type, whatever they are called in that provider's scheme.
Send it. A correct handler returns 2xx in well under a second, because the work belongs in a background job rather than the request. If Postman shows the response taking two seconds, you have found a timeout waiting to happen before a real sender did.
Sign the request so verification stays on
The temptation is to disable signature verification while testing. Don't: verification is the part most likely to break, and a test suite that skips it tests the wrong thing. Postman's pre-request scripts can sign the request for you, so the endpoint stays locked down and the request still gets in.
Providers that follow the Standard Webhooks specification sign the string id.timestamp.body with HMAC-SHA256 and send the result base64-encoded in a webhook-signature header. Postman's sandbox ships CryptoJS, so the whole scheme fits in a pre-request script:
const id = pm.variables.replaceIn('{{$guid}}');
const timestamp = Math.floor(Date.now() / 1000);
const body = pm.variables.replaceIn(pm.request.body.raw);
const secret = CryptoJS.enc.Base64.parse(pm.environment.get('webhook_secret'));
const signature = CryptoJS.HmacSHA256(`${id}.${timestamp}.${body}`, secret)
.toString(CryptoJS.enc.Base64);
pm.request.headers.add({ key: 'webhook-id', value: id });
pm.request.headers.add({ key: 'webhook-timestamp', value: String(timestamp) });
pm.request.headers.add({ key: 'webhook-signature', value: `v1,${signature}` });
Store the secret as a Postman environment variable, without the whsec_ prefix, and keep it in a local environment rather than one you sync. Other providers differ in the details, usually in what goes into the signed string and whether the digest is hex or base64, but the shape of the script is the same.
Capture what a real sender sends
Postman is an HTTP client, so it can only push requests out. To see what a provider actually sends, you need something publicly reachable. A capture tool such as Svix Play gives you a URL that records every delivery with its headers, which you then copy into Postman as your specimen. A tunnel such as ngrok does the same for code already running on your laptop. Postman mock servers cover a narrower case: they return canned responses at a public URL and log the calls, which is useful when you are the sender and want to see your own requests land.
Test the failures, not the happy path
Replaying a good event proves almost nothing. Duplicate every request Postman sends and confirm the second one changes nothing, because retries make duplicates routine and deduplication is the fix. Backdate the timestamp by an hour and confirm the request is rejected, which is your replay attack protection and the reason timestamp tolerance exists. Flip one character of the signature and confirm a 401. Truncate the JSON mid-object and confirm a 400 rather than a stack trace. Send a body ten times the size you expect and confirm it is rejected instead of buffered.
Each of these is a saved request in one Postman collection, with a test script asserting the status code. That turns a folder of manual pokes into a suite you can run in ten seconds after every change.
Run the collection in CI
Newman is Postman's command-line runner, and it takes an exported collection directly:
newman run webhooks.postman_collection.json \
--environment ci.postman_environment.json \
--bail
Point it at a service your pipeline just booted, and signature regressions fail the build instead of production. Raw-body handling is the classic catch: verification needs the exact bytes that arrived, and a JSON middleware that re-serializes the body breaks it in a way only an end-to-end request notices.
For the wider picture of what to test and how, see our webhook testing guide, and debugging webhooks for when a delivery has already gone wrong in production. If you would rather not own signature verification and delivery durability at all, Svix Ingest handles the receiving side.
Frequently asked questions
Can Postman receive a webhook?
No. Postman sends HTTP requests, it does not listen for them, so a provider cannot deliver to it. Use a capture tool such as Svix Play or a tunnel such as ngrok to receive real deliveries, then copy the payload and headers into a Postman request.
How do I sign a webhook request in Postman?
Use a pre-request script. CryptoJS is available in Postman's sandbox, so you can compute HMAC-SHA256 over the provider's signed string and add the signature, message ID, and timestamp headers with pm.request.headers.add before the request is sent.
Should I disable signature verification when testing?
No. Verification is the part of a webhook handler most likely to break, and raw-body bugs only show up when it is switched on. Sign test requests with a test secret instead, so verification stays enabled everywhere.
Need to receive webhooks reliably?
Svix Ingest gives you one endpoint for webhooks from any provider, with signature verification and durability built in, so a redeploy or a traffic spike never drops an event.
Start receiving webhooks with Svix Ingest or inspect webhooks with Svix Play