Hubspot
This page contains the setup guide and reference information for the HubSpot source connector.
Prerequisites
- HubSpot Account
- For Calabi Connect: Private App with Access Token
Setup guide
Step 1: Set up HubSpot
For Calabi Connect:
- OAuth (Recommended). We highly recommend you use OAuth rather than Private App authentication, as it significantly simplifies the setup process.
- Private App: If you are using a Private App, you will need to use your Access Token to set up the connector. Please refer to the official HubSpot documentation to learn how to obtain the access token.
For Calabi Connect:
- Private App setup (Recommended): If you are authenticating via a Private App, you will need to use your Access Token to set up the connector. Please refer to the official HubSpot documentation to learn how to obtain the access token.
- OAuth setup: If you are using Oauth to authenticate on Calabi Connect, please refer to Hubspot's detailed walkthrough. To set up the connector, you will need to acquire your:
- Client ID
- Client Secret
- Refresh Token
More information on HubSpot authentication methods can be found here.
Step 2: Configure the scopes for your streams (Private App only)
These instructions are only relevant if you are using a Private App for authentication. You can ignore this if you are authenticating via OAuth.
To set up a Private App, you must manually configure scopes to ensure Calabi Connect can sync all available data. Each scope relates to a specific stream or streams. Refer to HubSpot's documentation on scopes for instructions.
Expand to review scopes
| Stream | Required Scope |
|---|---|
campaigns | content |
companies | crm.objects.companies.read, crm.schemas.companies.read |
contact_lists | crm.lists.read |
contacts | crm.objects.contacts.read |
contacts_web_analytics | crm.objects.contacts.read, business-intelligence |
| Custom CRM Objects | crm.objects.custom.read |
deal_pipelines | crm.objects.contacts.read |
deals | crm.objects.deals.read, crm.schemas.deals.read |
deals_archived | crm.objects.deals.read, crm.schemas.deals.read |
email_events | content |
email_subscriptions | content |
engagements | crm.objects.companies.read, crm.objects.contacts.read, crm.objects.deals.read, tickets, e-commerce |
engagements_emails | sales-email-read |
forms | forms |
form_submissions | forms |
goals | crm.objects.goals.read |
leads | crm.objects.leads.read, crm.schemas.leads.read |
list_memberships | crm.lists.read |
line_items | e-commerce |
owners | crm.objects.owners.read |
products | e-commerce |
property_history | crm.objects.contacts.read |
subscription_changes | content |
tickets | tickets |
users | crm.objects.users.read, settings.users.read |
account_details | oauth |
deal_splits | crm.objects.deals.read |
properties | No additional scopes required |
workflows | automation |
Step 3: Set up the HubSpot connector in Calabi Connect
For Calabi Connect:
-
Log into your Calabi Connect account.
-
Click Sources and then click + New source.
-
On the Set up the source page, select HubSpot from the Source type dropdown.
-
Enter a name for the HubSpot connector.
-
From the Authentication dropdown, select your chosen authentication method:
-
(Recommended) To authenticate using OAuth, select OAuth and click Authenticate your HubSpot account to sign in with HubSpot and authorize your account.
HubSpot Authentication issuesYou may encounter an error during the authentication process in the popup window with the message
An invalid scope name was provided. To resolve this, close the window and retry authentication. -
(Not Recommended) To authenticate using a Private App, select Private App and enter the Access Token for your HubSpot account.
-
-
(Optional) Set the lookback window in minutes to re-fetch data for a specified number of minutes before the state from the previous sync. This helps to capture missing records.
-
Click Set up source and wait for the tests to complete.
For Calabi Connect:
- Navigate to the Calabi Connect dashboard.
- From the Calabi Connect UI, click Sources, then click on + New Source and select HubSpot from the list of available sources.
- Enter a Source name of your choosing.
- From the Authentication dropdown, select your chosen authentication method:
- (Recommended) To authenticate using a Private App, select Private App and enter the Access Token for your HubSpot account.
- (Not Recommended:) To authenticate using OAuth, select OAuth and enter your Client ID, Client Secret, and Refresh Token.
- (Optional) For Start date, use the provided datepicker or enter the date in the following format:
yyyy-mm-ddThh:mm:ssZ. The data added on and after this date will be replicated. If not set, "2006-06-01T00:00:00Z" (Hubspot creation date) will be used as start date. It's recommended to provide relevant to your data start date value to optimize synchronization. - (Optional) Set the lookback window in minutes to re-fetch data for a specified number of minutes before the state from the previous sync. This helps to capture missing records.
- Click Set up source and wait for the tests to complete.
Supported sync modes
The HubSpot source connector supports the following sync modes:
- Full Refresh
- Incremental
There are two types of incremental sync:
- Incremental (standard server-side, where API returns only the data updated or generated since the last sync)
- Client-Side Incremental (API returns all available data and connector filters out only new records)
Supported Streams
The HubSpot source connector supports the following streams:
- Campaigns (Client-Side Incremental)
- Companies (Incremental)
- Contact Lists (Incremental)
- Contacts (Incremental)
- Deal Pipelines (Client-Side Incremental)
- Deal Splits (Incremental)
- Deals (including Contact associations) (Incremental)
- Records that have been deleted (archived) and stored in HubSpot's recycle bin will only be kept for 90 days, see response from HubSpot Team
- Deals Archived (including Contact associations) (Incremental)
- Email Events (Incremental)
- Email Subscriptions
- Engagements (Incremental)
- Engagements Calls (Incremental)
- Engagements Emails (Incremental)
- Engagements Meetings (Incremental)
- Engagements Notes (Incremental)
- Engagements Tasks (Incremental)
- Forms (Client-Side Incremental)
- Form Submissions (Client-Side Incremental)
- Goals (Incremental)
- Leads (Incremental)
- List Memberships (Full Refresh)
- Line Items (Incremental)
- Marketing Emails (Incremental)
- Owners (Client-Side Incremental)
- Owners Archived (Client-Side Incremental)
- Users (Full-Refresh)
- Products (Incremental)
- Properties (Full Refresh)
- Contacts Property History (Client-Side Incremental)
- Companies Property History (Client-Side Incremental)
- Deals Property History (Client-Side Incremental)
- Subscription Changes (Incremental)
- Tickets (Incremental)
- Ticket Pipelines (Client-Side Incremental)
- Workflows (Client-Side Incremental)
- ContactsWebAnalytics (Incremental)
- CompaniesWebAnalytics (Incremental)
- DealsWebAnalytics (Incremental)
- TicketsWebAnalytics (Incremental)
- EngagementsCallsWebAnalytics (Incremental)
- EngagementsEmailsWebAnalytics (Incremental)
- EngagementsMeetingsWebAnalytics (Incremental)
- EngagementsNotesWebAnalytics (Incremental)
- EngagementsTasksWebAnalytics (Incremental)
- GoalsWebAnalytics (Incremental)
- LineItemsWebAnalytics (Incremental)
- ProductsWebAnalytics (Incremental)
- Account Details (Full Refresh)
Entity-Relationship Diagram (ERD)
Notes on the property_history streams
Property_history streams can be synced using an Incremental sync mode, which uses a cursor timestamp to determine which records have been updated since the previous sync. Within these streams, some fields types (ex. CALCULATED type) will always have a cursor timestamp that mirrors the time of the latest sync. This results in each sync including many more records than were necessarily changed since the previous sync.
Notes on the engagements stream
- Objects in the
engagementsstream can have one of the following types:note,email,task,meeting,call. Depending on the type of engagement, different properties are set for that object in theengagements_metadatatable in the destination:
- A
callengagement has a correspondingengagements_metadataobject with non-null values in thetoNumber,fromNumber,status,externalId,durationMilliseconds,externalAccountId,recordingUrl,body, anddispositioncolumns. - An
emailengagement has a correspondingengagements_metadataobject with non-null values in thesubject,html, andtextcolumns. In addition, there will be records in four related tables,engagements_metadata_from,engagements_metadata_to,engagements_metadata_cc,engagements_metadata_bcc. - A
meetingengagement has a correspondingengagements_metadataobject with non-null values in thebody,startTime,endTime, andtitlecolumns. - A
noteengagement has a correspondingengagements_metadataobject with non-null values in thebodycolumn. - A
taskengagement has a correspondingengagements_metadataobject with non-null values in thebody,status, andforObjectTypecolumns.
- The
engagementsstream uses two different APIs based on the length of time since the last sync and the number of records which Calabi Connect hasn't yet synced.
- EngagementsRecent if the following two criteria are met:
- The last sync was performed within the last 30 days
- Fewer than 10,000 records are being synced
- EngagementsAll if either of these criteria are not met.
Because of this, the engagements stream can be slow to sync if it hasn't synced within the last 30 days and/or is generating large volumes of new data. To accommodate for this limitation, we recommend scheduling more frequent syncs.
Notes on the Forms and Form Submissions stream
This stream only syncs marketing forms.
Notes on the Custom CRM Objects
Custom CRM Objects and Custom Web Analytics will appear as streams available for sync, alongside the standard objects listed above.
If you set up your connections before April 15th, 2023 (on Calabi Connect) or before 0.8.0 (OSS) then you'll need to do some additional work to sync custom CRM objects.
First you need to give the connector some additional permissions:
-
If you are using OAuth on Calabi Connect go to the Hubspot source settings page in the Calabi Connect UI and re-authenticate via OAuth to allow Calabi Connect the permissions to access custom objects.
-
If you are using OAuth on OSS or Private App auth go into the Hubspot UI where you created your Private App or OAuth application and add the
crm.objects.custom.readscope to your app's scopes. See HubSpot's instructions here.
Then, go to the schema tab of your connection and click refresh source schema to pull in those new streams for syncing.
Limitations & Troubleshooting
Expand to see details about Hubspot connector limitations and troubleshooting.
Rate limiting
The connector is restricted by normal HubSpot rate limits. The burst limit applies per app, and the daily limit is shared across all apps within the same HubSpot account.
| Product tier | Burst (per 10 seconds) | Daily (per account) |
|---|---|---|
| Free & Starter | 100 | 250,000 |
| Professional | 190 | 625,000 |
| Enterprise | 190 | 1,000,000 |
| API Limit Increase add-on | 250 | +1,000,000 per add-on (max 2) |
Custom properties sync slowly
If you use custom properties in HubSpot, syncs take longer. Calabi Connect doesn't alert you to the presence of custom properties, but you can check if you're using them with HubSpot's UI.
Troubleshooting
-
Enabling streams: Some streams, such as
workflows, require specific scopes before they can be read. If the authenticated user does not have the necessary permissions, the connector logs a warning and skips the stream. -
Hubspot object labels In Hubspot, a label can be applied to a stream that differs from the original API name of the stream. Hubspot's UI shows the label of the stream, whereas Calabi Connect shows the name of the stream. If you are having issues seeing a particular stream your user should have access to, search for the
nameof the Hubspot object instead. -
Unnesting top level properties: Since version 1.5.0, in order to offer users access to nested fields, we also denest the top-level fields into individual fields in the destination. This is most commonly observed in the
propertiesfield, which is now split into each attribute in the destination.For instance:
{
"id": 1,
"updatedAt": "2020-01-01",
"properties": {
"hs_note_body": "World's best boss",
"hs_created_by": "Michael Scott"
}
}becomes
{
"id": 1,
"updatedAt": "2020-01-01",
"properties": {
"hs_note_body": "World's best boss",
"hs_created_by": "Michael Scott"
},
"properties_hs_note_body": "World's best boss",
"properties_hs_created_by": "Michael Scott"
} -
401 Unauthorized Error (Private App Token)
If you authenticate using a Private App access token and receive a 401 Unauthorized error, the connector fails immediately with a configuration error asking you to update your token. Private App tokens are static and cannot be refreshed, so retrying won't help. To resolve this, generate a new access token in your HubSpot Private App settings and update the connector configuration.
If you authenticate using OAuth, the connector automatically refreshes expired tokens and retries the request. No action is needed unless the error persists, in which case you should re-authenticate the connector.
-
403 Forbidden Error
-
Hubspot has scopes for each API call.
-
Each stream is tied to a scope and will need access to that scope to sync data.
-
Review the Hubspot OAuth scope documentation here.
-
Additional permissions:
feedback_submissions: Service Hub Professional accountmarketing_emails: Market Hub Starter accountworkflows: Sales, Service, and Marketing Hub Professional accounts
-
-
Check out common troubleshooting issues for the Hubspot source connector on our Calabi Connect Forum.
-
Missing records in CRMSearch streams (
deals,companies,engagements_calls,engagements_emails,engagements_meetings,engagements_notes,engagements_tasks,contacts,deal_splits,leads,tickets):- If you notice missing records during incremental syncs, it may be due to irregularities in Hubspot's API behavior.
- To mitigate this, you can configure a lookback window in the source settings. This setting allows the connector to re-fetch data for a specified number of minutes before the state from the previous sync, helping to capture missing records.