HubSpot integration

Heedify supports HubSpot CRM integration via Workflows, integrated with Microsoft Teams, Teams Phone and the HubSpot CRM API. When a customer calls, Heedify finds their HubSpot contact from the phone number, shows the contact’s name, company and record link in the agent’s Teams call notification, and, when the call ends, logs a call activity on the contact’s HubSpot timeline with the AI summary and the full transcript.

This page is a step-by-step guide. It assumes you know the basics of Workflows and Call Flows.

  1. How it works
  2. Before you start
  3. Step 1 — Create a HubSpot service key
    1. If your account has no Service keys menu
  4. Step 2 — Workflow 1: find the caller in HubSpot
  5. Step 3 — Workflow 2: log the call in HubSpot
    1. Variables used in this step
  6. Step 4 — Attach the workflows and turn on transcription
  7. Step 5 — Show the HubSpot contact to the agent
  8. Step 6 — Test the integration
  9. Troubleshooting

How it works

The integration uses two workflows and the call flow’s Agent context:

When What happens Configured in
The call reaches Heedify (call connected) Workflow 1 searches HubSpot for a contact with the caller’s number and stores the contact id, name and company as variables. This runs while the greeting plays. Workflows
An agent’s Teams starts ringing The notification shows the HubSpot contact name and company; after pickup, the Teams side panel shows the details and a link to the HubSpot record. Microsoft Teams client only. Call flow → Agent context
The call ends (call ended) Workflow 2 creates a Call activity on the contact in HubSpot, with the AI summary and the transcript. Workflows
call connected ──► POST api.hubapi.com/crm/v3/objects/contacts/search   (caller's number)
                   stores $HUBSPOT_CONTACT_ID$, $HUBSPOT_FIRSTNAME$, $HUBSPOT_LASTNAME$, $HUBSPOT_COMPANY$
                                   │
agent rings ─────► Teams shows "$HUBSPOT_FIRSTNAME$ $HUBSPOT_LASTNAME$" + link to the HubSpot record
                                   │
call ended ──────► POST api.hubapi.com/crm/v3/objects/calls
                   summary + transcript, associated with $HUBSPOT_CONTACT_ID$

Before you start

  • HubSpot: a Super Admin user, or a user with the Developer tools access permission, to create the service key.
  • HubSpot contacts: phone numbers stored in international format (for example +33612345678) in the Phone number or Mobile phone number property. Heedify receives the caller’s number in this format.
  • Heedify: permission to create Workflows and to edit the Call Flow in the Entity that handles the calls.
  • Summary and transcript: they are produced from the call recording. The call flow needs Enable recording and Enable Transcription turned on (see Step 4). Without them, the call is still logged in HubSpot, but without a summary or transcript.

Step 1 — Create a HubSpot service key

Heedify authenticates to HubSpot with a service key: a key you create in your HubSpot account for API access, which grants only the permissions (scopes) you select. HubSpot recommends service keys over private apps for this kind of single-account integration.

  1. Sign in to HubSpot as a Super Admin, or as a user with the Developer tools access permission.
  2. Go to Development, then in the left sidebar click Keys > Service keys.
  3. Click Create service key in the top right and enter a name, for example Heedify.
  4. Click Add new scope. In the right panel, search for and check these scopes, then click Update:

    Scope Why Heedify needs it
    crm.objects.contacts.read Find the contact that matches the caller’s number.
    crm.objects.contacts.write Create the call activity and attach it to the contact. This is the scope HubSpot requires to create a call.

    No calls or calling transcription scope is needed: the transcript is sent as text in the call notes.

  5. Click Create in the top right, then confirm.
  6. Open the key you created, click Show, then Copy.
  7. Keep the key at hand for the next steps. You will paste it into both workflows.

The key gives read and write access to your HubSpot contacts. Paste it only into the Heedify workflow Headers, never in an email or a chat. Anyone who can open these workflows in Heedify can read it: limit the Workflows permission on this Entity to the administrators who need it.

HubSpot recommends rotating the key every six months. On the key’s page, click Rotate, choose Rotate and expire later, then paste the new key into both Heedify workflows within 7 days, before the old one expires. View logs on the same page lists the requests Heedify made with the key.

If your account has no Service keys menu

Use a private app instead. It works the same way for Heedify: its access token goes in the same header.

  1. Go to Development > Legacy apps, click Create legacy app, then select Private. On older accounts, the screen is under Settings > Integrations > Private Apps.
  2. If HubSpot suggests service keys, check I understand that legacy private apps have limited functionality… and click Continue with legacy private app.
  3. On the Basic Info tab, enter a name. On the Scopes tab, add the scopes listed above, then click Create app.
  4. Open the app, go to the Auth tab, click Show token, then Copy. Use this token wherever this guide says key.

Step 2 — Workflow 1: find the caller in HubSpot

This workflow runs as soon as the call reaches Heedify, searches the HubSpot contact by phone number, and stores the result as variables for the rest of the call.

  1. In Heedify, open Workflows from the sidebar and click Add New Workflow.
  2. Fill in the form:

    Field Value
    Display Name HubSpot — find caller
    Entity The Entity of the call flow that receives the calls.
    Trigger Event call connected
    Action → method POST
    Action → URL https://api.hubapi.com/crm/v3/objects/contacts/search
  3. Under Headers, add two rows:

    Key Value
    Authorization Bearer followed by your key from Step 1 (the word Bearer, a space, then the key)
    Content-Type application/json
  4. Turn on Body (JSON) and paste:

    {
      "filterGroups": [
        { "filters": [ { "propertyName": "phone", "operator": "EQ", "value": "$CALLER_ID_E164$" } ] },
        { "filters": [ { "propertyName": "mobilephone", "operator": "EQ", "value": "$CALLER_ID_E164$" } ] }
      ],
      "properties": ["firstname", "lastname", "company"],
      "limit": 1
    }
    

    The two filter groups mean Phone number or Mobile phone number equals the caller’s number. Heedify replaces $CALLER_ID_E164$ with the caller’s number in international format before sending the request.

  5. Turn on Mapping and add these rows (Key = the variable name, Value = where to read it in HubSpot’s response):

    Key Value
    HUBSPOT_CONTACT_ID results.0.id
    HUBSPOT_FIRSTNAME results.0.properties.firstname
    HUBSPOT_LASTNAME results.0.properties.lastname
    HUBSPOT_COMPANY results.0.properties.company

    results.0 is the first contact found. From now on, these values are available for the rest of the call as $HUBSPOT_CONTACT_ID$, $HUBSPOT_FIRSTNAME$, $HUBSPOT_LASTNAME$ and $HUBSPOT_COMPANY$.

  6. Click Save.

Use call connected, not agent connected. The name shown to the agent is prepared when their Teams starts ringing: a contact looked up at agent connected arrives too late for the agent who answers.

Step 3 — Workflow 2: log the call in HubSpot

This workflow runs when the call is over and creates a Call activity on the HubSpot contact found in Step 2, with the AI summary and the transcript.

  1. Click Add New Workflow again and fill in:

    Field Value
    Display Name HubSpot — log call
    Entity The same Entity as Workflow 1.
    Trigger Event call ended
    Action → method POST
    Action → URL https://api.hubapi.com/crm/v3/objects/calls
  2. Add the same two Headers as in Workflow 1 (Authorization with your key, Content-Type: application/json).
  3. Turn on Body (JSON) and paste:

    {
      "properties": {
        "hs_timestamp": "$nowIso$",
        "hs_call_title": "Inbound call — $QUEUE_NAME$ — $AGENT_NAME$",
        "hs_call_direction": "INBOUND",
        "hs_call_status": "COMPLETED",
        "hs_call_from_number": "$CALLER_ID_E164$",
        "hs_call_body": "Summary: $CALL_SUMMARY$ — Sentiment: $CALL_SENTIMENT$ — Talk time: $CALL_HANDLE_TIME$ s — Transcript: $CALL_TRANSCRIPTION$"
      },
      "associations": [
        {
          "to": { "id": "$HUBSPOT_CONTACT_ID$" },
          "types": [ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 194 } ]
        }
      ]
    }
    
    • hs_call_body is the call notes shown in HubSpot. Keep only what you need: for example, remove the Transcript: part if you only want the summary.
    • associations attaches the call to the contact found by Workflow 1. Keep 194 as is: it is HubSpot’s fixed code for call → contact.
  4. Leave Mapping off and click Save.

