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

# HubSpot

> Create, update, and look up HubSpot CRM contacts

## Overview

The HubSpot tools integrate with the HubSpot CRM API to manage contacts from your workflows. Both tools key on the email address, so you can reconcile records without going through the Search API and its rate limit.

## Key Features

* `HUBSPOT_UPSERT_CONTACT`
  * Create a contact, or update the existing one with the same email address. Supports custom properties.
* `HUBSPOT_GET_CONTACT`
  * Fetch a contact by object ID or by email address. Returns `found: false` instead of failing when no contact matches.

## Authentication

For setup instructions, [see the HubSpot credentials page](/en/pages/credentials/hubspot).

| Config field   | Description                                                                                                                            |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `access_token` | A HubSpot access token (select from workspace secrets). Needs the `crm.objects.contacts.read` and `crm.objects.contacts.write` scopes. |

### Example: Look Up a Contact, Then Create or Update It

```yaml theme={null}
- id: find_contact
  tool: HUBSPOT_GET_CONTACT
  config:
    - name: access_token
      value: "{{secrets.HUBSPOT_ACCESS_TOKEN}}"
  input:
    - name: email
      value: "customer@example.com"
    - name: properties
      value: "email, firstname, lastname, company"
- id: upsert_contact
  tool: HUBSPOT_UPSERT_CONTACT
  config:
    - name: access_token
      value: "{{secrets.HUBSPOT_ACCESS_TOKEN}}"
  input:
    - name: email
      value: "customer@example.com"
    - name: firstname
      value: "Ada"
    - name: lastname
      value: "Lovelace"
    - name: lifecyclestage
      value: "lead"
    - name: properties
      value: '{"hs_lead_status":"OPEN"}'
```

## Inputs

### `HUBSPOT_UPSERT_CONTACT`

| Input                                                              | Required | Description                                                                                                                                   |
| ------------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `email`                                                            | Yes      | The lookup key. An existing contact with this email is updated, otherwise a new one is created.                                               |
| `firstname`, `lastname`, `phone`, `company`, `jobtitle`, `website` | No       | Standard contact properties.                                                                                                                  |
| `lifecyclestage`                                                   | No       | e.g. `subscriber`, `lead`, `marketingqualifiedlead`, `customer`.                                                                              |
| `properties`                                                       | No       | Any other HubSpot properties as a JSON object of internal name → value, e.g. `{"hs_lead_status":"OPEN"}`. A `null` value clears the property. |

A named input left blank is skipped, not sent — HubSpot reads an empty string as "clear this property", so clearing has to be asked for explicitly through `properties` (`{"firstname": null}`). Named inputs win over the same key inside `properties`. Setting `properties.email` to something other than the `email` input is rejected. A difference in letter case alone is treated as the same address.

Returns `result.id`, `result.created`, `result.properties`, and the raw `result.contact`.

### `HUBSPOT_GET_CONTACT`

| Input          | Required       | Description                                                                                                                                                                                                             |
| -------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `contact_id`   | One of the two | HubSpot contact object ID.                                                                                                                                                                                              |
| `email`        | One of the two | Contact email address.                                                                                                                                                                                                  |
| `properties`   | No             | Comma-separated property names, e.g. `email, firstname, company`. HubSpot returns only a minimal set when this is empty. Custom properties use their internal name, which you can find under **Settings → Properties**. |
| `associations` | No             | Comma-separated object types to also fetch associated record IDs for, e.g. `companies, deals`.                                                                                                                          |

Returns `result.found`, `result.id`, `result.properties`, `result.associations`, and the raw `result.contact`.

## Notes

* **Not found is not an error**: `HUBSPOT_GET_CONTACT` returns `result.found = false` on a missing contact, so "look up, and create it if missing" can be an ordinary condition step.
* **Concurrent writes are last-write-wins**: HubSpot's CRM API has no optimistic locking, so overlapping updates resolve per property. Do not use `HUBSPOT_UPSERT_CONTACT` for read-modify-write accumulation (reading a score, adding to it, writing it back) across runs that may overlap — use a HubSpot calculated property instead.
* **Archived contacts**: a contact in HubSpot's recycle bin still reserves its email address, so an upsert against it cannot succeed. Restore it from the recycle bin, or use a different address.
* **Timeouts**: every request has a 30-second timeout, with automatic retries on rate limits and transient server errors.
