Zapier
This follows the three moves in How every recipe works. Zapier is a good middle layer when your CRM can’t send or receive webhooks itself.
Zap 1: send new leads
Section titled “Zap 1: send new leads”Start the Zap with your CRM’s “New contact” (or “New lead”) trigger. Then add Webhooks by Zapier > Custom Request:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://v2-api.callview.ai/api/v1/external/leads |
| Data | The JSON below, with your CRM’s fields mapped in |
| Headers | Authorization = Bearer cs_live_..., Content-Type = application/json, Idempotency-Key = zap- plus the contact’s ID |
{ "campaign_id": "7c1f2b9e-4a3d-4e8f-9b21-5d6a7e8f9a01", "external_id": "<contact ID>", "phone": "<phone>", "name": "<full name>", "email": "<email>", "consent": { "source": "web_form", "agreed_at": "<created date, ISO 8601>", "url": "https://example.com/quote" }, "call_now": true}Use Custom Request rather than the simpler POST action: it sends your JSON exactly as written, and CallView refuses fields it doesn’t know.
Zap 2: write outcomes back
Section titled “Zap 2: write outcomes back”- Start with Webhooks by Zapier > Catch Raw Hook, and copy the address it gives you.
- Point a CallView webhook endpoint at it, with
"events": ["call.completed"]. Then send a sample withPOST /webhook_endpoints/{id}/testso Zapier has data to map. - We recommend a Code by Zapier step next, to check the signature with the Node or Python code. Give it the raw body and the
CallView-Signatureheader from the trigger, and stop the Zap if they don’t match. - If your CRM words outcomes differently, a Formatter step can translate
outcome. - Finish with your CRM’s “Find contact” by
data.object.lead.external_id, then “Update contact” withdata.object.outcome,data.object.noteanddata.object.handled_by.name.
Zapier may retry a step that times out, and we may send an event twice. If double notes would bother you, add a Filter step that skips an event id you’ve already stored.