Skip to main content
Webhooks deliver monitoring alerts as HTTP POST requests to an endpoint you control, instead of (or in addition to) email or Slack. This makes it easy to pipe alerts into a custom dashboard, trigger downstream automation, or store them in your own database. When a development matches one of your monitoring views, the matched event is serialized as JSON and POSTed to your configured URL. Each request can be signed with an HMAC signature so you can verify its authenticity.

Setting up a webhook

Webhooks are configured in the Intel app, not through the API: when you create or edit a monitoring view, its alert settings are where you enable webhook delivery and set the URL and secret. Webhook delivery is enabled per monitoring view by creating or updating an alert policy with a webhook_url. Optionally include a webhook_secret to enable HMAC signature verification.
  • webhook_url (required when delivery_types contains webhook): the HTTP(S) endpoint to POST to.
  • webhook_secret (optional): a shared secret used to compute the HMAC signature. Set one so your endpoint can verify request authenticity. If omitted, the X-Webhook-Signature header is not included.
Webhooks are only delivered for the immediately cadence. A policy with daily or weekly cadence will not dispatch to webhook endpoints even if webhook is listed in delivery_types and a webhook_url is set.

Request format

Each webhook is delivered as an HTTP POST with the following headers: The request body is a JSON envelope. Optional fields that aren’t set are omitted entirely from the JSON rather than sent as null. The example below shows a fully populated payload:

Envelope fields

Data fields

latest_development fields

Verifying signatures

When you provide a webhook_secret, every delivery includes an X-Webhook-Signature header. Verify it on every incoming request to confirm the webhook is authentic and untampered.

Header format

  • t: the Unix timestamp (seconds) at which the signature was generated
  • v1: the HMAC-SHA256 signature as a hex string

Computing the expected signature

The signed payload is the concatenation of the timestamp, a literal ., and the raw request body:
Compare your computed expected_sig against the v1 value from the header using a constant-time comparison. If they match, the request is authentic.

Rejecting stale signatures

A valid HMAC alone is not enough. Without a freshness check, an attacker who captures a legitimate webhook could replay it indefinitely. Reject any request whose t timestamp is more than a small tolerance away from your server’s current time. A tolerance of 5 minutes comfortably covers network delay, clock skew, and the retry window described in Retries. The helpers below combine both checks: they parse the header defensively (returning false on any missing or malformed component), enforce the timestamp tolerance, and then compare the HMAC in constant time.
Always verify against the raw request body bytes. If your framework re-serializes the JSON before you receive it, the bytes will not match what was signed and verification will fail.

Responding to webhooks

Your endpoint should return an HTTP 2xx status code to acknowledge successful receipt. The HTTP client has a 30-second transport timeout, and each delivery attempt has a 1-minute overall timeout. Slow or non-2xx responses may trigger retries. Return 200 OK quickly after durably queuing the alert for processing on your side, rather than doing heavy work synchronously.

Retries

When a delivery fails with a retryable status code, network error, or timeout, it is automatically retried with exponential backoff:
  • Maximum attempts: 5
  • Initial interval: 1 second
  • Backoff coefficient: 2x
  • Maximum interval: 5 minutes
Non-retryable 4xx responses (excluding 429) are not retried. If your endpoint returns 400 Bad Request, the delivery is permanently marked as failed.

Best practices

  • Always set a webhook_secret and verify the X-Webhook-Signature header on every request, including the timestamp freshness check that prevents replay attacks.
  • Use HTTPS for your webhook URL. Plain HTTP endpoints are accepted but strongly discouraged.
  • Make your handler idempotent. Retries reuse the same envelope id; use it as an idempotency key to avoid double-processing the same event.
  • Respond quickly. Return 2xx as soon as you have durably queued the event; do downstream processing asynchronously.
  • Treat the body as authoritative. Do not trust query strings or other unsigned inputs.

Example: creating tickets in Linear

This walkthrough builds a webhook handler that receives a monitoring alert, verifies its signature, acknowledges receipt, and creates a Linear issue in the background. The same scaffolding works for any downstream destination: swap the Linear call for Slack, an on-call tool, an internal API, or a queue. The handler does five things in order:
1

Capture the raw body

Signatures are computed over raw bytes, not re-serialized JSON.
2

Verify the signature

Check the X-Webhook-Signature header before doing anything else.
3

Acknowledge immediately

Return 200 OK so the sender isn’t waiting on Linear’s response.
4

Hand off to a background worker

Process the envelope asynchronously.
5

Map and post

Translate the alert into a Linear issueCreate mutation.

The server

Instead of running a server, you can also use no-code tools such as Zapier or n8n to receive and transform these requests.
verifyWebhookSignature and verify_webhook_signature are the helpers from Verifying signatures above.

Transforming and posting to Linear

Linear exposes a GraphQL API; new issues are created with the issueCreate mutation. The transform takes a monitoring_event envelope and produces an IssueCreateInput, mapping the development title to the issue title, building a Markdown description from the view, asset list, and development summary, and translating importance to Linear’s priority enum. Two pieces of config are needed: a Linear API key for the Authorization header, and the target team ID.
Linear personal API keys are passed directly in the Authorization header (no Bearer prefix). OAuth access tokens use Authorization: Bearer <token>.
Because failed deliveries are retried, the same envelope can arrive more than once. To avoid duplicate Linear issues, dedupe on envelope.id: store seen IDs in a short-TTL cache, or include the ID in the issue description and search before creating.