hubspot-hello-world

Installation
SKILL.md

HubSpot Hello World

Overview

Create, read, update, and delete CRM records using the HubSpot API. Covers contacts, companies, and deals with real endpoints and SDK methods.

Prerequisites

  • Completed hubspot-install-auth setup
  • Private app with scopes: crm.objects.contacts.read, crm.objects.contacts.write
  • @hubspot/api-client installed

Instructions

Step 1: Create a Contact

import * 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

Step 2: Read a Contact

// 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}`);

Step 3: Update a Contact

// 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}`);

Step 4: Create a Company and Associate

// 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}`);

Step 5: Create a Deal

// 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})`);

Output

  • Created contact with properties and lifecycle stage
  • Read contact with specific properties and associations
  • Updated contact properties
  • Created company and associated it with the contact
  • Created deal associated with both contact and company

Error Handling

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

Examples

Search for Existing Contacts

// 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 (Archive) a Record

// DELETE /crm/v3/objects/contacts/{contactId}
await client.crm.contacts.basicApi.archive(contactResponse.id);
console.log('Contact archived');

Resources

Next Steps

Proceed to hubspot-local-dev-loop for development workflow setup.

Weekly Installs
1
GitHub Stars
2.1K
First Seen
Mar 25, 2026