JSPM

@maxnate/provider-hubspot

0.1.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 16
  • Score
    100M100P100Q70609F
  • License MIT

HubSpot CRM provider for @maxnate/crm-core. Implements CrmProviderAdapter against HubSpot v3 CRM API with private-app bearer auth and HMAC-SHA256 webhook verification.

Package Exports

  • @maxnate/provider-hubspot

Readme

@maxnate/provider-hubspot

HubSpot CRM provider for @maxnate/crm-core.

Implements CrmProviderAdapter with contact upsert + search via the HubSpot CRM v3 API.

npm install @maxnate/provider-hubspot @maxnate/crm-core

Credentials

Field Description
accessToken HubSpot Private App access token (pat-...). Settings > Integrations > Private Apps.

OAuth flow tokens (oauth-...) are accepted in the same field but the adapter does not auto-refresh them. Use a Private App for unattended workloads.

Property Mapping

HubSpot property names are lowercase and snake_case (firstname, lastname, mobilephone). The provider accepts a propertyMap in CrmProviderConfig to translate canonical Contact fields to HubSpot property names:

propertyMap: {
  firstName: 'firstname',
  lastName: 'lastname',
  phone: 'mobilephone'
}

Custom properties pass through attributes unchanged.

Usage

import { createCrmProviderRegistry } from '@maxnate/crm-core'
import { HubSpotCrmProvider } from '@maxnate/provider-hubspot'

const registry = createCrmProviderRegistry({ configStore, secretsCodec })
registry.register(new HubSpotCrmProvider())

await registry.configureProvider('tenant-1', {
  id: 'hubspot', name: 'HubSpot', enabled: true,
  credentials: { accessToken: process.env.HUBSPOT_PRIVATE_APP_TOKEN! },
  propertyMap: { firstName: 'firstname', lastName: 'lastname' }
})

// Upsert (idempotent on email)
const result = await registry.upsertContact('tenant-1', 'hubspot', {
  email: 'jane@example.com',
  firstName: 'Jane',
  lastName: 'Doe',
  attributes: { lead_source: 'web', campaign: '2026-q2' }
})
// → { contactId: '12345', created: true }

// Search
const contacts = await registry.findContacts('tenant-1', 'hubspot', {
  email: 'jane@example.com',
  limit: 10
})

Idempotency

Contact upsert is idempotent on email — HubSpot is the source of truth for the vid / contactId. The adapter does not maintain its own idempotency cache for upserts; the provided CrmIdempotencyStore is used only for retried jobs.

Webhooks

HubSpot supports outbound webhooks signed with HMAC-SHA256 over the request body. The current adapter version does not ship a built-in webhook handler — wire your own route and use the HubSpot signature verification documented at https://developers.hubspot.com/docs/api/webhooks/validating-requests. A future release of @maxnate/crm-core will add a unified webhook surface.

Requirements

  • Node.js >= 18
  • @maxnate/crm-core ^0.1.0
  • HubSpot Private App with crm.objects.contacts.read and crm.objects.contacts.write scopes

License

MIT