Test Intercom Webhooks Locally (Intercom Webhook on localhost)
Test Intercom webhooks locally on localhost without deploying. Inspect the real topic payload, forward to your handler, and verify the X-Hub-Signature.

You are building an Intercom integration — syncing contacts, reacting to new conversations, piping events into your own product — and you need to see your handler react to a real conversation.user.created or contact.created notification. The problem is immediate: Intercom will only POST to a public HTTPS URL, and your handler is running on localhost:8080. Intercom 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 actual topic, data, and X-Hub-Signature Intercom sends. What you want is to test Intercom webhooks locally — real notifications, hitting your local handler, with a URL that does not change every time you restart.
This guide shows how to do exactly that.
Why testing Intercom webhooks locally is tricky
A webhook is just an HTTP request that Intercom sends to a URL when something happens in your workspace — a new conversation, a contact update, a tag applied. Intercom 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 HTTPS endpoint Intercom 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 Intercom once and never touch it again.
There is one Intercom-specific wrinkle: when you save a webhook URL in the Developer Hub, Intercom sends a HEAD request to validate it before it will accept the subscription. Your endpoint must respond successfully to that check, and it must be HTTPS. Webhook Relay endpoints are HTTPS and answer the validation probe, so the URL is accepted right away.
Step 1: Inspect the real payload with Webhook Bin
Before you write any handler code, find out what Intercom actually sends. Open the free Webhook Bin — no signup — and you get an instant public HTTPS URL.
- Copy the Webhook Bin URL.
- Go to the Intercom Developer Hub, open your app, and in Configure → Webhooks paste the URL as the endpoint.
- Subscribe to the topics you care about — for example
conversation.user.created,contact.created, orcontact.tag.created. - Save. Intercom validates the URL with a HEAD request, then starts delivering notifications.
Trigger a real action in your workspace (start a conversation, create a contact) and inspect the captured request in Webhook Bin: the full JSON body, the query string, and every header. You will see the notification envelope Intercom uses — type: notification_event, the topic, your app_id, and a data object wrapping the affected Intercom resource — plus the X-Hub-Signature header.
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 notifications to localhost with the relay agent
Once you know the payload, route those same notifications into your local handler. Sign up for Webhook Relay, install the relay agent (CLI or Docker), and create a bucket — say intercom. The bucket gives you a stable public input endpoint.
Start forwarding to your local server:
relay forward --bucket intercom 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 Intercom webhook endpoint in Configure → Webhooks to your Webhook Relay endpoint (or just create it there from the start). Trigger an event and watch it arrive on localhost.
Intercom-specific configuration and quirks
A few Intercom details worth knowing:
- Where to configure it: webhooks live on a Developer Hub app, not in the main workspace settings. Open your app and go to Configure → Webhooks. You also need the matching permissions enabled on the app's Authorization page before some topics will deliver.
- Topics, not "all events": you explicitly subscribe to topics such as
conversation.user.created,conversation.admin.replied,contact.created, andcontact.tag.created. Use thetopicfield in the body to branch in your handler. - HTTPS + HEAD validation: the endpoint must be HTTPS and must answer Intercom's HEAD validation request, or the subscription will not save. Webhook Relay handles both.
- Respond fast with 200: Intercom expects an HTTP
200within 5 seconds and will retry otherwise. Acknowledge receipt immediately, then do slow work asynchronously. Sustained error responses will pause or suspend your subscription. - Payload envelope: the body always wraps the resource in a
notification_eventshape with adata.itemobject — your handler readstopicto know what happened anddata.itemfor the resource.
Step 3: Verify the Intercom webhook signature
Intercom signs every notification so you can confirm it really came from Intercom. It computes an HMAC-SHA1 of the raw request body using your app's client secret as the key, hex-encodes the result, and sends it in the X-Hub-Signature header, formatted as sha1=....
Your handler should recompute the HMAC-SHA1 over the raw body (the exact bytes received, before any JSON parser reshapes them) and compare in constant time before trusting the payload. Note this is SHA-1, not the SHA-256 some other providers use — match the algorithm exactly or the digest will never line up.
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 notification against your handler without touching Intercom at all.
- Iterate on your handler by editing code and replaying the same delivery until it behaves correctly. No deploys just to test a single 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 Intercom 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 intercom http://localhost:8080/webhook. - Point your Intercom Developer Hub webhook at the stable endpoint, trigger an event, and watch it hit
localhost.
You will be testing real Intercom topics against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.
