Bringing leads and stages from your CRM into the center through the generic webhook
Not every system has a ready connector — your own CRM, the automated spreadsheet, the agency’s system. The generic webhook is their door: a small contract (event, e-mail, phone, when, free data), and the lead enters the same timeline as the pixel and Hotmart. This is the contract and the mistakes it prevents.

Hotmart, Meta Ads, Google Ads, forms: they have connectors. The system where your sales team works often does not — it is a smaller CRM, a WhatsApp automation, an in-house system. And it is exactly there that the missing part of the story happens: who replied, who talked, who bought outside.
The generic webhook is the door for that. It knows nothing about your system; it knows how to receive an event with identity and place it on the right person — which is the job of centralized leads. In an account we follow, the CRM sends 56 thousand events a month through that path — more than any source other than the pixel — and each one matches the lead the ad brought.
The contract
{
"event": "crm.opportunity.client_replied",
"email": "person@example.com",
"phone": "+5511999990000",
"occurred_at": "2026-09-11T14:32:10-03:00",
"data": {
"produto": "Mentoria Fluxo",
"pipeline": "Evergreen",
"etapa_de": "Base",
"etapa_para": "Replied",
"vendedor": "ana-paula",
"oportunidade_id": "op_18271"
}
}- event: the event name, in three parts (system.object.action). It is what the audience, the journey and the Meta delivery will filter on.
- email and phone: the identity. At least one. It is what matches the lead the pixel created — and the phone needs the country code.
- occurred_at: when it happened, not when it was sent. Without it the event gets the arrival time, and yesterday’s resend lands on today.
- data: what only your system knows. It goes whole into the timeline, and it is what makes the filter “only product X” work.
The data block is the free part of the contract, and the one that decides the value. A CRM that sends only the event without the product delivers a lead that cannot be filtered.
Authentication and redelivery
Each webhook source has a key in the URL and an HMAC signature of the body. A request without a valid signature is refused — an open endpoint would be a door to invent leads. And the same event resent (the CRM tried twice, the network failed halfway) needs a deduplication key: the opportunity id plus the stage is usually enough. Without it, “replied” enters twice and the conversion that goes to Meta is counted double.
What it becomes afterwards
- Timeline: the event appears on the person’s profile, next to the ad click and the Hotmart purchase — it is what makes the story whole.
- Conversion to Meta: a delivery filters “crm.opportunity.two_way_interaction” for product X and sends it as a custom event via CAPI, with the CRM’s identity (100% phone).
- Audience: “replied and got no proposal within 3 days” is a rule over two events from the same CRM.
- Question to the AI: “how many leads from campaign Y replied this week” crosses the CRM event with the origin the pixel recorded.
Mistakes we saw in production
- 01Sending the send time as occurred_at. A batch reprocess puts a thousand events in the same minute.
- 02Phone without country code. “11 99999-0000” does not match “+5511999990000” — and the lead becomes a duplicate.
- 03Event name different from what was configured in the filter. The system’s panel says “compra_aprovada”, the payload says “order_approved”; a filter on one never sees the other. Always look at the REAL payload before configuring.
- 04Empty data block. The event enters, but there is no way to separate products — and the Meta delivery sends the wrong product’s conversion.
In CrazyLeads the webhook source receives this contract with a per-source key and HMAC signature, extracts identity, deduplicates by key, stores the whole data block on the timeline, and offers the catalog of events and fields MEASURED from what arrived — so the delivery, the audience and the AI filter on what exists, not on what is assumed.