# Webhooks

> Signed HTTP POSTs when things happen: lead created, conversation ended, action run. HMAC-SHA256 signatures with timing-safe verification.

Webhooks push events to your systems in real time. Add one under **Settings → Integrations → Webhooks**: an endpoint URL, an optional signing secret, and the events you want (or `*` for all). Webhooks are workspace-wide.

## Events

| Event | Fires when |
| --- | --- |
| `lead.created` | A visitor submits the in-chat lead form / the lead tool captures. |
| `conversation.ended` | A conversation is closed or resolved. |
| `action.run` | A custom action/tool runs. |

Workflow webhook steps are separate and more flexible — any URL, any payload, per-flow — see [Steps & nodes](/docs/workflows/steps). Post-call webhooks fire from the receptionist with the call summary.

## Payload envelope

```json
{
  "event": "lead.created",
  "data": {
    "leadId": 123,
    "agentId": 1,
    "fields": { "name": "Jane Doe", "email": "jane@example.com", "phone": "+1 555 0100" }
  },
  "ts": 1717800000000
}
```

## Verifying the signature

With a signing secret set, each request carries `X-OpenAgent-Signature: sha256=<hex>` — an HMAC-SHA256 of the **raw body**. Recompute and compare timing-safely:

```javascript
const crypto = require('crypto');

function verify(rawBody, header, secret) {
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from(header || ''), b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}
```

> **RESPOND FAST:** Return 200 quickly and do slow work (CRM sync, emails) asynchronously. Delivery is best-effort and non-blocking on OpenAgent's side.
