> For the complete documentation index, see [llms.txt](https://docs.appmixer.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.appmixer.com/connector-configuration/hubspot.md).

# Hubspot

## Register OAuth2 app

You need to create a developer account first (more about different Hubspot accounts can be found here<https://developers.hubspot.com/docs/api/account-types>)

Create a new application.

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-2d73448ed0bba50bfb820a30dba0822c48ab0369%2Fhubspot-1.png?alt=media)

In order to get rid of a warning that your users will see before installing Hubspot module, you have to verify your identity as an app provider.

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-8637d3927cefefb51de677962dc707b99bc0674c%2Fhubspot-2.png?alt=media)

You can manage the *Contact & Support* settings.

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-9b56eb11ed4a032ff10ca92c64ecb3e43ee3a9b5%2Fhubspot-3.png?alt=media)

Or skip for now.

Set the application name, logo, and description.

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-e099c5a236984bffc0010916c64e7852ba71280a%2Fhubspot-4.png?alt=media)

Go to the *Auth* tab and copy\&paste these values into the [Backoffice](https://github.com/Appmixer-ai/appmixer-docs-gitbook/tree/app-registrations/getting-started/services.md).

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-549e7d6f3c5c5610176e18f4fa007e04a14347fa%2Fhubspot-5.png?alt=media)

Create *Hubspot* configuration in the [Backoffice](https://github.com/Appmixer-ai/appmixer-docs-gitbook/tree/app-registrations/getting-started/services.md).

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-513f2b20066557b9d70f646658be68243d300f31%2Fhubspot-6.png?alt=media)

![appmixer:hubspot](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-2b8b907b4ad948b9a37682d831eceba1a16d6b25%2Fhubspot-7.png?alt=media)

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-32e5f359f52b1304768236a2aa7c38b4ca379956%2Fhubspot-8.png?alt=media)

Go back to Hubspot and set the redirect URL, replace *acme.com* with your domain and keep the suffix /auth/hubspot/callback

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-98568e23880ae56b0c4c850c8c5e793091068a31%2Fhubspot-9.png?alt=media)

Adding scopes.

<figure><img src="https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-95d17ea8b150096da1aad7b2e6d5b1741bde45b9%2Fhubspot-10.png?alt=media" alt=""><figcaption></figcaption></figure>

The HubSpot connector (bundle 4.8.0+) requests the following scopes in the authorization URL:

```
oauth
automation
e-commerce
forms
timeline
tickets
media_bridge.read
sales-email-read
crm.lists.read
crm.lists.write
crm.objects.companies.read
crm.objects.companies.write
crm.objects.contacts.read
crm.objects.contacts.write
crm.objects.deals.read
crm.objects.deals.write
crm.objects.owners.read
crm.schemas.companies.read
crm.schemas.companies.write
crm.schemas.contacts.read
crm.schemas.contacts.write
crm.schemas.custom.read
crm.schemas.deals.read
crm.schemas.deals.write
```

All of them must be added to the app, otherwise the authorization fails on an unconfigured scope.

{% hint style="info" %}
**Prefer the "Conditionally required" bucket over "Required"** for every scope (except `oauth`, which HubSpot manages itself). HubSpot validates the authorization URL against the app's scope configuration in both directions: a *Required* scope must appear in every authorization URL, while a scope marked *Optional* must not appear in the `scope` parameter at all. *Conditionally required* scopes are the flexible middle ground — they may be included in the `scope` parameter but do not have to be, so older connector versions (or other Appmixer instances sharing the app) that request fewer scopes keep working, and adding a new scope in a future connector release does not break existing deployments.
{% endhint %}

{% hint style="warning" %}
When a new connector version adds a scope (e.g. `forms` and `automation` in bundle 4.8.0), add it to the HubSpot app configuration **before** deploying the connector — a consent request with a scope the app does not have configured fails. Scope granting is independent of the portal's subscription tier: HubSpot grants e.g. `automation` on any portal, but the workflows API itself requires a Professional/Enterprise subscription (or a developer test account) and returns 403 on lower tiers at call time.
{% endhint %}

Hit *Save*.

One more thing you will need is the HubSpot developer API key: go back to the *Apps* page and hit the *Get HubSpot API key* button (in the newer developer account UI the key is in the developer overview).

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-661ceb501160b3cc21fd6fadcad8a08831066ebb%2Fhubspot-11.png?alt=media)

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-65daad6a126eeae75a504c6008ed9bdc179692f6%2Fhubspot-12.png?alt=media)

