Skip to Content
Elido is in closed beta — APIs are stable but rate-limits and quotas may change before GA. Request access →
Webhooks

Webhooks

Webhooks let your systems react to changes in Elido without polling. Two endpoint kinds:

  • Event endpoints — subscribe to specific event types (link.created, member.invited, etc.)
  • SIEM endpoints — firehose: every event in the workspace, plus the full audit-log stream as audit.event payloads

Creating an endpoint

From Settings → Webhooks, or via API:

curl -X POST https://api.elido.app/v1/webhooks/workspaces/1/webhooks \ -H "Authorization: Bearer $ELIDO_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://hooks.example.com/elido", "events": ["link.created", "link.deleted"], "kind": "event" }'

Response includes a one-time secret:

{ "endpoint": { "id": 7, "url": "...", "events": [...] }, "secret": "whsec_a1b2c3d4..." }

Save the secret now — it’s never returned again. Use it to verify signatures on incoming deliveries.

Verifying signatures

Every delivery carries:

X-Webhook-Signature: v1=4f8a... X-Webhook-Timestamp: 1735689600 X-Webhook-Event: link.created X-Webhook-Delivery: 12345

Compute HMAC-SHA256(secret, "{timestamp}.{raw_body}") and compare against the value after v1= in constant time. Reject deliveries older than 5 minutes (now - timestamp > 300).

import { createHmac, timingSafeEqual } from "node:crypto"; function verify(secret: string, headers: Headers, rawBody: string) { const sig = headers.get("X-Webhook-Signature")?.replace(/^v1=/, ""); const ts = headers.get("X-Webhook-Timestamp"); if (!sig || !ts) return false; if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false; const expected = createHmac("sha256", secret) .update(`${ts}.${rawBody}`) .digest("hex"); return timingSafeEqual(Buffer.from(sig), Buffer.from(expected)); }

Retries

Failed deliveries (anything that’s not 2xx) retry on exponential backoff: 1 minute, 5 minutes, 15 minutes. After 3 attempts the delivery is marked failed.

You can manually re-arm a failed (or already-delivered) attempt from Webhooks → endpoint → Retry, or via:

curl -X POST \ https://api.elido.app/v1/webhooks/workspaces/1/webhooks/7/deliveries/12345/retry \ -H "Authorization: Bearer $ELIDO_TOKEN"

SIEM mode

A SIEM-kind endpoint receives every event in the workspace, regardless of the per-event subscription filter. That includes both operational events (link.created, member.invited, …) and the audit-log firehose (audit.event).

Every audit-relevant action (BAA signed, member role changed, API key revoked, …) emits an audit.event envelope:

{ "type": "audit.event", "workspace_id": 1, "data": { "kind": "member.role_changed", "target_type": "member", "target_id": 42, "actor_user_id": 7, "ip": "1.2.3.4", "user_agent": "...", "metadata": { "from": "viewer", "to": "admin" }, "recorded_at": "2026-05-01T12:00:00Z" }, "timestamp": "2026-05-01T12:00:00Z" }

Your SIEM ingester (Splunk HEC, Datadog Logs, custom relay) is responsible for translating into its native format.

Available event types

EventWhen
link.createdA new link is created
link.updatedA link’s destination, slug, or rules change
link.deletedA link is archived or hard-deleted
workspace.createdA new workspace is provisioned
workspace.updatedWorkspace settings change
member.invitedSomeone is invited
member.removedA member is removed (or leaves)
audit.eventAny audit-log entry — see SIEM mode above