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 awebhook_url. Optionally include a webhook_secret to enable HMAC signature verification.
webhook_url(required whendelivery_typescontainswebhook): 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, theX-Webhook-Signatureheader 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 HTTPPOST 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 awebhook_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 generatedv1: 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:
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 whoset 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.
Responding to webhooks
Your endpoint should return an HTTP2xx 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
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_secretand verify theX-Webhook-Signatureheader 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
2xxas 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 theissueCreate 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>.