Variables used in this step

Variable Value
$nowIso$ Date and time the workflow runs, in ISO format (required by HubSpot as the activity date).
$QUEUE_NAME$ The queue that handled the call.
$AGENT_NAME$ Display name of the agent who answered.
$CALLER_ID_E164$ Caller’s number in international format.
$CALL_HANDLE_TIME$ Talk time, in seconds.
$CALL_SUMMARY$ AI summary of the conversation.
$CALL_SENTIMENT$ positive, neutral, negative or mixed.
$CALL_TRANSCRIPTION$ Full transcript, one line per speaker turn.
$HUBSPOT_CONTACT_ID$ Contact id stored by Workflow 1.

A variable that has no value is sent as written. If transcription is off on the call flow, HubSpot receives the text $CALL_SUMMARY$ instead of a summary. Turn on transcription (Step 4), or remove $CALL_SUMMARY$, $CALL_SENTIMENT$ and $CALL_TRANSCRIPTION$ from the body.

Step 4 — Attach the workflows and turn on transcription

  1. Open Call Flows and edit the call flow that receives the calls.
  2. In the Recording settings, turn on Enable recording, then Enable Transcription (visible once recording is on). See Call Flows → Recording.
  3. Open the Workflows tab and, in Select workflows, pick HubSpot — find caller and HubSpot — log call. Only workflows of the same Entity as the call flow are listed. A call flow accepts up to 3 workflows.
  4. Save the call flow.