Then copy\&paste the generated key and put it into the [Backoffice](https://github.com/Appmixer-ai/appmixer-docs-gitbook/tree/app-registrations/getting-started/services.md).

![](https://802996127-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIAGKHlIqVKJe9agnFr14%2Fuploads%2Fgit-blob-1e8d037ec82741334fb127b16463aad852fa8284%2Fhubspot-13.png?alt=media)

The *Hubspot* configuration in the Backoffice holds these values:

* `clientId` and `clientSecret` — from the app's *Auth* tab.
* `appId` — the app ID, shown on the app's *Auth* tab (it is also the number in the app's URL).
* `apiKey` — the developer API key from the previous step.

{% hint style="info" %}
`appId` and `apiKey` are **required for the webhook triggers** when you use your own HubSpot app — without them the triggers do not start (*HubSpot appId or apiKey missing in configuration*). The connector uses them to manage the app's webhook settings and subscriptions (see [Webhooks](#webhooks)); with AuthHub they are not needed. The developer API key belongs to the HubSpot developer account, not to a customer portal, and can manage every app in that account — keep it only in the Backoffice configuration.
{% endhint %}

## Webhooks

The triggers *New Contact*, *Updated Contact*, *Contact Property Changed*, *Deleted Contact*, *New Deal* and *Updated Deal* receive events through the app's webhooks. *New Contact In List* and *Form Submission* poll the API and need no webhook.

### Target URL

Set the app's webhook target URL (the app's *Webhooks* settings) to your Appmixer API URL followed by `/plugins/appmixer/hubspot/events`, for example `https://api.acme.com/plugins/appmixer/hubspot/events`.

If the app has no target URL yet, the connector sets it when a trigger starts for the first time — that first start still fails, start the flow again. A target URL that points elsewhere is never overwritten: the triggers then fail to start with *HubSpot webhook not configured properly, wrong target URL*.

Leave *Use expanded object support* turned off. The connector works with the classic `contact.*` and `deal.*` subscription types.

### Subscriptions

HubSpot sends an event only for a subscribed event type, and a property change only for a **subscribed property** — there is no "any property" subscription. Subscriptions belong to the app and apply to every portal that installed it; one app can have at most 1000 of them.

When a trigger starts, the connector creates the subscriptions it needs and turns back on the ones that were switched off (bundle 4.9.0+):

* *New Contact* — `contact.creation`
* *Deleted Contact* — `contact.deletion`
* *Updated Contact* — `contact.propertyChange` for `email`, `firstname`, `lastname`, `phone`, `website`, `company`, `address`, `city`, `state` and `zip`
* *Contact Property Changed* — `contact.propertyChange` for the property selected in the trigger (custom properties included)
* *New Deal* — `deal.creation`
* *Updated Deal* — `deal.propertyChange` for `dealname`, `dealstage`, `pipeline`, `hubspot_owner_id`, `closedate` and `amount`

*Updated Contact* and *Updated Deal* fire on a change of **any** subscribed property. To make them react to another property — a custom property, or a standard property outside the lists above — add a *Property changed* subscription for it in the app's webhook settings. Use the property's internal name (not its label) and make sure the subscription is active. Because subscriptions are shared by all portals, a subscription for a standard HubSpot property makes *Updated Contact* / *Updated Deal* fire on that property for every user of the app. To react to a single property only, use *Contact Property Changed*.

{% hint style="info" %}
Creating a record in HubSpot also sends property-change events for its initial values. *Updated Contact* and *Updated Deal* ignore them reliably only while the creation subscriptions (`contact.creation`, `deal.creation`) are active — keep those on even if you do not use *New Contact* or *New Deal*.
{% endhint %}

### Appmixer with AuthHub

With AuthHub, the Appmixer instances share the AuthHub's HubSpot app and the connector does not manage that app's subscriptions — the instance's HubSpot configuration needs no `appId` or `apiKey`. Whoever administers the app adds and activates the subscriptions — including *Property changed* subscriptions for custom properties — in its webhook settings. The app's target URL points at the AuthHub's `/plugins/appmixer/hubspot/events` route. *Contact Property Changed* then only filters the events; it cannot add a subscription for its property.

{% hint style="warning" %}
HubSpot ends support for legacy public apps (created before 23 June 2026) and for the `/v1/`–`/v3/` APIs in September 2027 ([announcement](https://developers.hubspot.com/changelog/legacy-apis-and-legacy-apps-whats-going-unsupported-and-when)). The connector manages webhooks through that API with the developer API key. Once an app is migrated to HubSpot's projects framework, its webhook subscriptions are defined in the project and can no longer be changed through the API or the app management UI.
{% endhint %}

## Hubspot App verification

> Your domain is unverified Until your domain is set and verified, users will see a warning when installing your app.

Users will encounter this warning during the installation or management of the app. To eliminate this warning, the verification process must be completed. HubSpot mandates the configuration of a DNS TXT record as the sole method for verification.

To configure and verify a custom HubSpot app for a hosted instance of Appmixer, such as ACME.appmixer.cloud, you will need to establish a custom domain for the Appmixer instance (for example, ACME.com). Without this custom domain, domain verification will not be possible.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.appmixer.com/connector-configuration/hubspot.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
