# Linear webhook trigger

> Run a workflow on Linear issue, comment, and project events, optionally scoped to one team, with signature verification.

Source: https://cotera.co/docs/reference/webhooks/linear

---

Run a workflow on Linear activity — an issue is created or updated, a comment is added, a project changes. The event payload becomes the workflow's input.

For behavior shared by every provider (the delivery URL, testing), see the [webhook triggers reference](https://cotera.co/docs/reference/webhooks.md).

## Prerequisites

Linear webhooks are **auto-registered**: Cotera creates the webhook for you over Linear's API, using your connected Linear account (OAuth). Without one, install fails with `linear_credentials_missing`.

## Setup

1. Add a **From an app** trigger and pick **Linear**.
2. Choose the event (see below).
3. Optionally set a **team ID** to scope the trigger to one Linear team. Omit it to receive the event across all teams.
4. Save. Cotera registers the webhook for the event's resource type (Issue, Comment, or Project), pointed at the trigger's unique URL.

Deleting the trigger removes the webhook from Linear.

## Events

The event key is `resource.action` (lower-cased). Linear registers one webhook per resource type and delivers every action for it; Cotera routes each delivery to the trigger whose action matches.

| Event key        | Fires when           | Resource |
| ---------------- | -------------------- | -------- |
| `issue.create`   | An issue is created  | Issue    |
| `issue.update`   | An issue is updated  | Issue    |
| `comment.create` | A comment is created | Comment  |
| `project.create` | A project is created | Project  |
| `project.update` | A project is updated | Project  |

## Payload

The raw Linear webhook delivery is passed through as the workflow input. An `issue.create` delivery looks like:

```json
{
  "action": "create",
  "type": "Issue",
  "createdAt": "2023-07-15T10:30:00.000Z",
  "data": {
    "id": "b1c2d3e4-f5a6-7b8c-9d0e-1f2a3b4c5d6e",
    "title": "Found a bug",
    "description": "Something is broken.",
    "priority": 1,
    "identifier": "ENG-123",
    "url": "https://linear.app/acme/issue/ENG-123",
    "state": { "id": "s1", "name": "Todo", "type": "unstarted" },
    "team": { "id": "t1", "key": "ENG", "name": "Engineering" }
  },
  "url": "https://linear.app/acme/issue/ENG-123",
  "webhookId": "wh_0123456789",
  "organizationId": "org_0123456789"
}
```

| Field                          | Description                                                             |
| ------------------------------ | ----------------------------------------------------------------------- |
| `action`                       | `create`, `update`, or `remove`.                                        |
| `type`                         | The resource type — `Issue`, `Comment`, or `Project`.                   |
| `data`                         | The affected object (issue, comment, or project).                       |
| `updatedFrom`                  | On `update` deliveries, the previous values of the fields that changed. |
| `createdAt`                    | When the event happened.                                                |
| `webhookId` / `organizationId` | The Linear webhook and workspace the event came from.                   |

Update deliveries carry the same shape plus `updatedFrom` (for example `{ "stateId": "s1" }` when an issue's status changed). Comment and project deliveries carry their own `data` objects.

## Signature verification

Linear signs each delivery with the webhook's secret and sends it in the `Linear-Signature` header — an HMAC-SHA256, in hexadecimal, of the raw request body. The secret is generated by Linear when the webhook is created, so there's no per-trigger secret for you to manage. Linear also sends a `Linear-Delivery` header (a unique id used to deduplicate retries). Cotera verifies the signature on every delivery and rejects anything that fails.

