Test Sentry Webhooks Locally (Receive Sentry Webhooks on localhost)
Test Sentry webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the Sentry-Hook-Signature.
You are building a Sentry integration — a service that turns errors into tickets, pages an on-call engineer, or syncs issues into your own dashboard — and you need to see your handler react to a real issue alert or error event. The problem is immediate: Sentry will only POST to a public URL, and your handler is running on localhost:8080. Sentry has no way to reach it.
The usual workarounds are painful. Deploying to a staging server for every code change is slow. Copying a sample payload from the docs into curl gives you a guess at the real request, not the real headers and body Sentry actually sends. What you want is to test Sentry 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 Sentry webhooks locally is tricky
A webhook is just an HTTP request that Sentry sends to a URL when something happens — an issue is created, an alert fires, an integration is installed. Sentry 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 Sentry 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 Sentry once and never touch it again.
A quick note on Sentry's webhook mechanisms
Sentry has more than one way to send webhooks, and it helps to know which one you are using before you wire anything up:
- Integration webhooks (recommended): create an Internal or Public integration under Settings → Integrations → Custom Integrations and give it a Webhook URL. These deliver structured JSON for
installation,issue,error,event_alert, andmetric_alertresources, and — importantly — they are signed. - Alert rule webhook actions: in an issue or metric alert rule you can add a webhook action that posts to an integration. These payloads carry an
"action": "triggered"shape with the event data. - Legacy Webhooks: the older per-project "Legacy Webhooks" plugin. Still works, but Sentry steers new setups toward integrations, and the legacy plugin does not give you the signed headers.
For a modern, verifiable setup, use an Internal Integration — that is what produces the Sentry-Hook-Signature and Sentry-Hook-Resource headers described below.
Step 1: Inspect the real payload with Webhook Bin
Before you write any handler code, find out what Sentry actually sends. Open the free Webhook Bin — no signup — and you get an instant public URL.
- Copy the Webhook Bin URL.
- In Sentry, go to Settings → Integrations → Create New Integration → Internal Integration.
- Paste the URL into Webhook URL, enable the resources you care about (Issue, Error, and so on), and save.
- Trigger an event — throw a test error from your app, or resolve an issue.
The request lands in Webhook Bin right away. Inspect the captured request: the full JSON body, and every header, including Sentry-Hook-Resource (which resource fired), Sentry-Hook-Timestamp, Request-ID, and Sentry-Hook-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 sentry. The bucket gives you a stable public input endpoint.
Start forwarding to your local server:
relay forward --bucket sentry 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 set the integration's Webhook URL to your Webhook Relay endpoint (or just create it there from the start). Trigger an error and watch it arrive on localhost.
Sentry-specific configuration and quirks
A few Sentry details worth knowing:
- Where to add it: Settings → Integrations for an organization-wide integration; the legacy plugin lives under Project Settings → Legacy Integrations.
- Resources vs alerts: enabling the issue and error resources sends a webhook automatically whenever an issue is created, resolved, assigned, or archived. If you only want webhooks from specific alert conditions, leave those resource toggles off and add a webhook action to an alert rule instead.
- Client Secret: an internal integration has a Client Secret — this is the key Sentry uses to sign requests. Keep it handy for verification (next step).
- Payload shape differs: issue/error webhooks include the issue object with an action like
resolved; alert-rule webhooks use the"action": "triggered"structure. Branch onSentry-Hook-Resourceso your handler routes each one correctly. - Test installations: installing an internal integration fires an
installationresource webhook — a clean way to confirm your endpoint is reachable.
Step 3: Verify the Sentry webhook signature
Internal and public integration webhooks are signed. Sentry computes an HMAC-SHA256 of the raw request body using your Client Secret and sends the hex digest in the Sentry-Hook-Signature header. Your handler should recompute the HMAC over the raw body and compare in constant time before trusting the payload. Use the Sentry-Hook-Resource header to decide how to process the body.
To sanity-check your implementation, paste a captured body, your Client Secret, and the received signature into the free HMAC signature verifier. For language-specific code and the common pitfalls (reading the body after a JSON parser has consumed it, 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 Sentry event against your handler without triggering a new error in your app.
- Iterate on your handler by editing code and replaying the same delivery until it behaves correctly. No commits, no pushes, no deploys just to test a code path.
Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Sentry 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 sentry http://localhost:8080/webhook. - Point your Sentry integration's Webhook URL at the stable endpoint, trigger an error, and watch it hit
localhost.
You will be testing real Sentry events against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.
