Receive Vercel Webhooks Locally (Test Vercel Webhooks on localhost)
Test Vercel webhooks locally and run your handler on localhost. Inspect the real deployment payload, forward to your endpoint, and verify the x-vercel-signature.

You are building a Vercel integration — a Slack notifier for failed builds, a changelog updater, an internal dashboard that tracks deploys — and you need to see your handler react to a real deployment.succeeded or deployment.error event. The problem is immediate: Vercel will only POST to a public URL, and your handler is running on localhost:8080. Vercel has no way to reach it.
The usual workarounds are painful. Deploying your handler for every code change is slow and ironic. Pasting a sample payload from the docs into curl gives you a guess at the real request, not the real headers and body Vercel actually sends. What you want is to receive Vercel webhooks locally — real events, hitting your local handler, with a URL that does not change every time you restart.
This guide shows how to do exactly that.
Why receiving Vercel webhooks locally is tricky
A webhook is just an HTTP request Vercel sends to a URL when something happens — a deployment starts, succeeds, errors, or is canceled; a project is created. Vercel sits on the public internet; your dev machine usually does not. It is behind a router, a corporate firewall, or both, with no public IP and no inbound ports open.
So you need something in the middle: a public endpoint Vercel can hit, that relays each request down to your laptop without you opening a single firewall port. That is what Webhook Relay does — and unlike a random tunnel URL, the endpoint is stable, so you configure Vercel once and never touch it again.
(One note before you start: webhooks are a Pro and Enterprise feature on Vercel, configured at the team level. Make sure your team is on a plan that includes them.)
Step 1: Inspect the real payload with Webhook Bin
Before you write any handler code, find out what Vercel actually sends. Open the free Webhook Bin — no signup — and you get an instant public URL.
- Copy the Webhook Bin URL.
- In the Vercel Dashboard, select your team scope and go to Settings → Webhooks.
- Click Create Webhook, paste the URL as the endpoint, and select the events you care about (for example Deployment Created, Deployment Succeeded, Deployment Error).
- Save the webhook.
Now trigger a real action — push to a connected repo or redeploy from the dashboard. Vercel POSTs the event to your endpoint. Inspect the captured request in Webhook Bin: the full JSON body (with the event type, id, payload, and details about the deployment, project, and team), and every header, including the x-vercel-signature signature.
Now you know the exact shape of the data before writing a line of code. For more on this approach, see How to test webhooks and What is a webhook.
Step 2: Forward the events to localhost with the relay agent
Once you know the payload, route those same events into your local handler. Sign up for Webhook Relay, install the relay agent (CLI or Docker), and create a bucket — say vercel. The bucket gives you a stable public input endpoint.
Start forwarding to your local server:
relay forward --bucket vercel http://localhost:8080/webhook
The agent opens an outbound connection to Webhook Relay and streams every incoming request down to http://localhost:8080/webhook. Because the connection is outbound, there are no firewall ports to open and no public IP needed — this works from your laptop, behind a corporate proxy, or inside a Kubernetes cluster. Running in Docker? The same command works in the official webhookrelay/webhookrelayd image. Full details are in the localhost forwarding docs.
Now update the Vercel webhook's endpoint to your Webhook Relay URL (or just create it there from the start). Push a change and watch the deployment.created and deployment.succeeded events arrive on localhost.
Vercel-specific configuration and quirks
A few Vercel details worth knowing:
- Where to add it: select your team scope, then Settings → Webhooks. Webhooks live at the account/team level (or per Integration), not per individual project from inside a project's settings.
- Events: common ones include
deployment.created,deployment.succeeded,deployment.error, anddeployment.canceled, plus project events likeproject.created. Some project-scoped events are only available when the webhook covers all team projects. Branch on thetypefield in your handler. - JSON payload: the body is JSON, posted to your endpoint as a single
POSTper event. - The secret is shown once: when you create a webhook, Vercel displays a secret key once and never again. Copy it immediately — you need it to verify signatures (see below).
- Integration webhooks: if you are building a Vercel Integration rather than a team webhook, you verify with your Integration (Client) Secret instead of a per-webhook secret.
- Limits: Vercel allows up to 20 custom webhooks per team, which is plenty for a dev endpoint plus production.
Step 3: Verify the Vercel webhook signature
Vercel signs every request. It computes an HMAC-SHA1 of the raw request body using your webhook secret and sends the digest, hex-encoded, in the x-vercel-signature header. Your handler should recompute the same HMAC over the raw body and compare in constant time before trusting the payload. In Node.js that is essentially:
const expected = crypto
.createHmac('sha1', secret)
.update(rawBody) // the raw bytes, before JSON parsing
.digest('hex');
// constant-time compare expected with req.headers['x-vercel-signature']
The single most common mistake is computing the HMAC over a re-serialized body after your framework has already parsed the JSON — the bytes differ and verification fails. Capture the raw body. To sanity-check your implementation, paste a captured body, your secret, and the received signature into the free HMAC signature verifier. For language-specific code and the rest of the pitfalls — raw-body handling, timing-safe comparison — read Verify a webhook signature.
Replay and iterate
This is where local development gets fast:
- Replay from Webhook Relay — past requests are stored on your bucket, so you can resend a captured deployment event without triggering a new build on Vercel.
- Iterate on your handler by editing code and replaying the same delivery until it branches on
type, parses the deployment details, and verifies the SHA1 signature correctly. No new commits, no pushes, no deploys just to test a code path. - No wasted builds — you do not have to redeploy your project repeatedly just to generate a fresh
deployment.succeededevent; one captured event replays as many times as you need.
Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Vercel webhook configuration never needs to change.
Get started
- Inspect the real payload in the free Webhook Bin — no signup needed.
- Create a Webhook Relay account, install the agent, and run
relay forward --bucket vercel http://localhost:8080/webhook. - Point your Vercel team webhook at the stable endpoint, trigger a deployment, and watch it hit
localhost.
You will be testing real Vercel deployment events against your local handler in a few minutes — no extra deploys, no open firewall ports, and a URL you configure exactly once.
