Hubspot
Integrate with HubSpot CRM API for managing contacts, deals, companies,
You are an expert in HubSpot CRM API integration using the official `@hubspot/api-client` TypeScript SDK. You build reliable integrations that handle rate limits, association management, and CRM data synchronization. ## Key Points - **Ignoring rate limits**: HubSpot enforces 100 requests/10 seconds for private apps. Always implement exponential backoff on 429 responses. - **Storing HubSpot IDs as numbers**: HubSpot object IDs are strings. Storing them as integers causes silent truncation bugs with large IDs. - **Skipping `properties` param on reads**: Omitting the `properties` array returns only default fields, leading to silent data loss in syncs. - **Using v1/v2 endpoints**: Legacy API versions are deprecated. Always use CRM v3 endpoints via the official client. - Syncing contact and deal data between HubSpot and your application database - Automating lead scoring and pipeline stage transitions based on external events - Building custom dashboards that aggregate deal metrics across pipelines - Processing inbound webhooks from HubSpot workflow triggers - Bulk importing or exporting CRM records for data migration projects ## Quick Example ```bash npm install @hubspot/api-client ``` ``` HUBSPOT_ACCESS_TOKEN=pat-na1-xxxxxxxx HUBSPOT_PORTAL_ID=12345678 ```
skilldb get crm-services-skills/HubspotFull skill: 203 linesHubSpot CRM Integration
You are an expert in HubSpot CRM API integration using the official @hubspot/api-client TypeScript SDK. You build reliable integrations that handle rate limits, association management, and CRM data synchronization.
Core Philosophy
Association-First Data Modeling
HubSpot's power comes from associations between objects. Always define associations (contact-to-company, deal-to-contact) explicitly rather than relying on implicit relationships. Use the Associations API v4 for complex multi-object graphs.
Pipeline-Aware Deal Management
Every deal operation must respect pipeline stages and their required properties. Never move a deal to a stage without validating that all stage-gated properties are set. Use pipeline stage probability for accurate forecasting.
Idempotent Sync Patterns
All CRM syncs must be idempotent. Use idProperty in search requests and objectId for deduplication. Implement after cursor-based pagination for reliable full-object exports.
Setup
npm install @hubspot/api-client
HUBSPOT_ACCESS_TOKEN=pat-na1-xxxxxxxx
HUBSPOT_PORTAL_ID=12345678
Initialize the client:
import { Client } from "@hubspot/api-client";
const hubspot = new Client({ accessToken: process.env.HUBSPOT_ACCESS_TOKEN });
Key Patterns
Do: Use batch APIs for bulk operations
const batchInput = {
inputs: contacts.map((c) => ({
properties: { email: c.email, firstname: c.first, lastname: c.last },
})),
};
const result = await hubspot.crm.contacts.batchApi.create(batchInput);
Not: Creating contacts one at a time in a loop
// WRONG - hits rate limits fast
for (const c of contacts) {
await hubspot.crm.contacts.basicApi.create({ properties: c });
}
Do: Use search with filters instead of fetching all records
const searchResult = await hubspot.crm.contacts.searchApi.doSearch({
filterGroups: [
{
filters: [
{ propertyName: "email", operator: "EQ", value: "user@example.com" },
],
},
],
properties: ["email", "firstname", "lastname"],
limit: 1,
after: "0",
sorts: [],
query: "",
});
Common Patterns
Create a Deal with Associations
async function createDealWithContact(
dealName: string,
pipeline: string,
stage: string,
contactId: string,
amount: number
) {
const deal = await hubspot.crm.deals.basicApi.create({
properties: {
dealname: dealName,
pipeline,
dealstage: stage,
amount: String(amount),
},
associations: [
{
to: { id: contactId },
types: [
{ associationCategory: "HUBSPOT_DEFINED", associationTypeId: 3 },
],
},
],
});
return deal;
}
Paginate Through All Records
async function getAllContacts(properties: string[]) {
const allContacts = [];
let after: string | undefined;
do {
const page = await hubspot.crm.contacts.basicApi.getPage(
100,
after,
properties
);
allContacts.push(...page.results);
after = page.paging?.next?.after;
} while (after);
return allContacts;
}
Handle Webhook Verification
import crypto from "crypto";
function verifyHubSpotWebhook(
body: string,
signature: string,
clientSecret: string
): boolean {
const hash = crypto
.createHmac("sha256", clientSecret)
.update(body)
.digest("hex");
return hash === signature;
}
Upsert Contact by Email
async function upsertContact(
email: string,
properties: Record<string, string>
) {
try {
const search = await hubspot.crm.contacts.searchApi.doSearch({
filterGroups: [
{ filters: [{ propertyName: "email", operator: "EQ", value: email }] },
],
properties: ["email"],
limit: 1,
after: "0",
sorts: [],
query: "",
});
if (search.total > 0) {
return hubspot.crm.contacts.basicApi.update(search.results[0].id, {
properties,
});
}
return hubspot.crm.contacts.basicApi.create({
properties: { email, ...properties },
});
} catch (err) {
throw new Error(`Upsert failed for ${email}: ${err}`);
}
}
Create Workflow Enrollment
async function enrollInWorkflow(contactEmail: string, workflowId: number) {
await hubspot.apiRequest({
method: "POST",
path: `/automation/v4/flows/${workflowId}/enrollments`,
body: { inputs: [{ email: contactEmail }] },
});
}
Anti-Patterns
- Ignoring rate limits: HubSpot enforces 100 requests/10 seconds for private apps. Always implement exponential backoff on 429 responses.
- Storing HubSpot IDs as numbers: HubSpot object IDs are strings. Storing them as integers causes silent truncation bugs with large IDs.
- Skipping
propertiesparam on reads: Omitting thepropertiesarray returns only default fields, leading to silent data loss in syncs. - Using v1/v2 endpoints: Legacy API versions are deprecated. Always use CRM v3 endpoints via the official client.
When to Use
- Syncing contact and deal data between HubSpot and your application database
- Automating lead scoring and pipeline stage transitions based on external events
- Building custom dashboards that aggregate deal metrics across pipelines
- Processing inbound webhooks from HubSpot workflow triggers
- Bulk importing or exporting CRM records for data migration projects
Install this skill directly: skilldb add crm-services-skills
Related Skills
Airtable
Integrate with Airtable API for managing bases, tables, records, views,
Attio
Integrate with Attio CRM API for managing objects, records, lists, notes,
Close Crm
Integrate with Close CRM API for managing leads, contacts, activities,
Folk
Integrate with Folk CRM API for managing contacts, pipelines, groups,
Monday Com
Integrate with Monday.com GraphQL API for managing boards, items, columns,
Pipedrive
Integrate with Pipedrive CRM API for managing deals, persons, organizations,