Overview
HubSpot's API is authenticated with a Private App access token — a long-lived bearer token that you create inside the HubSpot UI and scope to the data Ingest should read. This is HubSpot's recommended pattern for server-to-server integrations on a single account; OAuth2 is also supported but unnecessary unless you're building a multi-tenant marketplace app.
The available endpoints depend on your HubSpot subscription tier — most CRM endpoints work on Free, but Marketing, Service Hub Pro features (feedback_submissions, goals), Enterprise-only features (schemas, roles), Marketing Hub Starter+ (files, folders), and Content Hub (blog_*, landing_pages, site_pages, hubdb_*) require the corresponding paid subscription.
Setup guide
Create the Private App token
- Sign in to HubSpot.
- Click the gear icon (top right) to open Settings.
- In the left sidebar: Integrations → Private Apps.
- Click Create a private app, give it a name (e.g.
ingest), and an optional description. - Switch to the Scopes tab and check the scope for every object type you want Ingest to read. The most common picks are:
crm.objects.contacts.read,crm.objects.companies.read,crm.objects.deals.read,crm.objects.tickets.read,crm.objects.line_items.read,crm.objects.products.read,crm.lists.read,crm.objects.owners.read,tickets,e-commerce,forms,automation,content,files, andbusiness-intelligence. Add others as your endpoint selection grows. - Click Create app and copy the access token shown on the next screen. The full token is only shown once.
Add it to Ingest
In the Ingest UI under Connectors → HubSpot, paste the token. Ingest stores it in AWS Secrets Manager under the key token. The runtime sends it as Authorization: Bearer <token> on every request.
Mind the limits
A HubSpot Private App on Free/Starter has two limits in play simultaneously: a burst ceiling of 100 requests per 10-second window, and a daily ceiling of 250,000 requests. The Ingest runtime dispatches at 5 req/sec globally to respect HubSpot's separate Search-endpoint limit (also 5 req/sec) and uses AIMD backoff if 429s appear.
Errors with status 400 (malformed request), 401 (bad/expired token), 403 (scope missing or paid feature on a Free workspace), and 404 (object id not found) are treated as fatal — fix the cause before retrying.
Pick endpoints
HubSpot's API is large — 66 endpoints in this connector. Most customers want the CRM core (contacts, companies, deals, tickets, plus their *_properties lookups for the field schema) and the Engagement objects (notes, calls, emails, meetings, tasks). Pipelines, owners, lists, and search variants round out the CRM workflow. Marketing, automation, analytics, and CMS endpoints are tier-gated; see each endpoint's description for the subscription requirement.
The cascade is mostly flat — every endpoint takes a token and queries directly. The exceptions:
lists_search→list_memberships(lists must be enumerated first)threads→thread_messages(one set of messages per conversation thread)hubdb_tables→hubdb_rows(rows are scoped to a table)association_labels/association_definitionsuse enum-templated URLs ({from_object}×{to_object}); the generator enumerates the cross-product.
Supported streams
42 endpoints are available out of the box. Each endpoint syncs into its own Iceberg table in Snowflake.
| Endpoint | Description | Reference |
|---|---|---|
| actors actors | – | |
| association_definitions association_definitions | – | |
| association_labels association_labels | – | |
| calls calls | – | |
| channel_accounts channel_accounts | – | |
| channels channels | – | |
| communications communications | – | |
| companies companies | – | |
| companies_properties companies_properties | – | |
| companies_search companies_search | – | |
| contacts contacts | – | |
| contacts_properties contacts_properties | – | |
| contacts_search contacts_search | – | |
| deals deals | – | |
| deals_properties deals_properties | – | |
| deals_search deals_search | – | |
| emails emails | – | |
| forms forms | – | |
| imports imports | – | |
| inboxes inboxes | – | |
| line_items line_items | – | |
| line_items_properties line_items_properties | – | |
| list_memberships list_memberships | – | |
| lists_search lists_search | – | |
| meetings meetings | – | |
| notes notes | – | |
| owners owners | – | |
| pipelines_deals pipelines_deals | – | |
| pipelines_tickets pipelines_tickets | – | |
| postal_mail postal_mail | – | |
| products products | – | |
| products_properties products_properties | – | |
| quotes quotes | – | |
| quotes_properties quotes_properties | – | |
| tasks tasks | – | |
| taxes taxes | – | |
| teams teams | – | |
| threads threads | – | |
| tickets tickets | – | |
| tickets_properties tickets_properties | – | |
| tickets_search tickets_search | – | |
| users users | – |
Authentication
- Auth type
- Bearer Token
- Sent as header
Authorization- Provider docs
- developers.hubspot.com ↗
Performance & limits
- Rate limit
- Private App on Free/Starter — 100 req/10s + 250,000 req/day. Search endpoints have a separate 5 req/s ceiling. Ingest dispatches at 5 req/s globally to respect the search cap and lets AIMD tune up where higher rates are allowed.