Skip to main content

Connect Heilo to your CRM

Four steps to connect Heilo to any CRM — using Zapier, Make, or any other tool that supports webhooks.

After every call, Heilo sends a notification with the call details to an address you choose. This guide shows how to connect Heilo to any CRM using Zapier or Make — no code, in 15–20 minutes.

It’s a universal path that works with any CRM supported by Zapier or Make. Dedicated step-by-step recipes for Pipedrive, HubSpot, and Zoho CRM are included below. One-click Zapier/Make templates are still on the roadmap — until then, each recipe walks you through the last step (saving to your CRM) manually.

1Create a new Zap in Zapier

The “Webhooks by Zapier (Catch Hook)” trigger generates an address that Heilo will send events to.

  1. Sign in to your Zapier dashboard
  2. Create Zap → Choose Trigger → “Webhooks by Zapier”
  3. Event = “Catch Hook” → Continue
  4. Zapier shows an address like https://hooks.zapier.com/hooks/catch/… — copy it

2Paste the address into Heilo as a webhook subscription

Heilo verifies the address — your Zapier endpoint responds automatically. After activation, every call is sent to this address.

  1. Go back to Settings → Integrations in Heilo
  2. Click “Add subscription”
  3. Paste the Zapier address into the “Endpoint URL” field, choose the event types (completed call + outbound call attempt) and click “Create + handshake”
  4. The status should change to “Active”. Copy the signing_secret (shown once)

3Send a test event

Heilo sends a test event with the full set of data from a completed call (sample data: Jan Kowalski / plastering / Warsaw) — in Zapier you’ll see every field you’ll get in real events. Map once, and it works for both the test and real calls.

  1. In Heilo, click the “Test” icon next to your subscription
  2. Back in Zapier, go to the trigger step → “Test trigger” → you should see the full data
  3. Check that you can see the call data — the caller’s number, name, summary and recording link
  4. Continue → move on to the action step (your CRM)

4Set up the save in your CRM

In your tool (Zapier or Make) add actions for your CRM — for example Pipedrive, Zoho CRM, Notion or Airtable. For sales workflows this is usually three steps: (1) find or create a contact by phone number, (2) create or update a lead/deal, (3) attach an activity, task or note.

Heilo fieldMap to CRM
data.call_idID / reference field
data.customer_phone_e164Contact phone (“Phone” / “Primary Phone”)
data.transcript_processed.caller_nameContact name (if Heilo detected it)
data.transcript_processed.summaryNote body or activity description
data.transcript_processed.service_neededActivity subject or deal title
data.transcript_processed.subjectLead/deal title (best fallback for service_needed)
data.transcript_processed.lead_scorePriority, label or qualification filter
data.transcript_processed.preferred_dateFollow-up due date or expected close date
data.transcript_processed.client_cityContact city / address field
data.transcript_processed.client_addressContact street address
data.transcript_processed.services_matchWhether the request matches your offer (true/false) — for qualification
data.transcript_processed.additional_detailsExtra details from the call → note / description
data.recording_urlA URL field (e.g. “Recording link”)
data.durationActivity duration (in seconds)

The data.outbound_lifecycle field appears only in call.outbound.attempted and call.failed events — it is not present in call.completed.

Recipes for specific CRMs

Below are CRM-specific configurations. The generic webhook gives you the call data; this section shows how to turn it into a contact, lead/deal and activity in a specific CRM.

Pipedrive: contact + lead/deal + activity

Target outcome: after a completed call, Pipedrive finds or creates a person, creates a sales lead/deal and attaches an activity with the summary and recording link.

Use Lead if calls should first land in Leads Inbox for qualification. Use Deal if every qualified call should enter the pipeline immediately.

Zapier
  1. Trigger: Webhooks by Zapier → Catch Hook. Keep the Heilo subscription in permissive mode.
  2. Filter by Zapier: allow event_type = call.completed; during setup also allow webhook.test (or filter by data._test = true).
  3. Pipedrive → Find or Create Person. Search by Phone Numbers = data.customer_phone_e164, and set Person Name from caller_name or the phone number.
  4. Pipedrive → Create Lead or Find or Create Deal. Set the title from subject, with service_needed as fallback.
  5. Pipedrive → Create Activity. Attach it to Lead ID or Deal ID, then put summary, recording_url, transcript_original and call_id in Note/Public Description.
