> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pyai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# HubSpot integration

> Post a note with the TL;DR, summary, and next steps on the matching HubSpot contact after every completed call. Private app token setup in two minutes.

The HubSpot integration posts a note on the matching contact after every
completed call: the TL;DR leads, then the summary, next steps, and the call
reference. If no contact matches, the note still posts with the call
reference so nothing is lost.

## What you need

* A **HubSpot private app token** with these scopes:

  * `crm.objects.contacts.read`
  * `crm.objects.notes.write`

  Create it in HubSpot: **Settings → Integrations → Private Apps → Create a
  private app** → Scopes tab → enable the two scopes → create and copy the
  token.

## Connect

1. In PyAI Console, open **Integrations** and find **HubSpot** under CRM.
2. Click **Connect**, paste the token, and pick your events.
3. Press **Test**. A sample note posts to a matched contact (or unassociated
   if no match exists yet).
4. Done. Notes land after every completed call.

## How the contact is matched

1. If the call carries a `hubspot_contact_id` or `hubspot_id` CRM field, that
   contact is used directly.
2. Otherwise PyAI searches your contacts by the caller's phone number.
3. No match → the note posts unassociated with the full summary and call
   reference.

## Troubleshooting

* **Error: 401 / INVALID\_TOKEN.** The token was rotated or deleted. Create a
  fresh private app token and update the connection (omitted fields preserve
  stored values).
* **Error: 403.** The private app is missing a scope. Edit the app in HubSpot
  and add both scopes, then press Test again.
* **Notes land unassociated when you expected a match.** Check the contact's
  phone number format in HubSpot; the match searches by the caller's number,
  so international formatting differences matter. Pass `hubspot_contact_id`
  in the call's CRM fields for an exact match.
