CRM Webhook
Endpoint: POST /webhooks/crm/lead
Accepts lead change events from the CRM (or from Make.com as a proxy). The payload is matched to our lead by crm_lead_id (looked up in Leads first, then in LeadSubmissions for follow-up leads). When a match is found, the event is stored in LeadCrmActivity and exposed in the lead detail API and dashboard timeline.
Authentication
Requires CRM_WEBHOOK_SECRET (or CRM_CALLBACK_SECRET if CRM_WEBHOOK_SECRET is not set). Send via:
Authorization: Bearer <secret>, orX-API-Key: <secret>
Requests without a valid secret receive 401 Unauthorized. If neither secret is configured, the endpoint returns 503 Service Unavailable.
Request
- Method:
POST - Content-Type:
application/json - Body:
{
"crm_lead_id": "crm-abc-456",
"event_type": "status_changed",
"status": "qualified",
"updated_at": "2026-03-05T10:00:00Z"
}| Field | Type | Required | Description |
|---|---|---|---|
crm_lead_id | string | Yes | CRM lead ID (must match Leads.CrmLeadId or LeadSubmissions.CrmLeadId). |
event_type | string | No | Event type (e.g. created, updated, status_changed). Default: updated. |
| (any) | — | No | Additional fields are stored as JSON in LeadCrmActivity.PayloadJson. |
The full request body is stored in PayloadJson so the dashboard or downstream consumers can use it.
Lookup behaviour
- Look up Leads by
CrmLeadId. If found, use that lead’s row ID forLeadCrmActivity.LeadId. - If not found, look up LeadSubmissions by
CrmLeadId(most recent bySubmittedAt). If found, use that submission’sLeadIdforLeadCrmActivity.LeadId. - If no match, the webhook returns
200 OKwithstored: falseso the CRM does not retry; the event is logged for debugging.
Response
200 OK — Event stored:
{
"ok": true,
"stored": true,
"lead_id": 123
}200 OK — No matching lead/submission (event not stored):
{
"ok": true,
"stored": false,
"reason": "No matching lead or submission for crm_lead_id"
}400 Bad Request — Missing or invalid crm_lead_id, or invalid JSON.
401 Unauthorized — Missing or invalid secret.
500 Internal Server Error — Database error while inserting.
503 Service Unavailable — CRM webhook secret not configured.
Integration (CRM or Make.com)
- In the CRM (or Make.com), configure a webhook or HTTP request to fire when a lead is created, updated, or status-changed.
- URL:
https://<your-worker>/webhooks/crm/lead - Method: POST
- Headers:
Authorization: Bearer <CRM_WEBHOOK_SECRET>(orCRM_CALLBACK_SECRET) orX-API-Key: <secret> - Body: Include at least
crm_lead_id; addevent_typeand any other fields as needed. The entire body is stored for the lead’s activity timeline.
CRM activity is returned by GET /analytics/leads/:id in the crm_activity array and shown in the dashboard lead detail timeline with a “CRM” label.