---
title: "Test Linear Webhooks Locally | WebhookRelay"
meta:
  "og:description": "Test Linear webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the Linear-Signature."
  "og:title": "Test Linear Webhooks Locally"
  description: "Test Linear webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the Linear-Signature."
---

![Stripes](https://webhookrelay.com/blog/receive-linear-webhooks-locally/images/stripes.svg)

# **Test Linear Webhooks Locally**

Test Linear webhooks locally and receive them on localhost without deploying. Inspect the real payload, forward to your handler, and verify the Linear-Signature.

![Test Linear Webhooks Locally (Receive Linear Webhooks on localhost)](https://webhookrelay.com/blog/receive-linear-webhooks-locally/images/blog/heroes/localhost.jpg)

You are building a Linear integration — a Slack notifier, a deployment trigger, a sync to your own database — and you need to watch your handler react to a real `Issue` or `Comment` event. The problem hits immediately: Linear will only POST to a **public URL**, and your handler is running on `localhost:8080`. Linear has no way to reach it.

The usual workarounds are slow. Deploying to a staging environment for every code change kills your iteration speed. Copying a sample payload out of the docs into curl gives you a _guess_ at the real request, not the exact headers and body Linear actually sends. What you really want is to **test Linear webhooks locally** — real events, hitting your local handler, on a URL that does not change every time you restart.

This guide shows how to do exactly that.

## [Why testing Linear webhooks locally is tricky](#why-testing-linear-webhooks-locally-is-tricky)

A webhook is just an HTTP request that Linear sends to a URL when something changes in your workspace — an issue is created, a comment is added, a project is updated. Linear lives on the public internet; your dev machine usually does not. It sits 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 Linear can hit that relays each request down to your laptop without you opening a single firewall port. That is what [Webhook Relay](https://my.webhookrelay.com/register) does — and unlike a random tunnel URL, the endpoint is **stable**, so you configure Linear once and never touch it again.

## [Step 1: Inspect the real payload with Webhook Bin](#step-1-inspect-the-real-payload-with-webhook-bin)

Before you write any handler code, find out what Linear actually sends. Open the free [Webhook Bin](https://webhookrelay.com/blog/receive-linear-webhooks-locally/webhook-bin/) — no signup — and you get an instant public URL.

1. Copy the Webhook Bin URL.
2. In Linear, go to **Settings → API → Webhooks** and click **New webhook** (you can also create a webhook scoped to a single team).
3. Paste the URL into the webhook **URL** field.
4. Choose the resource events you care about — **Issues**, **Comments**, **Projects**, **Issue labels**, and more — then save.

Trigger a real action (create an issue, drop a comment) and inspect the captured request: the full JSON body, including the `action` (`create`, `update`, `remove`), the `type`, the `data` object, and the `webhookTimestamp`. You will also see every header, including `Linear-Event`, `Linear-Delivery`, and `Linear-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](https://webhookrelay.com/blog/receive-linear-webhooks-locally/blog/how-to-test-webhooks/) and [What is a webhook](https://webhookrelay.com/blog/receive-linear-webhooks-locally/blog/what-is-webhook/).

## [Step 2: Forward the events to localhost with the relay agent](#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](https://my.webhookrelay.com/register), install the `relay` agent (CLI or Docker), and create a bucket — say `linear`. The bucket gives you a stable public input endpoint.

Start forwarding to your local server:

```
relay forward --bucket linear 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](https://webhookrelay.com/blog/receive-linear-webhooks-locally/docs/webhooks/internal/localhost/).

Now update the Linear webhook's **URL** to your Webhook Relay endpoint (or just create it there from the start). Create an issue and watch it arrive on `localhost`.

## [Linear-specific configuration and quirks](#linear-specific-configuration-and-quirks)

A few Linear details worth knowing:

- **Where to add it:** **Settings → API → Webhooks** for a workspace-level webhook, or scope a webhook to an individual team if you only care about that team's activity.
- **Events:** subscribe to the resource types you need — Issues, Comments, Projects, Cycles, Issue labels, Attachments, and others. Each delivery carries the resource name in the `Linear-Event` header and an `action` field in the body, so you branch on those in your handler.
- **Payload shape:** the body is always JSON. Expect top-level `action`, `type`, `data`, `url`, and `webhookTimestamp` keys. The `data` object mirrors the resource that changed.
- **Per-webhook secret:** when you create the webhook, Linear shows a **signing secret** unique to that webhook. Save it — you need it to verify signatures (next step).
- **Respond fast:** Linear expects a quick `2xx`. Acknowledge the delivery first, then do slow work asynchronously so you do not trip delivery timeouts.

## [Step 3: Verify the Linear webhook signature](#step-3-verify-the-linear-webhook-signature)

Linear signs every request. It computes an **HMAC-SHA256** of the **raw** request body using your webhook's secret, hex-encodes the result, and sends it in the **`Linear-Signature`** header. Your handler should recompute the HMAC over the raw body and compare it to the header value in constant time before trusting the payload.

Linear also includes a **`webhookTimestamp`** in the body. After the signature checks out, confirm that timestamp is recent (for example, within 60 seconds of now) and reject anything older — this stops an attacker from replaying a previously valid request.

To sanity-check your implementation, paste a captured body, your secret, and the received signature into the free [HMAC signature verifier](https://webhookrelay.com/blog/receive-linear-webhooks-locally/hmac-verification/). For language-specific code and the common pitfalls (reading the body _after_ a JSON parser has already consumed it, timing-safe comparison), read [Verify a webhook signature](https://webhookrelay.com/blog/receive-linear-webhooks-locally/blog/verify-webhook-signature/).

## [Replay and iterate](#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 event against your handler without touching Linear at all.
- **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 single code path.
- **Keep `relay forward` running** while you work — events stream straight to `localhost` as you trigger them in Linear.

Because the Webhook Relay endpoint is stable, you can stop and restart the agent, reboot your machine, or come back next week — the Linear configuration never needs to change.

## [Get started](#get-started)

1. Inspect the real payload in the free [Webhook Bin](https://webhookrelay.com/blog/receive-linear-webhooks-locally/webhook-bin/) — no signup needed.
2. [Create a Webhook Relay account](https://my.webhookrelay.com/register), install the agent, and run `relay forward --bucket linear http://localhost:8080/webhook`.
3. Point your Linear webhook at the stable endpoint, create an issue, and watch it hit `localhost`.

You will be testing real Linear events against your local handler in a few minutes — no deploys, no open firewall ports, and a URL you configure exactly once.