Make
  1. Trigger: Webhooks → Custom webhook. The scenario must be active and run when data arrives.
  2. Add a filter after the webhook: event_type = call.completed; while mapping test data, also allow webhook.test (or filter by data._test = true).
  3. Pipedrive CRM → Search Persons by data.customer_phone_e164. If there is no result, create a Person with that phone and caller_name or the phone number as the name.
  4. Pipedrive CRM → Search Leads or Search Deals for that person. If there is no open opportunity, create a Lead or Deal.
  5. Pipedrive CRM → Create Activity or Create Note. Attach it to the lead/deal/person and store summary, recording_url and call_id.
Heilo fieldPipedrive field / actionUse
event_typeFilter / RouterProcess call.completed; use webhook.test only for field mapping.
data.customer_phone_e164Person → Phone NumbersPrimary field for contact lookup and deduplication.
data.transcript_processed.caller_namePerson → Person NameIf empty, use the phone number as a safe fallback name.
data.transcript_processed.subjectLead/Deal → TitleBest opportunity title; fall back to service_needed.
data.transcript_processed.service_neededLead/Deal → Title or custom fieldInquiry category; useful for pipeline routing or labels.
data.transcript_processed.summaryActivity/Note → Note or Public DescriptionShort call description visible on the opportunity.
data.transcript_processed.lead_scoreLead label / priority / filterFor example, create a lead/deal only from 7/10 or send lower scores to review.
data.transcript_processed.preferred_dateExpected close date or activity due dateUse when the customer mentioned a deadline or preferred follow-up date.
data.transcript_processed.client_cityPerson → Address (city) or custom fieldCustomer city; handy for segmentation or a regional pipeline.
data.transcript_processed.client_addressPerson/Organization → AddressFill the person/organization address when the caller provided it.
data.transcript_processed.services_matchFilter / Lead labelfalse = request outside your offer; skip the deal or flag it for rejection.
data.transcript_processed.additional_detailsActivity/Note → NoteExtra details from the call; append them to the activity body.
data.recording_urlActivity/Note → Recording linkPlayback link; may stop working after the call is deleted for GDPR retention.
data.call_idCustom field → Heilo Call IDIdempotency key. Prevents a second CRM record for the same call.
data.durationActivity durationHeilo sends seconds; convert if your Pipedrive field expects a time format.

Conditions for correct pairing

  • Do not enable strict mode for Zapier/Make — their webhook endpoints return standard 2xx responses but do not echo the challenge.
  • Do not mix event types without a filter: call.outbound.attempted does not include the full transcript or recording.
  • Add a Pipedrive custom field named Heilo Call ID and store data.call_id there to avoid duplicates.
  • When updating an existing lead/deal, first search for an open opportunity for the person, and create a new one only if none exists.
HubSpot: contact + deal + note

Target outcome: after a completed call, HubSpot finds or creates a contact by phone number, creates a deal and logs a note with the summary and recording link.

Deduplication trap: Zapier's Create or Update Contact matches existing contacts by e-mail only. Heilo events carry a phone number and often no e-mail, so that action creates a duplicate contact on every call. Always search by the phone property first and create a contact only when the search finds nothing.

Zapier
  1. Trigger: Webhooks by Zapier → Catch Hook. Keep the Heilo subscription in permissive mode.
  2. Filter by Zapier: allow event_type = call.completed; during setup also allow webhook.test (or filter by data._test = true).
  3. HubSpot → Find Contact. Set the search property to Phone Number and map data.customer_phone_e164; enable the option to create the contact when nothing is found, with caller_name or the phone number as the name. Do not use Create or Update Contact here — it matches by e-mail.
  4. HubSpot → Create Deal. Set Deal Name from subject (service_needed as fallback), pick Pipeline and Deal Stage, and associate the deal with the contact.
  5. HubSpot → Create Engagement (type Note). Associate it with the contact and deal, and put summary, recording_url, transcript_original and call_id in the note body.
Make
  1. Trigger: Webhooks → Custom webhook. The scenario must be active and run when data arrives.
  2. Add a filter after the webhook: event_type = call.completed; while mapping test data, also allow webhook.test (or filter by data._test = true).
  3. HubSpot CRM → Search for Contacts by the phone property = data.customer_phone_e164. If there is no result, create the contact with Create a Contact (that phone plus caller_name or the phone number as the name).
  4. HubSpot CRM → Create a Deal. Set Deal Name from subject, pick Pipeline and Deal Stage, and associate the deal with the contact.
  5. HubSpot CRM → Create an Engagement (type Note). Link it to the contact and deal and store summary, recording_url and call_id.
