Elido
Help center

Integrations

Webhooks: subscribe to link and click events

Configure an HTTP endpoint to receive real-time events from Elido — link created, link clicked (aggregated), domain verified, abuse flagged, and more.

Updated 2026-05-15

Webhooks push events from Elido to your server as they happen. Use them instead of polling the API when you need real-time data — typical use cases include syncing link metadata to your CRM, building a custom dashboard, or kicking off a CI pipeline when a link is published.

Add a webhook endpoint#

  1. Dashboard → Webhooks → New endpoint.
  2. Paste the URL we should POST to. It must be HTTPS — we reject plain HTTP at create time.
  3. Pick the event kinds you want. The full list is below.
  4. (Optional) Paste a signing secret, or let us generate one. The secret is shown once; copy it before leaving the page.
  5. Save. We send a test event immediately so you can confirm the endpoint is reachable.

Event catalogue#

The current event kinds. Names follow <resource>.<action> and stay stable across versions.

  • link.created — a new short link was created.
  • link.updated — destination, slug, expiry, or password changed.
  • link.deleted — link was soft-deleted (still recoverable for 30 days).
  • link.clicked.aggregated — every 60 seconds we send the click counts per link for the previous window. We don't deliver per-click events over webhooks (the volume would crush most endpoints) — use the click export for raw event data.
  • domain.verified — a custom domain's DNS check passed.
  • domain.tls_renewed — Caddy renewed the TLS cert for a custom domain.
  • qr.generated — a QR code SVG/PNG was rendered.
  • abuse.flagged — our URL scanner marked a destination as suspicious.
  • member.invited / member.removed — workspace membership changes.

Payload shape#

Every event has the same envelope:

{
  "id": "evt_2c8L9N4M5",
  "type": "link.created",
  "created_at": "2026-05-15T09:42:11.382Z",
  "workspace_id": 4123,
  "data": {
    "link_id": 891234,
    "slug": "spring-2026",
    "destination": "https://acme.com/spring-sale",
    "created_by": "user_5821"
  }
}

id is unique per delivery. Use it for idempotency — if you receive the same id twice (because we retried), skip the duplicate.

Verifying signatures#

We sign every webhook body with HMAC-SHA256 using your endpoint's secret. The signature is in the Elido-Signature header as t=<unix_ts>,v1=<hex>.

To verify in Node:

import { createHmac } from "node:crypto";

function verify(secret: string, body: string, header: string): boolean {
  const parts = Object.fromEntries(
    header.split(",").map((p) => p.split("=")),
  );
  const expected = createHmac("sha256", secret)
    .update(`${parts.t}.${body}`)
    .digest("hex");
  return expected === parts.v1;
}

We include the timestamp in the signed payload to prevent replays. Reject events where |now - t| > 300 seconds.

Retries#

We retry failed deliveries (any non-2xx response, or no response within 10 seconds) with exponential backoff: 30s, 1m, 5m, 30m, 2h, 12h. After 6 failures we mark the endpoint failing and stop retrying that specific event. The endpoint stays subscribed; new events continue to attempt delivery.

Endpoint stays failing for 5 consecutive deliveries → we auto-disable it and email the workspace owner. Re-enable in the dashboard once you've fixed your server.

Delivery log#

Open any webhook in the dashboard to see the last 500 deliveries, with status code, response time, and the request/response body for each. Failed deliveries can be replayed manually from this view.

Local testing#

Use the Elido CLI to forward webhooks to localhost:

npx @elido/cli webhooks forward --url http://localhost:3000/webhooks

The CLI registers a temporary endpoint that lasts until you Ctrl-C, tunnels deliveries to your machine, and prints the request body for each event.

Limits#

  • 20 endpoints per workspace (Pro), 100 (Business).
  • 10 KB max signed payload size. Larger payloads are split — data includes a truncated: true flag and a URL to fetch the full body.
  • 50 events per second sustained per endpoint. Bursts are queued.

Troubleshooting#

Endpoint reports 401 in the delivery log. Your endpoint is verifying signatures with the wrong secret. Compare the secret in Webhooks → Endpoint → Settings against the one your server has stored.

Some events are arriving twice. Either we retried after a slow response, or your endpoint timed out without responding. Use the event id for idempotency.

link.clicked.aggregated counts don't match analytics dashboard. The dashboard is real-time (within 30s of click); the webhook is windowed at 60s. There's also a small (~1%) discrepancy because bots filtered out of the dashboard are still included in raw aggregates until the bot-filter window closes.

Was this helpful?
Need more? Email the team — replies within one working day.Contact support
Webhooks: subscribe to link and click events · Elido