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

# HubSpot

> Prioritize & personalize your marketing & sales outreach by adding customer data into HubSpot

## Overview

HubSpot is a CRM and customer platform for managing contacts, companies, deals, and customer engagement. Use Hightouch to sync records to standard and custom HubSpot objects, log custom behavioral events, and keep contact lists up to date from your warehouse.

## Supported syncing

| Sync Type | Description | Supported Sync Modes | API Reference |
| - | - | - | - |
| [**Objects**](#objects) | Sync records to objects such as contacts or companies in HubSpot. | Upsert, Update, Insert | [Manage CRM records ↗](https://developers.hubspot.com/docs/api/crm/understanding-the-crm) |
| [**Events**](#events) | Sync records as custom behavioral events in HubSpot. | Insert | [Track behavioral events ↗](https://developers.hubspot.com/docs/api/analytics/events) |
| [**Contact lists**](#contact-lists) | Create, sync, and keep contact lists up-to-date in HubSpot. | Add, Remove | [Manage lists ↗](https://developers.hubspot.com/docs/api/crm/lists) |

For more information about sync modes, refer to the [sync modes](https://docs.hightouch.com/syncs/types-and-modes.md#sync-modes) docs.

## Understand your HubSpot setup

Before you configure syncs, confirm your HubSpot data model supports your plan. Property uniqueness, data types, editability, enumeration values, associations, and OAuth scopes all affect record matching and field mapping, so checking them first prevents configuration errors. For the planning steps common to every destination (what to sync, which fields, which mode, and how often), see [Plan your sync](https://docs.hightouch.com/destinations/overview.md#plan-your-sync). If you prefer, you can [download this resource as a PDF](https://cdn.sanity.io/files/pwmfmi47/production/b3c4f849dd2b6b85800cf56308af0a5dd7843cd1.pdf) to share with your team.

### Required data specifications

Once you’ve defined what you want to sync, verify that your HubSpot setup supports your plan. Use the table below to validate that your objects, properties, and permissions are configured correctly before creating your syncs.

| Consideration | Effect on sync configuration |
| - | - |
| Is the property that you would like to use for [record matching](#record-matching) unique? | Non-unique values can lead to duplicates and sync errors. |
| What are the expected data types of the properties you want to sync to? | The response affects your [field mapping](#field-mapping); if the expected type differs from your model column type, you must [type cast your data](https://docs.hightouch.com/models/data-types-casting.md) in your model configuration. |
| Are the properties you want to sync editable? | Hightouch only displays editable fields during [field mapping](#field-mapping). |
| Are any of the properties you want to sync [calculated](https://community.hubspot.com/t5/Tips-Tricks-Best-Practices/Using-calculated-properties/m-p/372525) properties? | Calculation properties are non-editable and read-only. Change the field type if you want to sync data to it. |
| Are any of the properties you want to sync [enumeration](https://knowledge.hubspot.com/account/property-field-types-in-hubspot) properties? | Enumeration properties only accept specific values. Ensure your data matches these values or create a new property. |
| Are there any associations you want to make between objects? | You can set up [associations](#associations) while field mapping, assuming the association exists in HubSpot first. |
| Does the user you are authenticating to Hightouch have edit access? | The sync will error if the user doesn't have the correct permissions. |

Permissions depend on both the HubSpot user’s role and the OAuth scopes granted when connecting Hightouch. If objects or properties don’t appear during [record matching](#record-matching) or [field mapping](#field-mapping), re-check permissions and reconnect the destination with the appropriate scopes.

Use the steps in [Inspect objects, properties, and associations](#inspect-objects-properties-and-associations) to validate your HubSpot configuration before creating your syncs.

### Inspect objects, properties, and associations

1. In HubSpot, click the settings icon in the top navigation bar. In the left sidebar, go to **Objects** (under **Data Management**), then select the object you want to inspect (for example, **Contacts**, **Companies**, **Leads**, or a **Custom Object**).

![Inspecting objects in the HubSpot UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-objects.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=e667a878abd5ba18c64d8fcdb65fa12a)

2. In the object's overview page, under **Setup**, click **Manage \[object] properties**.

![Inspecting properties in HubSpot UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-properties.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=de39a07081d8baafb43ea140f12d101a)

3. Review both standard and custom properties you want to sync data to. Make note of their:

* **Internal name**: This is the name that appears in the Hightouch UI for [record matching](#record-matching) and [field mapping](#field-mapping). You can access it by clicking on the property name and then clicking **\</>** in the property inspector.

![Inspecting a property's internal name](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-internal-name.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=f237bf4118040c99356c15922654200d)

* **Property access**: The HubSpot user you use to [authenticate to Hightouch](#connect-to-hubspot) should have access to edit the property.

* **Data type**: For example, **Single-line text** or **Number**—you can view these under the property **Name**. When selecting model columns for [field mapping](#field-mapping), you must ensure the data type matches. For example, a **Single-line text** property requires text data and a **Number** requires numerical data.

![Inspecting a property's data type and access](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-type-and-access.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=02f62adadb68dc3c28bb4ceca894a9fb)

4. Check whether any of the properties you plan on syncing to are an enumeration type, such as **Dropdown select**, **Radio select**, or **Multiple checkboxes**. For example, the native **Lead rating** property for contacts is a **radio select** property.

![Lead rating property in HubSpot UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-lead-rating.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=9cdf2d59c3355286a8f93fdd18e111be)

If you plan on syncing to enumeration properties, the data you sync must match the **internal value** of the options. Lead rating, for example, can accept the values "bucket\_1," "bucket\_2," "bucket\_3," and "bucket\_4," though the labels are "1 Star," "2 Stars," etc.

![Lead rating property in HubSpot UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-lead-rating-2.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=4eabc3c2b6e3b761c557c86b2e585ca4)

Since internal values can't be updated once created, you may need to create a new custom property to accept data from your model. Refer to HubSpot's guide on [property field types](https://knowledge.hubspot.com/account/property-field-types-in-hubspot) to select the appropriate field type when creating new properties.

5. Check if the property requires unique values: Click on its name, then go to **Rules**. Under **Validation rules**, see if **Require unique values for this property** is checked. Properties you want to use for [record matching](#record-matching) must have this validation.

![Inspecting a property's uniqueness](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-uniqueness.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=5340669a17a68fe088b9e41aa1c2bec1)

6. Check if the property is sensitive or highly sensitive. To sync sensitive data, you must be using an Enterprise account and have permissions from your admin to read and write to sensitive and highly sensitive properties.

7. Return to the object's overview page and select **Associations**. Look for associated child objects like contacts, companies, or deals linked to the records. You can use these to map [associations](#associations) in Hightouch. Add, remove, or correct links between objects as needed.

![Inspecting a property's associations](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-association.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=73b741ac7980ae7c207f6ec7c1617b42)

Once you've validated the properties and associations of the objects you want to sync to, you're ready to configure your sync in Hightouch.

## Connect to HubSpot

Add HubSpot from the [Destinations](https://app.hightouch.com/destinations?from=docs) page, then authenticate:

1. Choose how to authenticate Hightouch to HubSpot:
   * **`OAuth`** (recommended): Use this option to sync CRM objects (for example, contacts and companies) and update standard properties.
   * **`OAuth with enterprise scopes`**: Required if you plan to sync **custom behavioral events** or use Enterprise-only features such as sensitive properties.
     * Enterprise users can also enable scopes for [sensitive data](https://knowledge.hubspot.com/properties/store-sensitive-data). Select **`Sensitive`** or **`Highly sensitive`** only if your sync requires access to those properties.

> [!NOTE]
>
> For the smoothest setup, authenticate using a HubSpot user with admin
> permissions (typically **Super Admin**). HubSpot permissions and the OAuth
> scopes you approve both affect which objects and properties appear in
> Hightouch and whether syncs can write updates.

![Authentication method selection](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-authentication-method.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=e809e50108a7fc17e54009dff9f74494)

> [!WARNING]
>
> Only enable **`Sensitive`** or **`Highly sensitive`** scopes if your sync
> needs to read or write those properties.

2. Select the **HubSpot account** you want to connect to Hightouch.

3. Review and accept the scopes that the Hightouch app requests from HubSpot.

![HubSpot scopes requested by Hightouch](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-scopes-authorization.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=0359c280a1591e52d9960495d2049824)

4. After authorization succeeds, you’ll be redirected back to Hightouch. Click **`Continue`**.

5. (Optional) Configure alert settings and recipients. You can edit these later from the destination settings.

6. Enter a descriptive **destination name** and configure permissions for:

   * Triggered syncs
   * Configuring models and syncs
   * Managing the destination

7. Click **`Finish`** to complete setup.

At this point, you should know which objects, properties, identifiers, and associations you plan to sync, and have verified that your HubSpot permissions and property types support your configuration.

## Sync configuration

The configuration options below vary by sync type.

### Objects

Sync records to standard HubSpot objects (contacts, companies, deals, and more) or to custom objects. Use **Upsert** to create missing records and update existing ones, **Update** to change only records that already exist, and **Insert** to add new records without updating. To sync to a custom object, [create it in HubSpot](https://knowledge.hubspot.com/crm-setup/use-custom-objects) first.

#### Record matching

To match rows from your model to objects in HubSpot, select a HubSpot property and the corresponding column from your model.

![Record matching in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-record-matching.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=93bb71ca4ceb3f8f46c924cf4faaad50)

You can match on any of the available properties in the dropdown. It's best to select a property that [HubSpot automatically deduplicates on](https://knowledge.hubspot.com/crm-setup/deduplication-of-contacts-companies-deals-tickets#deduplicate-companies-by-company-domain). These include **email** (Contacts), **company domain** (Companies), or a **HubSpot record ID** (for example, `hs_object_id`) for other object types.

If you select a model column with duplicates to send to one of these properties, HubSpot [returns a 409 error](#409---contact-already-exists) and the sync errors.

If record matching isn’t unique (for example, multiple HubSpot records match the same value), HubSpot may reject updates and Hightouch may need extra lookups. This can slow syncs and cause partial failures.

> [!NOTE]
>
> The `id` property is only available for record matching when in update mode.
> It is a read-only property, and HubSpot sets its value upon object creation.

The HubSpot property you select to match on should be **unique**, and its data type must match the data type of the corresponding column in your model. If the property to match on isn't unique, record matching will be slower and duplicate records may occur. You can check a property's uniqueness validation by [inspecting the property in HubSpot](#inspect-objects-properties-and-associations).

> [!TIP]
>
> If the object doesn't have a native unique property, consider creating a
> unique custom property. Refer to [HubSpot's
> instructions](https://community.hubspot.com/t5/Tips-Tricks-Best-Practices/Custom-unique-property/td-p/683119#)
> on how to do so.

#### Field mapping

Field mapping lets you choose which properties you want to update on your HubSpot objects. If the HubSpot object you're syncing to doesn't have the specific property you want to send your data to, you need to [create a new property on the object](https://knowledge.hubspot.com/crm-setup/manage-your-properties) in HubSpot first.

> [!TIP]
>
> You can also sync to [enumeration
> properties](https://knowledge.hubspot.com/account/property-field-types-in-hubspot),
> such as **Dropdown select**, **Radio select**, and **Multiple checkboxes**.
> Make sure to create your property's internal values before syncing them, as
> explained in the [Common errors](#400---property-values-were-not-valid)
> section.
>
> Check out [HubSpot's documentation](https://knowledge.hubspot.com/crm-setup/import-data-to-checkbox-properties)
> to learn how to sync **Multiple checkboxes**.

After creating or editing properties, you can refresh the available properties for mapping by clicking the refresh button next to **`Field from HubSpot`**. The new property should then be available.

![HubSpot internal naming](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-refresh-fields.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=8c340e47f0d5ebeeae3317721edd9f9d)

Hightouch displays the property's **Internal name**, not label, in the dropdown. You can find a property's internal name by [inspecting the property in HubSpot](#inspect-objects-properties-and-associations).

![HubSpot internal naming](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-inspect-internal-name.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=f237bf4118040c99356c15922654200d)

> [!NOTE]
>
> Read-only fields in HubSpot aren’t available for mapping in Hightouch.

> [!NOTE]
>
> Field mapping columns may appear greyed out until you select a sync type and
> configure record matching. Once record matching is set, the available fields
> for that object type populate and become editable.

If a model column’s data type doesn’t match the HubSpot property type (for example, sending text to a number property), HubSpot may reject the row. If needed, type cast your data in your model before syncing.

#### Field sync behavior

Each field mapping has a sync behavior setting that controls how Hightouch handles the value for that field. Click the gear icon on a field mapping row to choose one of the following options:

![Field sync behavior options in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-field-sync-behavior.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=9241dfc9eadb5f2239e86ec774c55884)

| Behavior | Description |
| - | - |
| **Always sync** | Syncs the value from your model to HubSpot on every sync run, including null values. Use caution, as this can erase existing production data. Does not apply to nested object or array properties. |
| **Don’t sync null values** | Skips syncing any null values from your model to HubSpot. If the model value is null, the existing HubSpot value is left unchanged. |
| **Only write to empty fields** | Only writes the value if the HubSpot property is currently empty. Existing non-empty values are not overwritten. |

**Only write to empty fields** is useful when you want to populate missing data without overwriting values that have already been set in HubSpot—for example, backfilling phone numbers or other contact details without replacing manually entered data.

#### Associations

**Associations** let you express a relationship between the object you're syncing to (the **main object**) and a different HubSpot object (the **associated object**). For example, you may be syncing contacts to HubSpot and want to associate a company with each one.

Before mapping an association in Hightouch, confirm the association exists for the object pair in HubSpot (**Settings → Objects → \[Object] → Associations**).

1. Click **`Add mapping`**, then select the association label under **`Field from HubSpot`**. The list of supported association labels for the object appears in the dropdown. You can find an object's supported associations and add others by [inspecting the object in HubSpot](#inspect-objects-properties-and-associations).

2. Search for the object you want to associate to (the **associated object**). For example, if you want to associate a company with each contact you're syncing, search for "company," then select the appropriate association. In this example, you would select **CONTACT\_TO\_COMPANY**.

> [!WARNING]
>
> The association should only be set up in the main object's sync configuration.
> In this example, you would only add it to the **Contact** sync and not to the
> **Company** one. You can learn more about this in the [Common
> errors](#conflicting_one_to_ones_specified) section.

> [!NOTE]
>
> Make sure that the sync to the associated object always runs before the one to
> the main object. After creating your syncs, you can [set up a
> sequence](https://docs.hightouch.com/syncs/schedule-sync-with-sequences.md) to schedule them in the correct
> order.

![Associations list in Hightouch](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-associations-list.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=f6b1b6c6143bb007442a35c6e8e262a8)

Next, select the properties to match on. For example, if you're associating companies with contacts and a company's `name` matches the `COMPANY_NAME` in your contact data, you would select those properties.

![Associations list in Hightouch](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-full-association.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=8226bd2a077aafcae52bf3032ec0c340)

If your data contains the `id` of the object you want to associate to, it's best to use this column for matching. Since the sync doesn't have to perform a lookup, sync performance is significantly faster.

The example below shows using contact data that includes the associated company's id in a column called `ACCOUNT_ID`.

![Associations list in Hightouch](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-full-association-with-id.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=31ea198c64cbf70fd21285891d9fc10a)

You can create multiple HubSpot associations in a single sync. Click **`Add mapping`** for each association you want to make.

For more information on associations, check out [HubSpot's association docs](https://knowledge.hubspot.com/crm-setup/associate-records).

#### Association modes

##### **Create added associations**

Associations will only be appended to the record. This setting will not remove previous associations if the associated object is updated or removed.

##### **Overwrite existing associations**

When there are changes to associations in the source, remove all associations in HubSpot before creating the associations present in the source. If there are no changes to associations in the source, do not remove any associations.

> [!WARNING]
>
> This setting will also remove any associations that were created outside of
> Hightouch.

##### **Delete removed associations and create added associations**

This mode will find the differences between sync runs to delete associations in HubSpot that have been removed from the model, then create associations that have been added to the model.

#### One-to-many relationships

You might want to associate the object you're syncing to with multiple objects of the same type. For example, if you're syncing company objects, you may want to link several contacts to each company.

For Hightouch to associate multiple objects, the model column you select for the association must be in one of these formats:

* an array of string or number values, for example, `["id1", "id2", "id3"]`
* a comma-separated string, for example, `"id1, id2, id3"`

> [!WARNING]
>
> Confirm that the association cardinality in your HubSpot settings is
> compatible with the data you're syncing to HubSpot. You can learn more about
> this in the [Common errors](#conflicting_one_to_ones_specified) section.

#### Association labels

If you have a Professional or Enterprise HubSpot account, you can also use HubSpot's [association labels feature](https://knowledge.hubspot.com/crm-setup/create-and-use-association-labels) to describe relationships between objects.

Association labels let you add descriptive text to an association that provides more context about the relationship. For example, instead of just linking a contact to a company, you can use an association label like "Employee at" or "Customer of" to clarify the nature of the relationship.

> [!WARNING]
>
> Before configuring a sync to use association labels, check out HubSpot's
> association label limitations at the bottom of this [HubSpot
> doc](https://developers.hubspot.com/docs/api/crm/associations/v4).

To add association labels to a Hightouch sync, you must first [set up your labels in your HubSpot account](https://knowledge.hubspot.com/crm-setup/create-and-use-association-labels). Then, you need to update the [model](https://docs.hightouch.com/getting-started/concepts.md#models) column you use for associations to contain an object with this schema:

```
{ "value": string | number, "label": string | Array<string> }
```

> [!NOTE]
>
> Make sure to set the model column's [data
> type](https://docs.hightouch.com/models/data-types-casting.md#view-model-data-types) to **Object / Array**.

Hightouch uses the **value** to match the associated object and the **label** as the label on the association in HubSpot. For example, if you're associating companies with contacts, you may set the company name as the value and the contact's role as the label.

```
{ "value": "ABC Corp", "label": "Employee at" }
```

If you want to add more than one label, the label can be an array of strings or a comma-separated list. For example, if you're associating companies with a contact and the contact has multiple roles, a row from your model might look like this:

```
{ "value": "ABC Corp", "label": ["Employee at", "Decision maker"] }
```

If you want to add more than one association label to an object, you can sync an array of association label objects.
For example, if you're associating billing data with multiple contacts, a row from your model might look like this:

```
[{ "value": "John Doe", "label": "Buyer" }, { "value": "Jane Doe", "label": "Seller" }]
```

Ensure **all** rows follow this schema to avoid inconsistent behavior with HubSpot's API. If a row doesn't have a label, you can set the label as `null`.

For example, suppose you want to associate a company with a contact but don't have any information about the contact's role there. The model row should look like this:

```
{ "value": "ABC Corp", "label": null }
```

You can use some SQL helper functions to create an object or array of objects with this schema. Below is an example of a SQL query that creates an object for an association label:

```sql theme={null}
SELECT
  id,
  first_name,
  last_name,
  email,
  JSONB_BUILD_OBJECT('value', company_name, 'label', role) as company_obj
```

The query creates a column called `company_obj` and sets the `company_name` name as the value in the object and the `role` as the label in the object.

![Model creation with association labels](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-sql-object-query.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=47bebe8ffe9b4dbdfda4b08843e2952a)

Once you've formatted the data correctly, ensure the association in your sync configuration uses the column with the properly formatted object.

![Association with association labels](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-association-label.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=af11a3392f3679ee97be2d141087d2ca)

#### Sensitive data

HubSpot allows for Enterprise users to store [sensitive data](https://knowledge.hubspot.com/properties/store-sensitive-data). Prior to creating Sensitive Data properties, a user with super admin permissions must turn on Sensitive Data in your Privacy & Consent
settings and accept the related terms and conditions.

A property can be defined as sensitive or highly sensitive upon creation in the UI or through the API. If syncing to these sensitive data properties, ensure that you have the correct scopes selected when you authorize your account.

The available sensitive data scopes are:

* `crm.objects.custom.sensitive.read`
* `crm.objects.custom.sensitive.write`
* `crm.objects.custom.highly_sensitive.read`
* `crm.objects.custom.highly_sensitive.write`
* `crm.objects.appointments.sensitive.read`
* `crm.objects.appointments.sensitive.write`

Sensitive scopes are object-specific. If you don’t see the object you need covered by a sensitive scope, confirm HubSpot supports sensitive properties for that object type and reconnect with the required scopes.

#### Delete behavior

The [delete behavior](https://docs.hightouch.com/syncs/overview.md#delete-behavior) you select dictates what to do when a row no longer appears in your model's query results. Depending on the [sync mode](#objects) you're using, you can select from some or all of these options:

| Behavior | Description |
| - | - |
| **Do nothing** | Keep the record in HubSpot |
| **Clear fields** | Keep the record, but clear the mapped fields |
| **Archive record** | Archive the record in HubSpot |
| **Delete record (Contacts only)** | GDPR Delete the record in HubSpot (Permanent delete) |

In HubSpot, **archived** records are removed from active views but are not permanently deleted. **GDPR delete** is permanent and only available for Contacts.

In Upsert mode, you can select from all of the above (**Delete record** for contacts only, performs a permanent delete using the [**GDPR delete**](https://developers.hubspot.com/docs/reference/api/crm/objects/contacts/v3#post-%2Fcrm%2Fv3%2Fobjects%2Fcontacts%2Fgdpr-delete) endpoint). In Update mode, you can only select between **Do nothing** and **Clear fields**. Insert mode doesn't support delete behavior.

> [!WARNING]
>
> **Delete record** uses HubSpot's GDPR delete endpoint and is permanent — the
> contact and its associated data can't be recovered. Choose it only when you
> intend an irreversible deletion.

#### Split retries

HubSpot counts all objects in a batch as rejected if the request contains a single invalid record. To pinpoint which records are getting rejected with which errors and reduce the number of valid records that get retried, you can enable [**split retries**](https://docs.hightouch.com/syncs/retries.md#split-retries).

### Events

Sync records as [**custom behavioral events**](https://knowledge.hubspot.com/analytics-tools/create-codeless-custom-behavioral-events) in HubSpot, with custom properties. Events require **OAuth with enterprise scopes** — confirm you used that method when you [connected HubSpot](#connect-to-hubspot).

> [!WARNING]
>
> To ensure syncs send each event, your event model must use a truly unique [primary key](https://docs.hightouch.com/getting-started/concepts.md#unique-primary-key-requirement). See the [events syncs](https://docs.hightouch.com/syncs/types-and-modes.md#event-syncs) documentation for more information.

#### Event name

Providing an event name is required to log an event in HubSpot. You can either provide a static value or select to **use a column** from your model data.

![Track configuration in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-event-name.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=020ecae0dd164f847778095274e86f4c)

The event name should match the event's **internal name**. HubSpot assigns the internal name automatically when you create the event. You can find an event's internal name either in [HubSpot](https://knowledge.hubspot.com/analytics-tools/create-custom-behavioral-events#define-the-api-call) or by using the HubSpot [events API](https://legacydocs.hubspot.com/docs/methods/events/get_events).

Follow the instructions in HubSpot's docs to learn how to [find the internal name](https://knowledge.hubspot.com/analytics-tools/create-custom-behavioral-events#define-the-api-call) for an event.

#### Event timestamp

You can optionally select a column that contains timestamps of when events occurred. If this field is empty, Hightouch uses the time the event arrives at the server.

#### Assigning events to contacts

Assign each event to a contact by selecting a column in your events data that matches one of these HubSpot contact identifiers:

* email
* object (contact) ID
* user token

![Contact assignment in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-assign-contact-to-event.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=83873ebab40ec882cb690966b232c357)

> [!TIP]
>
> If the identifier column is null or doesn’t match an existing HubSpot contact,
> HubSpot can’t attribute the event to a record.

#### Field mapping

In the field mapping section, you can select columns from your model to sync to the default or custom properties of a HubSpot custom behavioral event.

![Field mapping in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-event-mappings.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=6c4fe738143e3d9c2b6de29a7ae40281)

> [!NOTE]
>
> Custom properties must exist on the event before you can sync to them. See
> HubSpot's docs on [how to create a custom
> property](https://knowledge.hubspot.com/analytics-tools/create-custom-behavioral-events-with-the-code-wizard)
> on an event.

### Contact lists

Sync contacts into a HubSpot [contact list](https://knowledge.hubspot.com/lists/create-active-or-static-lists) — either an existing list or a new one created on the first sync run. Select **Segment** as the sync type.

#### User identifiers

To identify which contacts to add or update in a contact list, select a model column and the corresponding HubSpot field.

You can match on either **Email** or **HubSpot Contact ID**.

![Record matching in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-contact-list-id-mapping.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=6cf27e64730de89f6ad36dd8465e24d8)

#### List creation or selection

Hightouch can create a new list for the sync automatically. Specify a custom name for the list, or leave it empty to default to the model name. The example below defaults to the model name "Newsletter subscribers."

![List creation in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-lists-create.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=97a7425840dc04fafe58ece8c8840b8e)

If you opt to sync to an existing list, you can select the list name from the dropdown.

#### Migrating from v1 to v3

If you had existing contact list syncs that use HubSpot's v1 API before April 30th, 2026, you need to migrate them to v3. The v1 and v3 APIs use different list IDs, so you must re-select your list after switching.

To migrate a sync:

1. Open your sync configuration.
2. Under **Object type**, select **Contacts**.
3. Select **Use an existing list** and **re-select your list from the dropdown.**
4. Save the sync.

Your list contents and membership are unchanged by this migration. Only the API version is updated.

## Uninstall Hightouch from HubSpot

Deleting the destination in Hightouch removes its syncs but leaves the Hightouch app installed in HubSpot. To remove the app itself, uninstall it from your HubSpot account using HubSpot's [instructions](https://knowledge.hubspot.com/integrations/connect-apps-to-hubspot#uninstall-an-app). Previously synced data in HubSpot isn't changed.

## Tips and troubleshooting

To see the exact API requests and responses from each sync run, use the [live debugger](https://docs.hightouch.com/syncs/debugger.md). To get notified by Slack, PagerDuty, SMS, or email when a sync fails, set up [sync alerts](https://docs.hightouch.com/syncs/alerting.md). If you run into an issue this page doesn't cover, [contact support](#pylon-chat).

> [!NOTE]
>
> For Hightouch platform error codes related to HubSpot, see [Error codes:
> HubSpot](https://docs.hightouch.com/developer-tools/error-codes.md#hubspot).

### Date values

When syncing date or timestamp values to HubSpot, you need to consider which data type the HubSpot field should use: `date` or `datetime`.
HubSpot `date` fields support date values which store a date without a time. `datetime` fields support timestamps. For more information, check out [HubSpot's timestamp FAQ](https://developers.hubspot.com/docs/api/faq#timestamps).

Values you send to a `date` field must follow one of these formats:

* date-only ISO 8601 strings (`YYYY-MM-DD`), for example, `2020-02-29`
* EPOCH-millisecond [timestamps](https://en.wikipedia.org/wiki/Unix_time), **with the time set to midnight UTC**: for example, `1430438400000`

If you're syncing a timestamp to a date field, Hightouch automatically sets its time to midnight UTC, as required by HubSpot.

Values you send to a `datetime` field must follow one of these formats:

* ISO 8601 formatted strings (`YYYY-MM-DDThh:mm:ss.sTZD`), for example, `2020-02-29T03:30:17.000Z`
* EPOCH-millisecond [timestamps](https://en.wikipedia.org/wiki/Unix_time): for example, `1427997766000`

HubSpot displays `datetime` values in the timezone of the user viewing the record.

A convenient way to convert your date values to Unix millisecond timestamps is to use the `to_unix` function in the [template mapper](https://docs.hightouch.com/syncs/mapping-data.md#template-mapping).

![Field mapping in the Hightouch UI](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/mapping-data/mapping-data-template-map-to-unix.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=bfbbd7a126655eb59e551f0cd27097ed)

The `to_unix` function throws an error if the input row's value is `null`. To avoid this, you can enter this [Liquid](https://shopify.dev/docs/api/liquid) into the template mapper:

```liquid theme={null}
{%- if row['column_name'] == null -%}
{{null}}
{%- else -%}
{{row['column_name'] | to_unix}}
{%- endif -%}
```

Be sure to replace `column_name` with the name of your model column.

If you notice the timestamp from your Hightouch model column isn't appearing in HubSpot for your `datetime` field, edit the JSON mapping in your sync configuration to include `"skipDateParse": true`. See example below:

```json theme={null}
mappings: [
  {
    "from": "hightouch_datetime_column",
    "to": "hubspot_datetime_field",
    "skipDateParse": true
  }
]
```

### Validate your setup

After your first sync completes, verify the data in HubSpot:

* For object syncs, open the target object in HubSpot (for example, **Contacts** or **Companies**) and search for a test record. Confirm that mapped properties appear with expected values.
* For event syncs, open a contact record and check the **Activity** timeline for the custom behavioral event.
* For contact list syncs, open the target list in **Contacts → Lists** and confirm membership matches your model.

If properties or objects don't appear in Hightouch during sync configuration, re-check the connected user's permissions and OAuth scopes, then reconnect the destination.

## Common errors

| Error message | Description |
| :- | :- |
| `402 - Cannot create another PORTAL_SPECIFIC_OBJECT` | Reached HubSpot's object creation limit for a specific type. [More detail.](#402---cannot-create-another-portal_specific_object) |
| `403 (1006) - Firewall blocked request` | HubSpot's firewall is blocking Hightouch's IP addresses. [More detail.](#403-1006---firewall-blocked-request) |
| `429 - You have reached your secondly limit` | Rate limit exceeded due to concurrent syncs or association constraints. [More detail.](#429---you-have-reached-your-secondly-limit) |
| `Missing permissions or OAuth scopes` | Objects or properties don't appear, or syncs fail after connecting. [More detail.](#missing-permissions-or-oauth-scopes) |
| `409 - Contact already exists` | Duplicate email or record matching values. [More detail.](#409---contact-already-exists) |
| `Property does not exist or is not writable` | Property missing, read-only, or insufficient scopes. [More detail.](#property-does-not-exist-or-is-not-writable) |
| `400 - Cannot update object...the following properties were cleared` | No data sent to a required HubSpot property. [More detail.](#400---cannot-update-object-with-type--the-following-properties-were-cleared-) |
| `400 - Property values were not valid` | Value doesn't match a valid option in an enumeration property. [More detail.](#400---property-values-were-not-valid) |
| `400 - BAD_REFRESH_TOKEN` | OAuth token expired or revoked. [More detail.](#400---bad_refresh_token) |
| `400 - Duplicate unique property value` | Another record already uses the value for a unique field. [More detail.](#400---duplicate-unique-property-value) |
| `400 - One or more associations are invalid` | Association limit exceeded or self-referencing association. [More detail.](#400---one-or-more-associations-are-invalid) |
| `Invalid property value due to type mismatch` | Data type in model doesn't match the HubSpot property type. [More detail.](#invalid-property-value-due-to-type-mismatch) |
| `CONFLICTING_ONE_TO_ONES_SPECIFIED` | Association set up in both objects' syncs or cardinality mismatch. [More detail.](#conflicting_one_to_ones_specified) |
| `Row with ID email...could not be added to the list` | Contact doesn't exist in HubSpot before list sync. [More detail.](#row-with-id-emailcould-not-be-added-to-the-list) |
| `Association label missing or misformatted` | Association payload missing the required label key. [More detail.](#association-label-missing-or-misformatted) |

### 402 - Cannot create another PORTAL\_SPECIFIC\_OBJECT

```
402 - Cannot create another PORTAL_SPECIFIC_OBJECT
```

**Cause:** Your HubSpot portal has reached the maximum number of records for a specific object type. For example, the default limit for contacts is 1,500,000.

**Solution:**

1. Archive or delete unused records in HubSpot to free up capacity.
2. If you need a higher limit, upgrade your HubSpot subscription or contact HubSpot support.

### 403 (1006) - Firewall blocked request

```
403 - {"status":"error","category":"BLOCKED","errors":[{"errorType":"BLOCKED","id":"1006"}]}
```

**Cause:** HubSpot's web application firewall (WAF) is blocking requests from Hightouch's IP addresses.

**Solution:**

1. Contact HubSpot support and ask them to allowlist Hightouch's IP addresses. You can find the current IPs in [Hightouch's networking documentation](https://docs.hightouch.com/security/networking).
2. Try disconnecting and reconnecting your HubSpot destination in Hightouch to reauthorize.

### 429 - You have reached your secondly limit

```
429 - You have reached your secondly limit
```

**Cause:** HubSpot's per-second API rate limit has been exceeded. This typically happens when another sync to HubSpot is running simultaneously, or when [associations](#associations) are configured (the HubSpot API has constraints that slow syncs using associations).

**Solution:**

1. Ensure you're following [record matching configuration suggestions](#record-matching).
2. Stagger sync schedules so multiple HubSpot syncs don't run at the same time.
3. Enable [split retries](#split-retries) so Hightouch retries only the failed records instead of the full batch.
4. If you're on a lower-tier HubSpot plan, check whether your plan's API rate limits are sufficient for your sync volume.

For more information about HubSpot's API limits, see [HubSpot's API usage guidelines](https://developers.hubspot.com/docs/api/usage-details).

### Missing permissions or OAuth scopes

Objects, properties, or events don’t appear in Hightouch, or syncs fail immediately after connecting. This isn’t a specific error message — it’s a pattern that indicates the HubSpot user may not have the required permissions, or the connection may be missing required scopes.

**Cause:** The HubSpot user who authorized the connection doesn’t have sufficient role permissions, or the OAuth connection wasn’t granted the necessary scopes.

**Solution:**

1. Reconnect HubSpot using a user with admin permissions (typically Super Admin).
2. Approve the required scopes (use **OAuth with enterprise scopes** for events and sensitive properties).

### 409 - Contact already exists

```
409 - Contact already exists
400 - Duplicate IDs found in batch input
```

**Cause:** The model column used for [record matching](#record-matching) contains duplicate values, the column [mapped](#field-mapping) to HubSpot's `email` field contains duplicate values, or you're creating a new contact with the same email as an existing one but a different record-matching value. HubSpot uses email as the primary unique identifier — two contacts can't share the same email. See [HubSpot's Contacts API Reference](https://developers.hubspot.com/docs/api/crm/contacts#properties) for more information.

**Solution:**

1. Ensure the column you selected for record matching doesn't contain duplicate values.
2. Ensure any email information you're syncing doesn't include duplicate values.
3. Confirm you aren't creating a new HubSpot contact with the same email as an existing one but a different value in the record-matching field.

> [!NOTE]
>
> The `409 - Contact already exists` error message contains an `Existing ID`
> value returned by HubSpot. This value refers to HubSpot's ID for the contact
> and doesn't necessarily correspond to any values in your model data.

### Property does not exist or is not writable

```
Property does not exist or is not writable
```

**Cause:** The HubSpot property doesn’t exist on the target object, is read-only (for example, a calculated property), or the connected HubSpot user/scopes don’t have permission to write to it.

**Solution:**

1. Confirm the property exists on the correct HubSpot object (**Settings → Objects → \[Object] → Properties**).
2. Confirm the property is editable (calculated properties are read-only).
3. Reconnect the destination if you recently added custom objects or changed permissions/scopes.

### 400 - Cannot update object with type ... the following properties were cleared ...

```
400 - Cannot update object with type: ... the following properties were cleared: [property_name]
```

**Cause:** No data is being sent to a required property in HubSpot. The properties listed after "the following properties were cleared" are the required properties.

**Solution:**

1. Remove records with empty values in the required property by updating your [model definition](https://docs.hightouch.com/models/creating-models.md) to exclude those rows.
2. Alternatively, add a value to the required property in your model data.

### 400 - Property values were not valid

```
400 - {"status":"error","message":"Property values were not valid: [{"isValid":false,...}]"}
```

**Cause:** You're sending a value to an [enumeration property](https://knowledge.hubspot.com/account/property-field-types-in-hubspot) that isn't one of the valid options. Enumeration properties include **Dropdown select**, **Radio select**, and **Multiple checkboxes**. The error message may contain diagnostic lines like `"error":"INVALID_OPTION","name":"custom_dropdown_field"` or `"error":"INVALID_OPTION","message": {...} was not one of the allowed options` to help identify the field.

**Solution:**

1. Ensure values exactly match HubSpot's **Internal values**, not the **Labels**. These values are case sensitive.
2. Refer to step 4 of [Inspect objects, properties, and associations](#inspect-objects-properties-and-associations) to find the **Internal Values** of your HubSpot field.

![Dropdown select internal values in HubSpot](https://mintcdn.com/hightouch-3c037897/L_vQfA0JQEpeGUUo/images/destinations/destination-hubspot-dropdown-internal-values.png?fit=max\&auto=format\&n=L_vQfA0JQEpeGUUo\&q=85\&s=5e8d38ec044a90e6d6eb1bad2b840101)

> [!NOTE]
>
> As explained in the [field mapping](#field-mapping) section, make sure to
> follow [HubSpot's
> guidelines](https://knowledge.hubspot.com/crm-setup/import-data-to-checkbox-properties)
> when syncing to **Multiple checkboxes** fields.

### 400 - BAD\_REFRESH\_TOKEN

```
400 - BAD_REFRESH_TOKEN
```

**Cause:** The OAuth refresh token for your HubSpot connection has expired or been revoked.

**Solution:** Disconnect and reconnect HubSpot in **Destinations → \[your HubSpot destination] → Configuration**. Use a HubSpot user with admin permissions to reauthorize.

### 400 - Duplicate unique property value

```
400 - Cannot set PropertyValueCoordinates: ... A record with this value already exists
```

**Cause:** You’re syncing a value to a field that has a unique constraint in HubSpot, but another record already uses that value.

**Solution:**

1. Check the HubSpot property’s settings to confirm it’s marked as unique.
2. Deduplicate the values in your model, or update your model query to exclude rows that conflict with existing HubSpot records.

### 400 - One or more associations are invalid

```
400 - One or more associations are invalid
```

**Cause:** The sync is attempting to create an association that exceeds HubSpot’s [association limits](https://developers.hubspot.com/docs/api/crm/associations#association-limits), or is trying to associate a record with itself.

**Solution:**

1. Check HubSpot’s association limits for the object types involved.
2. Ensure your model data doesn’t include rows that would associate a record with its own ID.
3. If you’re hitting limits, review your data model to reduce the number of associations per record.

### Invalid property value due to type mismatch

```
Invalid property value due to type mismatch
```

**Cause:** The data type in your model doesn’t match the HubSpot property type (for example, sending text to a number property).

**Solution:**

1. Check the property’s field type in HubSpot.
2. Type cast the model column to the expected type before syncing.
3. Re-run the sync after updating the model or mapping.

### CONFLICTING\_ONE\_TO\_ONES\_SPECIFIED

```
CONFLICTING_ONE_TO_ONES_SPECIFIED
```

**Cause:** An [association](#associations) is set up in both the main object's and the associated object's sync configuration, or the cardinality of your association or [association label](#association-labels) in HubSpot isn't compatible with the data you're syncing. For example, a `1-to-1` association can't [associate multiple records](#one-to-many-relationships) on the main object with one record on the associated object.

**Solution:**

1. If the association exists in both sync configurations, remove it from the associated object's sync.
2. Access the main object's HubSpot settings, open the **Associations** tab, and check your associations' cardinalities.
3. In your Hightouch sync configuration, use an association or association label that has the correct cardinality.

### Row with ID email...could not be added to the list.

```
Row with ID email...could not be added to the list
```

**Cause:** When syncing [contact lists](#contact-lists) and [matching on **Email**](#user-identifiers), the contact you're trying to add doesn't exist in your HubSpot workspace.

**Solution:** Ensure the contact exists in HubSpot before syncing it to a contact list. Sync contacts first, then sync list membership.

### Association label missing or misformatted

```
Associating 0-2 object with {…} was not found
```

**Cause:** An association requires a label but the payload doesn’t include one, or the label format doesn’t match the expected schema.

**Solution:**

1. Ensure the model column for association labels uses the required object schema described in [Association labels](#association-labels).
2. Ensure the `label` key is present (set to a string, array of strings, or `null`).
