Webhooks
Last Updated: 2026-04-20
Webhooks let Mylla push call and request/customer events to your own server in real time. Use them to sync data to a custom CRM, trigger internal automations, or post messages into your own tools.
Some event names and payload keys still use lead.* and lead for backward compatibility with existing automations. Those payloads are synthesized from the current Customers and Requests data model.
If you don't have a server and just want to connect to a SaaS tool, use the built-in integrations (HubSpot, Zapier, Google Calendar, etc.) instead — see Integrations.
Setting up a Custom Webhook
- Go to Integrations
- Find Custom Webhook → click Connect
- Enter:
- Webhook URL — a publicly reachable HTTPS endpoint on your server (e.g.,
https://api.example.com/mylla/webhook) - Secret (optional but recommended) — a shared string used to sign each payload
- Events — pick which event types you want delivered
- Webhook URL — a publicly reachable HTTPS endpoint on your server (e.g.,
- Save
Mylla immediately sends a test event to verify the endpoint responds with 2xx.
Events
| Event | Fires when |
|---|---|
call.completed | A call finishes (inbound or widget) |
lead.created | A new request/customer payload is captured |
lead.updated | A request/customer payload's status, notes, or fields change |
call.escalated | The agent transfers a caller to a human |
voicemail.received | A caller leaves a voicemail outside business hours |
Payload shape
All payloads are POSTed as JSON:
{
"event": "lead.created",
"timestamp": "2026-04-20T15:32:11.284Z",
"tenant_id": "7f3b...",
"data": {
"lead": {
"id": "lead_abc123",
"name": "Jane Doe",
"phone": "+14155551234",
"email": "jane@example.com",
"reason": "Booking a cleaning",
"status": "new"
},
"call": {
"id": "call_xyz789",
"duration_seconds": 142,
"agent_id": "agent_...",
"recording_url": "https://..."
}
}
}
Field sets per event:
| Event | data contains |
|---|---|
call.completed | call, transcript_url, summary |
lead.created | lead, call |
lead.updated | lead, changes (fields that changed) |
call.escalated | call, escalation (transfer number, reason) |
voicemail.received | call, voicemail_url, transcript |
Headers Mylla sends
| Header | Value |
|---|---|
Content-Type | application/json |
User-Agent | Mylla-Webhook/1.0 |
X-Mylla-Signature | HMAC-SHA256 of the raw body using your secret (only if you set a secret) |
Verifying the signature
If you set a secret, verify every incoming request:
Node.js / TypeScript:
import { createHmac, timingSafeEqual } from 'crypto'
function verify(rawBody: string, signature: string, secret: string) {
const expected = createHmac('sha256', secret).update(rawBody).digest('hex')
const a = Buffer.from(expected)
const b = Buffer.from(signature)
return a.length === b.length && timingSafeEqual(a, b)
}
Python:
import hmac, hashlib
def verify(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
Retries
Mylla retries failed deliveries with exponential backoff:
- Attempt 1 — immediate
- Attempt 2 — after 10 seconds
- Attempt 3 — after 1 minute
- Attempt 4 — after 5 minutes
Anything other than a 2xx response counts as a failure. Respond with 200 as soon as you've accepted the payload — do heavy processing in a background queue.
Requirements
- HTTPS only (HTTP endpoints are rejected)
- Must respond within 30 seconds
- Must return a
2xxstatus code on success
Testing
Click the Custom Webhook integration in Integrations and hit Send Test Event. A payload with event: "test" is sent — useful when bootstrapping your handler.
Disabling
- Integrations → Custom Webhook → Disconnect
All in-flight retries are cancelled immediately.
Zapier as an alternative
If you want to react to the same events without writing code, use the Zapier integration instead. Same event types, no server required.
Permissions
| Action | Super Admin | Admin | Member |
|---|---|---|---|
| Configure Custom Webhook | ✅ | ✅ | ❌ |
| View webhook status | ✅ | ✅ | ❌ |