Linear Webhooks
A webhook lets Linear tell your own system when something changes. Instead of asking Linear again and again for new data, your server waits and receives a message the moment an issue, comment, or project updates.
How Webhooks Work
┌──────────┐ event happens ┌──────────┐ HTTPS POST ┌──────────────┐
│ Linear │ ────────────────► │ Webhook │ ──────────────► │ Your server │
│ workspace│ (issue created) │ delivery │ JSON payload │ /linear-hook│
└──────────┘ └──────────┘ └──────┬───────┘
│
Reply HTTP 200 quickly
Everyday Comparison
Imagine waiting for a parcel. You can walk to the front door every five minutes and check. A doorbell saves the effort, because the courier rings when the parcel arrives. Polling through the API resembles the repeated walks. Webhooks resemble the doorbell.
Create a Webhook
- Open Settings > API.
- Find the Webhooks section and click New webhook.
- Enter the public HTTPS address of your endpoint.
- Choose one team or all public teams.
- Select the resource types to receive, such as Issues, Comments, or Projects.
- Save the webhook and copy the signing secret.
Admin access is required for workspace-level webhook settings.
Read the Payload
Linear sends a JSON body with a POST request. The body describes what changed.
{
"action": "update",
"type": "Issue",
"createdAt": "2026-06-20T10:15:30.000Z",
"url": "https://linear.app/acme/issue/ENG-204",
"data": {
"id": "a1b2c3",
"title": "Fix login error",
"priority": 2
}
}| Field | Meaning |
|---|---|
| action | What happened: create, update, or remove |
| type | The kind of object, such as Issue or Comment |
| data | The current state of the object |
| url | A link to the object in Linear |
| createdAt | The time of the event |
Verify the Sender
Anyone can post to a public address, so verify each request. Linear signs the raw request body with your webhook secret using HMAC-SHA256 and sends the result in the Linear-Signature header. Compute the same signature on your server and compare the two values. Reject the request when they differ.
const crypto = require("crypto");
function isValid(rawBody, signature, secret) {
const hash = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return hash === signature;
}Use the raw body bytes for the calculation. Parsed and re-encoded JSON can change the text and break the match.
Respond Correctly
Return an HTTP 200 status quickly. Linear treats slow or failed responses as errors and retries delivery a few times. Place heavy work in a background queue and respond first.
Handle Retries Safely
A retry can deliver the same event twice. Store a delivery identifier or the object version, and skip events you already processed. This habit is called idempotency.
Practical Uses
- Post a message to a chat channel when a bug receives Urgent priority.
- Copy issue data into a reporting database.
- Start a build pipeline when an issue reaches a chosen status.
- Update a customer-facing status page when a project completes.
Security Checklist
- Serve the endpoint over HTTPS.
- Store the signing secret in environment variables, not in code.
- Verify every signature before reading the payload.
- Log failures so you can spot delivery problems early.
Test Your Webhook
Build and test in small steps. Start with a simple endpoint that logs incoming requests. Create a test issue in Linear and confirm that the payload arrives. Add signature checks after that, and build the business logic last. A local tunnel tool can expose a development machine to the internet during testing.
Debug Failed Deliveries
Open the webhook settings page to review recent delivery attempts and responses. Common causes include wrong addresses, expired certificates, and server errors. Fix the cause and create another test event.
Choose Events Carefully
Subscribe only to the resource types you need. Fewer events mean less traffic, lower cost, and simpler code.