Recording, and therefore the summary and transcript, starts when an agent answers. A caller who hangs up in the queue has no summary; for such calls, Workflow 2 logs the call without one.

Step 5 — Show the HubSpot contact to the agent

The call flow’s Agent context tab decides what the agent sees in Microsoft Teams: the ringing notification, then the side panel during the call. Every field accepts the variables stored by Workflow 1.

For now, the agent sees this context only when they answer the call in the Microsoft Teams client. It is not shown in the Heedify Agent Console.

  1. In the same call flow, open the Agent context tab and turn on Call context for the agent.
  2. Fill in the fields:

    Field Value What the agent sees
    Caller name $HUBSPOT_FIRSTNAME$ $HUBSPOT_LASTNAME$ The contact’s name instead of the phone number, in the ringing notification.
    Call subject $HUBSPOT_COMPANY$ → $QUEUE_NAME$ The notification title. Teams shows 48 characters at most.
    Customer record link https://app.hubspot.com/contacts/YOUR_HUB_ID/record/0-1/$HUBSPOT_CONTACT_ID$ A link that opens the contact in HubSpot.
    Side panel lines HubSpot contact: $HUBSPOT_FIRSTNAME$ $HUBSPOT_LASTNAME$ · $HUBSPOT_COMPANY$ A line in the Teams side panel during the call.
    • Replace YOUR_HUB_ID with your HubSpot account ID, shown in HubSpot under your account name in the top-right menu.
    • If your HubSpot account is hosted in Europe, its address starts with app-eu1.hubspot.com: use that host in the link instead of app.hubspot.com.
  3. Optionally, under Additional information, add Label / Value pairs such as Company / $HUBSPOT_COMPANY$. Once you add one pair, your list replaces the default information (flow, queue, waiting time…), up to 10 pairs.
  4. Save the call flow.

When the caller is not found in HubSpot, every field that uses a HubSpot variable is simply left out: the agent sees the phone number and the default information, as without the integration.

Step 6 — Test the integration

  1. In HubSpot, create a test contact with your own mobile number in international format (for example +33612345678).
  2. Call the number of the call flow from that phone and stay on the line during the greeting.
  3. On the agent side, check that the Teams notification shows the contact’s name and company. Answer, talk for a few seconds, then hang up.
  4. Wait about a minute (the summary is generated from the recording after the call), then open the contact in HubSpot: a new Call activity appears in its timeline with the summary and transcript.

Troubleshooting

Symptom Likely cause What to do
The agent sees no HubSpot information at all The agent answers in the Heedify Agent Console. The context is shown only when the call is answered in the Microsoft Teams client.
The agent sees the number, not the name No HubSpot contact has this number in the same format. Store the number in international format (+33…) in Phone number or Mobile phone number.
The agent sees the number, not the name, for some calls only The HubSpot search had not finished when the agent’s Teams started ringing. Keep a greeting or a menu at the start of the call flow: the search runs while it plays.
Nothing works, even for a known contact The workflows use agent connected instead of call connected, or are not attached to the call flow. Check the Trigger Event of Workflow 1 and the call flow’s Workflows tab. If a call connected workflow never runs, open it and click Save again.
No call in HubSpot The caller is not a HubSpot contact, or the key is wrong or expired. Test with a known contact. Check that the Authorization header is Bearer followed by the current key.
No call in HubSpot, key correct The service key is missing a scope. On the key’s page in HubSpot, click Edit and check that both crm.objects.contacts.read and crm.objects.contacts.write are selected. View logs shows whether HubSpot refused Heedify’s requests.
The HubSpot call shows $CALL_SUMMARY$ Transcription is off on the call flow, or the call was not answered by an agent. Turn on Enable recording and Enable Transcription (Step 4).
The link opens HubSpot on the wrong account Wrong Hub ID or host in Customer record link. Copy your Hub ID from HubSpot; use app-eu1.hubspot.com for a European account.

A workflow failure never affects the call: the call is routed and handled normally, only the HubSpot part is skipped.

Works with: Microsoft Teams, Teams Phone, HubSpot CRM API, HubSpot service keys, Workflows, Call Flows, call recording and transcription.