---
title: "HubSpot"
url: https://docs.light-ai.app/integrations/hubspot.md
canonical_url: https://docs.light-ai.app/integrations/hubspot
last_updated: 2026-10-13
summary: "Contacts, notes and deals from Light AI leads and quotes through n8n and HubSpot's CRM API, which works on every HubSpot tier, Free included."
api_status: beta
related:
  - https://docs.light-ai.app/integrations
  - https://docs.light-ai.app/inbound
  - https://docs.light-ai.app/webhooks
  - https://docs.light-ai.app/external-refs
---

# HubSpot

> Contacts, notes and deals from Light AI leads and quotes through n8n and HubSpot's CRM API, which works on every HubSpot tier, Free included.

| Direction | Path | How |
| --- | --- | --- |
| Leads → Light AI | **via n8n** · **via Zapier** | A HubSpot trigger (form submission or new contact) in Zapier, or n8n's HubSpot Trigger (needs a HubSpot developer app) → `POST /v1/leads` with `source: hubspot` and `external_ref: { system: "hubspot", id: <contact id> }`. A workflow **Send a webhook** action also works but needs Data Hub Professional or Enterprise. |
| Light AI → HubSpot | **via n8n** | Contact (and a note) on `lead.created`; deal on `quote.published` keyed on `project.id`; closed-won on `quote.approved`; closed-lost on `quote.declined` / `quote.expired`. The template creates a closed-won deal on approval. |

## Lead → contact and note

| HubSpot | Light AI |
| --- | --- |
| `firstname`, `lastname`, `email`, `phone` | `contact.first_name`, `contact.last_name`, `contact.email`, `contact.phone` |
| `address`, `city`, `state`, `zip`, `country` | `address.line1`, `address.city`, `address.region`, `address.postal_code`, `address.country` |
| A custom property (e.g. `light_ai_source`) | `source`, `source_detail` (HubSpot sets its own original-source fields) |
| Note (`hs_note_body`) on the contact | `message`, `service_interest`, form answers (`lead.form_answers`, see [Website request forms](https://docs.light-ai.app/forms)) and `project.app_url` |

## Quote → deal

| HubSpot | Light AI |
| --- | --- |
| `dealname` | Customer name and site address |
| `amount` | `totals.total.decimal` |
| `pipeline`, `dealstage` | `default`; `closedwon` / `closedlost` (custom pipelines have their own stage ids) |
| `closedate` | `approved_at` or `declined_at` |
| Line items: `name`, `quantity`, `price` | `line_items[]`: `name`, `quantity`, `unit_price_cents / 100` |
| `description` | `links.app_url` |

## Notes

- Credential: a legacy private app token or a service key (public beta since February 2026; REST calls only, no webhooks). Both are Bearer tokens for n8n's HubSpot App Token credential. Scopes: `crm.objects.contacts.write`, `crm.objects.deals.write`, plus `crm.objects.line_items.write` for line items.
- Write the deal id back on the project so later events update the same deal.
- `unit_price_cents` is `null` for lines priced as a whole (e.g. mini lights by the set): send quantity 1 and `total_cents` instead.
- Photos and instant previews: webhook payloads carry only asset ids (`assets.photos[]`, `assets.mockups[]` with `url: null`). Fetch `GET /v1/leads/{id}` for links that expire after 60 minutes and download the files if the CRM can store them; otherwise store `project.app_url` (sign-in required). Never save a 60-minute link in a CRM.

## Download

- [quote-approved-to-hubspot.json](https://docs.light-ai.app/downloads/n8n/quote-approved-to-hubspot.json)

## Sources

- [Legacy private apps](https://developers.hubspot.com/docs/apps/legacy-apps/private-apps/overview)
- [Service keys](https://developers.hubspot.com/docs/apps/developer-platform/build-apps/authentication/account-service-keys)
- [Deals API](https://developers.hubspot.com/docs/guides/api/crm/objects/deals)
- [Line items API](https://developers.hubspot.com/docs/guides/api/crm/objects/line-items)
- [Webhooks in workflows (Data Hub)](https://knowledge.hubspot.com/workflows/how-do-i-use-webhooks-with-hubspot-workflows)
- [n8n HubSpot node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.hubspot/)
