HubSpot database schema
You can select to sync any of HubSpotâs standard CRM objects to your Sequin database:
- Companies
- Contacts
- Deals
- Line items
- Owners
- Products
- Quotes
- Tickets
- Meetings
- Calls
- Tasks
- Postal Mail
- Communications
- Notes
Additionally, Sequin can sync custom CRM objects and associations between any of these collections.
Need other objects in your sync? Just send us a note.
The syncing process
HubSpot OAuth Apps like Sequin have dedicated rate limits:
| API | Syncs | Request limit | Interval |
|---|
| Standard | Owners, Pipelines, Associations | 100 | 10 seconds |
| Search | Objects (e.g. Company, Contact, custom objects) | 4 | 1 second |
Because these limits are scoped to the OAuth application, Sequin wonât impact your existing API quota usage (whether from other OAuth apps or your own HubSpot Private app). Sequin selects the fastest API to use for each collection in each stage of your syncâs lifecycle and maximizes its consumption of the available rate limit.
Because your synced tables
share these rate limits, we recommend
syncing what you need. If you realize you arenât using one or more synced HubSpot tables,
removing it from your sync may speed up the other tables!
When you create a sync or update your selected columns, Sequin initializes your tables with the current state of your HubSpot data. After the initial backfill, it continuously polls those collections â either repeatedly sweeping a collection or listening for changed records â and updates your tables accordingly.
Because these rate limits are scoped to our OAuth app and your HubSpot workspace, we do not recommend syncing the same HubSpot workspace with more than one active Sequin sync.
Learn more about our syncing process.
Associations
When you associate two objects in HubSpot, the association is undirected. When Contact A is associated with Company X, Company X is reciprocally associated with Contact A.
You can use association labels to indicate the kind of association between two objects. For example, Contact A can be a Manager at Company X and also a Former Employee at Company Y; you would associate Contact A with both companies but label the associations differently.
For any pair of object types, Sequin syncs all associations between objects of those types to an associative table. For example, every association between a Contact and a Company syncs to the table associations_company_contact with the following structure:additional-fields
| Column name | Postgres type | Example value | Description |
|---|
| company_id | text | â9457785876â | The associated companyâs HubSpot ID. |
| contact_id | text | â36701â | The associated contactâs HubSpot ID. |
| labels | text[] | The associationâs labels. | |
Because HubSpot associations are undirected, these associations will only appear in one table: if you have a table associations_company_contact, there wonât be a table with the opposite order (associations_contact_company). These table names are a fixed function of the type names.
You can JOIN using the associations tables:
SELECT
-- Contact data.
contact.id, contact.email,
-- Data from the corresponding company.
company.id, company.city,
-- Label data from the associations table.
association.labels
FROM hubspot.associations_company_contact association
LEFT JOIN hubspot.company company ON company.id = association.company_id
LEFT JOIN hubspot.contact contact ON contact.id = association.contact_id;
This example uses Contact and Company, but the same patterns apply for any other HubSpot CRM objects you can sync with Sequin. For example, if you have custom Requests and custom Cars in HubSpot, Sequin would sync an associations_car_request table with the columns car_id and request_id.
To write back to HubSpot, youâll connect via Sequinâs Postgres Proxy. The Proxy listens for changes. When you make a mutation, the Proxy applies the mutation to HubSpotâs API first. If the mutation succeeds, your database is updated as well. If it fails, your database mutation will be rolled back, and youâll receive a Postgres error.
With this architecture, HubSpot is the source of truth. All your database changes are validated by HubSpotâs API first. Thereâs never a chance for the two to get out-of-sync.
To create a new record in the API, youâll use the insert command. Hereâs how to insert a HubSpot contact:
insert into hubspot.contacts (first_name, last_name, email)
values ('Paul', 'Atreides', '[email protected]')
returning id;
id
--------------------
0038b00002gszToAAI
(1 row)
An insert command must translate to a single API query. Because HubSpot does not allow for transactional batch inserts, inserts on HubSpot are limited to a single record at a time.
Without transactional batch inserts, bulk inserting records could get your data into an inconsistent state. For example, imagine you batch inserted 20 HubSpot contacts. 2 of them failed. Is your code going to pull those out and try them again? What about the other 18 you created successfully â should they remain created or do you want to roll them back?
To avoid these tricky situations, we limit HubSpot to one insert at a time. For updates and deletes, those are safe to retry, and so we donât impose the same limitation.
To update a record in the API, youâll use the update command. Hereâs how to update a HubSpot contact:
update hubspot.contacts
set email = `[email protected]`, note = 'Moved to new planet called Dune'
where id = '0038b00002gszToAAI';
UPDATE 0 1
(1 row)
An update command must translate to a single API query. That means you can update a maximum of 100 records at a time.
To delete a record in the API, youâll use the delete command. Hereâs how to delete a HubSpot contact:
A delete command must translate to a single API query. That means you can delete a maximum of 100 records at a time.
- There may be other fields in your table, like
_sync_hash, _sync_inserted_at, and _sync_updated_at. Donât be alarmed: Sequin uses these columns to keep data flowing into Postgres smoothly. Just donât tamper with this data