Heilo fieldHubSpot field / actionUse
event_typeFilter / RouterProcess call.completed; use webhook.test only for field mapping.
data.customer_phone_e164Contact → Phone NumberPrimary lookup key. Store phones in HubSpot in E.164 format — the phone search matches exact values, not formatting variants.
data.transcript_processed.caller_nameContact → First Name / Last NameIf empty, use the phone number as a safe fallback name.
data.transcript_processed.subjectDeal → Deal NameBest opportunity title; fall back to service_needed.
data.transcript_processed.service_neededDeal → Deal Name or custom propertyInquiry category; useful for pipeline routing or labels.
data.transcript_processed.summaryNote → Note bodyShort call description visible on the opportunity.
data.transcript_processed.lead_scoreCustom property / filterFor example, create a lead/deal only from 7/10 or send lower scores to review.
data.transcript_processed.preferred_dateDeal → Close Date or task due dateUse when the customer mentioned a deadline or preferred follow-up date.
data.transcript_processed.client_cityContact → CityCustomer city; handy for segmentation or a regional pipeline.
data.transcript_processed.client_addressContact → Street AddressFill the person/organization address when the caller provided it.
data.transcript_processed.services_matchFilter / deal tagfalse = request outside your offer; skip the deal or flag it for rejection.
data.transcript_processed.additional_detailsNote → Note bodyExtra details from the call; append them to the activity body.
data.recording_urlNote → Recording linkPlayback link; may stop working after the call is deleted for GDPR retention.
data.call_idCustom property → Heilo Call IDIdempotency key. Prevents a second CRM record for the same call.
data.durationCustom property or noteHeilo sends seconds; convert if your HubSpot property expects a different format.

Conditions for correct pairing

  • Do not enable strict mode for Zapier/Make — their webhook endpoints return standard 2xx responses but do not echo the challenge.
  • Do not mix event types without a filter: call.outbound.attempted does not include the full transcript or recording.
  • Do not rely on Create or Update Contact for matching — it deduplicates by e-mail only; always run the phone search first.
  • Add a HubSpot custom property named Heilo Call ID (single-line text) and store data.call_id there to avoid duplicates.
  • When updating an existing lead/deal, first search for an open opportunity for the person, and create a new one only if none exists.
Zoho CRM: contact + deal + note

Target outcome: after a completed call, Zoho CRM finds or creates a contact by phone number, creates a deal and attaches a note with the summary and recording link.

Search contacts by the Phone field (or Mobile, if that is where you store numbers). Heilo sends data.customer_phone_e164 in E.164 format — keep Zoho numbers in the same format, otherwise the search will not match.

Zapier
  1. Trigger: Webhooks by Zapier → Catch Hook. Keep the Heilo subscription in permissive mode.
  2. Filter by Zapier: allow event_type = call.completed; during setup also allow webhook.test (or filter by data._test = true).
  3. Zoho CRM → Find Module Entry in the Contacts module, searching the Phone field by data.customer_phone_e164; enable the option to create the entry when nothing is found. Zoho requires Last Name — use caller_name or the phone number.
  4. Zoho CRM → Create Module Entry in the Deals module. Set Deal Name from subject (service_needed as fallback), pick Stage and link the deal to the contact.
  5. Zoho CRM → Create Module Entry in the Notes module. Put summary, recording_url, transcript_original and call_id in Note Content and relate the note to the deal or contact.
Make
  1. Trigger: Webhooks → Custom webhook. The scenario must be active and run when data arrives.
  2. Add a filter after the webhook: event_type = call.completed; while mapping test data, also allow webhook.test (or filter by data._test = true).
  3. Zoho CRM → Search Objects in the Contacts module with the criterion Phone = data.customer_phone_e164. If there is no result, create the contact with Create an Object (Last Name from caller_name or the phone number).
  4. Zoho CRM → Create an Object in the Deals module. Set Deal Name from subject, pick Stage and link the deal to the contact.
  5. Zoho CRM → Create an Object in the Notes module. Store summary, recording_url and call_id in Note Content and attach the note to the deal or contact.
