Webhooks
Webhooks enable real-time notifications when events occur in MeetLoyd. Instead of polling the API, receive HTTP callbacks when agents complete tasks, conversations end, or workflows finish.
Why Webhooks?
- Real-time updates -- know immediately when events happen
- Efficient -- no polling required
- Reliable -- automatic retries on failure
- Secure -- signature verification on every delivery
Available Events
The event picker is sourced from the canonical event catalog — the same
vocabulary agents react to — so the authoritative, always-current list is
GET /api/v1/events/catalog. Business events fire as the underlying system acts;
platform/lifecycle events fire from the agent / task / conversation runtime.
Subscribing to an event id outside this catalog is rejected.
CRM
| Event | Description |
|---|---|
crm.lead.created | A new lead/contact was captured |
crm.lead.qualified | A lead crossed the qualification bar (MQL/SQL) |
crm.deal.created | A new opportunity entered the pipeline |
crm.deal.won | A deal was marked closed-won |
crm.deal.lost | A deal was marked closed-lost |
Meetings
| Event | Description |
|---|---|
meeting.booked | A meeting was booked/confirmed |
meeting.rescheduled | A booked meeting moved to a new time |
meeting.cancelled | A booked meeting was cancelled |
meeting.completed | A meeting took place |
Billing
| Event | Description |
|---|---|
billing.subscription.created | A subscription started |
billing.subscription.cancelled | A subscription was cancelled (churn) |
billing.invoice.paid | An invoice was paid |
billing.payment.failed | A payment failed (dunning/at-risk) |
Repositories
| Event | Description |
|---|---|
repo.created | A new repository was created |
repo.pr.opened | A pull/merge request was opened |
repo.pr.merged | A pull/merge request was merged |
repo.deploy.failed | A deploy failed |
Support
| Event | Description |
|---|---|
support.ticket.created | A support ticket was created |
support.ticket.escalated | A ticket was escalated |
support.csat.received | A customer satisfaction response arrived |
Platform & lifecycle
| Event | Description |
|---|---|
agent.run.started | An agent started a run |
agent.run.completed | An agent finished a run |
agent.run.failed | An agent run errored |
agent.created / agent.updated / agent.deleted | Agent CRUD |
task.completed | A task completed |
conversation.created / conversation.started | A new conversation began |
conversation.message | A message was added to a conversation |
tool.executed | An agent executed a tool |
Filtering Events
Narrow a subscription to only the deliveries you care about with an optional
payload filter — a set of key = value conditions matched against the event
payload (every condition must match, or the delivery is skipped). For example, a
webhook on crm.deal.won with the filter stage = enterprise fires only for
enterprise deals. Filters are configured per-webhook in the Add/Edit Webhook
dialog and shown as a chip on the webhook card.
Retry Policy
Failed deliveries are retried automatically with exponential backoff — the delay before retry N is N² seconds (1s, 4s, 9s, …):
| Retry | Delay before it |
|---|---|
| 1st retry (2nd attempt) | 1 second |
| 2nd retry (3rd attempt) | 4 seconds |
| 3rd retry (4th attempt) | 9 seconds |
The number of attempts is the webhook's retry count (default 3, configurable 0–10).
After the final attempt fails, the delivery is marked failed. A delivery fails on an HTTP
status ≥ 400, a request timeout (default 30s, configurable up to 60s), or a network error.
Delivery Headers
Every delivery includes these headers:
| Header | Value |
|---|---|
X-Webhook-Signature | sha256=<hex> — HMAC-SHA256 of the raw request body using your webhook secret |
X-Webhook-Timestamp | ISO 8601 send time |
X-Webhook-Event | The event id (e.g. crm.deal.won) |
X-Webhook-Id | Unique delivery id — use it for idempotency |
Never process a webhook without verifying the X-Webhook-Signature first. This prevents
spoofed requests from being processed.
Creating Webhooks
From the Dashboard
- Go to Settings > Webhooks
- Click + Add Webhook
- Enter your endpoint URL
- Search and select events to subscribe to (grouped by capability)
- (Optional) Add payload filter conditions to narrow which deliveries fire
- Click Create
- Copy the webhook secret for signature verification
Webhook Payload
Every delivery's JSON body has this shape:
| Field | Description |
|---|---|
event | Event id (e.g., crm.deal.won) |
timestamp | ISO 8601 timestamp |
data | Event-specific payload (fields vary by event) |
The unique delivery id for idempotency is the X-Webhook-Id header — not a body field.
Verifying the Signature
Verify every delivery before processing it:
- Read the
X-Webhook-Signatureheader — its value issha256=<hex>. - Compute
HMAC-SHA256(rawRequestBody, webhookSecret)and hex-encode it. - Compare your digest to the hex after
sha256=using a constant-time comparison; reject on mismatch. - Optionally reject deliveries whose
X-Webhook-Timestampis older than a few minutes to limit replay.
Sign over the raw body bytes exactly as received — re-serializing the parsed JSON can change key order or whitespace and break the comparison. (The signature covers the body alone, not the timestamp.)
Managing Webhooks
From the dashboard, you can view all webhooks, update event subscriptions, enable/disable webhooks, rotate secrets, and view delivery history.
Delivery History
Each webhook shows its recent delivery history including timestamp, event type, response status, response body, and duration. Use this to debug failed deliveries.
Testing Webhooks
Send a Test Event
From the webhook detail page, click Send Test to deliver a sample event to your endpoint.
Local Development
Use a tunneling service like ngrok for local development:
- Start your local server
- Run
ngrok http 3000to get a public URL - Use the ngrok URL as your webhook endpoint
- Test with real or sample events
Best Practices
- Verify signatures -- always verify to prevent spoofing
- Respond quickly -- return 200 immediately, process asynchronously
- Handle duplicates -- use the
X-Webhook-Idheader for idempotency; webhooks may be delivered more than once - Monitor health -- set up alerts for high failure rates or elevated latency
- Use specific events -- subscribe only to events you need; avoid subscribing to everything
Next: Explore Tasks for background job execution.