Skip to main content

Overview

A webhook sends an HTTP POST to a URL you choose whenever something happens in a project. Use it to post to a Slack channel, open a ticket in your own system, or start an automation in Zapier. issue.created fires once per issue, not for every occurrence, so a crash loop doesn’t flood your channel.

Add a webhook

1

Open the settings

In the project, open Settings → Webhooks & Slack and click Add webhook. You need permission to change project settings.
2

Pick a destination

  • Webhook: any https:// URL that is publicly reachable. Lerix signs every request (see below).
  • Slack: an incoming-webhook URL, created in Slack under Apps → Incoming Webhooks. It starts with https://hooks.slack.com/. Lerix posts a formatted message with a link back to the dashboard.
3

Pick the events

Choose at least one of feedback.created, nps.detractor and issue.created.
4

Copy the signing secret

For a generic webhook, the signing secret (whsec_...) is shown once, right after you create it. Store it with your endpoint’s configuration. If you lose it, delete the webhook and add it again to get a new one.
5

Send a test

Click Test to send a webhook.test event. The dashboard shows the status code your endpoint answered, or the error if it couldn’t be reached.
You can pause a webhook without deleting it, and edit its URL or events at any time.

Payload

Every generic webhook request has a JSON body with the same envelope:
And these headers:

data by event

email, externalId and bugId are null when they don’t apply. bugId is set when the same install reported an error just before the feedback.
New fields may be added to data over time. Ignore fields you don’t know rather than rejecting the request.

Verify the signature

Lerix-Signature is an HMAC-SHA256 of the timestamp and the raw body, t + "." + body, keyed with the webhook’s signing secret. Check it before you trust a request:
  1. Split the header on , and read t and v1.
  2. Reject the request if t is more than 5 minutes away from your clock. This stops an old delivery from being replayed.
  3. Compute HMAC-SHA256(secret, t + "." + rawBody) as hex and compare it to v1 in constant time.
Use the raw request body, exactly as received. Parsing the JSON and serializing it again changes the bytes and breaks the signature.
Slack deliveries aren’t signed: Slack’s incoming-webhook URL is itself the secret, so keep it private.

Delivery and retries

  • Lerix waits up to 5 seconds for your endpoint. Answer with any 2xx status quickly, and do slow work after responding.
  • On a network error, a timeout, 429 or a 5xx, Lerix retries up to 3 times, after 2, 10 and 30 seconds. Every attempt is signed again with a fresh timestamp and keeps the same Lerix-Delivery ID.
  • Any other status (for example 400 or 404) is not retried.
  • Redirects aren’t followed.
  • The URL must use https and resolve to a public address. Private, loopback and link-local addresses are refused, both when you save the webhook and when each request is sent.
Deliveries are not guaranteed to arrive in order. Use createdAt in the body if order matters to you.