From hubspot-pack
Create a working HubSpot CRM example with contacts, companies, and deals. Use when starting a new HubSpot integration, testing your setup, or learning basic CRM API patterns with real endpoints. Trigger with phrases like "hubspot hello world", "hubspot example", "hubspot quick start", "first hubspot API call", "hubspot contact create".
npx claudepluginhub flight505/skill-forge --plugin hubspot-packThis skill is limited to using the following tools:
Create, read, update, and delete CRM records using the HubSpot API. Covers contacts, companies, and deals with real endpoints and SDK methods.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Create, read, update, and delete CRM records using the HubSpot API. Covers contacts, companies, and deals with real endpoints and SDK methods.
hubspot-install-auth setupcrm.objects.contacts.read, crm.objects.contacts.write@hubspot/api-client installedimport * as hubspot from '@hubspot/api-client';
const client = new hubspot.Client({
accessToken: process.env.HUBSPOT_ACCESS_TOKEN!,
});
// POST /crm/v3/objects/contacts
const contactResponse = await client.crm.contacts.basicApi.create({
properties: {
firstname: 'Jane',
lastname: 'Doe',
email: 'jane.doe@example.com',
phone: '(555) 123-4567',
company: 'Acme Corp',
lifecyclestage: 'lead',
},
associations: [],
});
console.log(`Created contact: ${contactResponse.id}`);
// Output: Created contact: 12345
// GET /crm/v3/objects/contacts/{contactId}
const contact = await client.crm.contacts.basicApi.getById(
contactResponse.id,
['firstname', 'lastname', 'email', 'phone', 'lifecyclestage'],
undefined, // propertiesWithHistory
['companies'] // associations to include
);
console.log(`${contact.properties.firstname} ${contact.properties.lastname}`);
console.log(`Email: ${contact.properties.email}`);
console.log(`Stage: ${contact.properties.lifecyclestage}`);
// PATCH /crm/v3/objects/contacts/{contactId}
const updated = await client.crm.contacts.basicApi.update(
contactResponse.id,
{
properties: {
lifecyclestage: 'marketingqualifiedlead',
phone: '(555) 987-6543',
},
}
);
console.log(`Updated at: ${updated.updatedAt}`);
// POST /crm/v3/objects/companies
const company = await client.crm.companies.basicApi.create({
properties: {
name: 'Acme Corp',
domain: 'acme.com',
industry: 'TECHNOLOGY',
numberofemployees: '150',
annualrevenue: '5000000',
},
associations: [],
});
// Associate contact with company
// PUT /crm/v4/objects/contacts/{contactId}/associations/companies/{companyId}
await client.crm.associations.v4.basicApi.create(
'contacts',
contactResponse.id,
'companies',
company.id,
[{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 1 }]
);
console.log(`Associated contact ${contactResponse.id} with company ${company.id}`);
// POST /crm/v3/objects/deals
const deal = await client.crm.deals.basicApi.create({
properties: {
dealname: 'Acme Enterprise License',
amount: '50000',
dealstage: 'appointmentscheduled', // default pipeline stage ID
pipeline: 'default',
closedate: '2026-06-30T00:00:00.000Z',
hubspot_owner_id: '12345', // owner user ID
},
associations: [
{
to: { id: company.id },
types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 5 }],
},
{
to: { id: contactResponse.id },
types: [{ associationCategory: 'HUBSPOT_DEFINED', associationTypeId: 3 }],
},
],
});
console.log(`Created deal: ${deal.properties.dealname} ($${deal.properties.amount})`);
| Error | Code | Cause | Solution |
|---|---|---|---|
409 Conflict | 409 | Contact with email already exists | Use crm.contacts.basicApi.getById or search first |
400 Bad Request | 400 | Invalid property name or value | Check property names in Settings > Properties |
404 Not Found | 404 | Record ID doesn't exist | Verify ID or check if archived |
PROPERTY_DOESNT_EXIST | 400 | Custom property not created | Create in Settings > Properties first |
// POST /crm/v3/objects/contacts/search
const searchResults = await client.crm.contacts.searchApi.doSearch({
filterGroups: [
{
filters: [
{
propertyName: 'email',
operator: 'EQ',
value: 'jane.doe@example.com',
},
],
},
],
properties: ['firstname', 'lastname', 'email'],
limit: 10,
after: 0,
sorts: [{ propertyName: 'createdate', direction: 'DESCENDING' }],
});
console.log(`Found ${searchResults.total} contact(s)`);
// DELETE /crm/v3/objects/contacts/{contactId}
await client.crm.contacts.basicApi.archive(contactResponse.id);
console.log('Contact archived');
Proceed to hubspot-local-dev-loop for development workflow setup.