Heilo fieldZoho CRM field / actionUse
event_typeFilter / RouterProcess call.completed; use webhook.test only for field mapping.
data.customer_phone_e164Contact → PhonePrimary lookup key. Search the Phone field (or Mobile) and keep one number format on both sides — the search matches exact values.
data.transcript_processed.caller_nameContact → Last NameZoho requires Last Name; if caller_name is empty, use the phone number as a safe fallback name.
data.transcript_processed.subjectDeal → Deal NameBest opportunity title; fall back to service_needed.
data.transcript_processed.service_neededDeal → Deal Name or custom fieldInquiry category; useful for pipeline routing or labels.
data.transcript_processed.summaryNote → Note ContentShort call description visible on the opportunity.
data.transcript_processed.lead_scoreCustom field / filterFor example, create a lead/deal only from 7/10 or send lower scores to review.
data.transcript_processed.preferred_dateDeal → Closing Date or task due dateUse when the customer mentioned a deadline or preferred follow-up date.
data.transcript_processed.client_cityContact → Mailing CityCustomer city; handy for segmentation or a regional pipeline.
data.transcript_processed.client_addressContact → Mailing StreetFill the person/organization address when the caller provided it.
data.transcript_processed.services_matchFilter / tagfalse = request outside your offer; skip the deal or flag it for rejection.
data.transcript_processed.additional_detailsNote → Note ContentExtra details from the call; append them to the activity body.
data.recording_urlNote → Note Content (link)Playback link; may stop working after the call is deleted for GDPR retention.
data.call_idCustom field → Heilo Call IDIdempotency key. Prevents a second CRM record for the same call.
data.durationCustom field or noteHeilo sends seconds; convert if your Zoho CRM field expects a different format.

Conditions for correct pairing

  • Do not enable strict mode for Zapier/Make — their webhook endpoints return standard 2xx responses but do not echo the challenge.
  • Do not mix event types without a filter: call.outbound.attempted does not include the full transcript or recording.
  • Add a Zoho CRM custom field named Heilo Call ID and store data.call_id there to avoid duplicates.
  • Zoho rejects records with missing required fields: Contacts need Last Name and Deals need at least Deal Name and Stage (depending on your layout also Closing Date) — map safe fallbacks for them.
  • When updating an existing lead/deal, first search for an open opportunity for the person, and create a new one only if none exists.

Full data structure (reference)

Every notification has the same structure. The fields under “data” depend on the event type — a completed call, for instance, includes the processed transcript. The Heilo-Signature header signs the payload (HMAC-SHA256), so you can verify a request really came from Heilo.

{
  "api_version": "2026-06-15",
  "event_id": "<uuid>",
  "event_type": "call.completed",
  "resource_id": "<call_id>",
  "created_at": "2026-06-03T12:34:56Z",
  "data": {
    "call_id": "...",
    "direction": "inbound",
    "caller_phone": "+48600100200",
    "customer_phone_e164": "+48600100200",
    "duration": 87,
    "recording_url": "https://heilo.io/api/v1/calls/.../recording.mp3?token=...",
    "transcript_processed": {
      "caller_name": "Jan Kowalski",
      "client_address": "ul. Przykladowa 10",
      "client_city": "Warszawa",
      "summary": "...",
      "service_needed": "Tynki gipsowe w mieszkaniu 65m2",
      "subject": "Wycena tynkow - Warszawa, 65m2",
      "lead_score": 7,
      "preferred_date": "2026-06-10",
      "services_match": true,
      "additional_details": "Klient wspomnial o terminie do konca czerwca."
    },
    "transcript_original": "..."
  }
}

Common issues

Verification (handshake) failed after adding the subscription
Your address didn’t confirm within 10 seconds. In Zapier this happens automatically; in Make the scenario must be switched on (and in strict mode you also need a “Webhook response” module). Also check the address has no spaces or “&” characters, fix it, then click “Reverify” on the paused subscription.
Duplicate contacts are being created in my CRM
Connector tools don’t normalise phone formats — “+48 600 100 200” and “+48600100200” look like two different numbers. Heilo already sends the number in E.164 format (the customer_phone_e164 field), so use that one to look up the contact. In Zapier you can also add a “Formatter → Phone Number → E.164” step before the lookup.
The recording link stops working after a while
The link works as long as the call exists and isn’t scheduled for deletion (GDPR). If the call was deleted, the link returns a 410 error. This is by design.
A message about exceeding the operation limit
One Heilo call is usually about 3 operations in the tool (find + create + optional update). Free plans are enough for testing; for higher call volumes consider a paid Zapier or Make plan (Make includes 1000 free operations/month ≈ 330 calls).

Roadmap (v1.1+)

What we're planning for upcoming releases. This list isn't a guarantee — priorities follow your feedback.

  • Dedicated recipes for more CRMs: Salesforce, Bitrix24, Livespace
  • One-click templates (Zapier/Make) for the most popular CRMs
  • Copy-paste deduplication and field-mapping rules
  • More event types to map (e.g. contact created/updated)

Missing your CRM or scenario? Email support@heilo.io — we prioritize by real-world need.

Manage keys and webhooks in the panel

Generate API keys, add webhook subscriptions and watch the delivery log after signing in.