@xenterprises/fastify-xhubspot
v1.2.1
Published
Fastify plugin for HubSpot CRM integration with contact management, engagement tracking, and custom objects support. Ideal for third-party portals managing contacts, companies, deals, and engagement notes.
Readme
@xenterprises/fastify-xhubspot
Fastify plugin for HubSpot CRM integration — contacts, companies, deals, engagements, and custom objects.
Install
npm install @xenterprises/fastify-xhubspotUsage
import Fastify from "fastify";
import xHubspot from "@xenterprises/fastify-xhubspot";
const fastify = Fastify();
await fastify.register(xHubspot, {
apiKey: process.env.HUBSPOT_ACCESS_TOKEN,
logRequests: false,
});
// Create a contact
const contact = await fastify.contacts.create({
email: "[email protected]",
firstname: "John",
lastname: "Doe",
});
// Add a note
await fastify.engagement.createNote(contact.id, "Initial onboarding call completed");Options
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| apiKey | string | — | Yes | HubSpot Private App access token |
| logRequests | boolean | false | No | Log each API call at debug level |
Decorated Properties
fastify.hubspot
The raw @hubspot/api-client Client instance for direct API access.
fastify.contacts
| Method | Arguments | Returns | Description |
|--------|-----------|---------|-------------|
| create(data) | CrmProperties | CrmObject | Create a contact |
| getById(id, props?) | string, string[] | CrmObject | Get contact by ID |
| getByEmail(email, props?) | string, string[] | CrmObject & { email } | Get contact by email |
| update(id, props) | string, CrmProperties | CrmObject | Update contact |
| delete(id) | string | true | Archive contact |
| list(opts?) | { limit?, after?, sort? } | { contacts, paging } | List contacts with pagination |
| search(prop, value) | string, string | CrmObject[] | Search by property value |
| batchCreate(contacts) | CrmProperties[] | CrmObject[] | Create up to 100 contacts |
| batchUpdate(contacts) | { id, properties }[] | CrmObject[] | Update up to 100 contacts |
| getAssociations(id, type) | string, string | Association[] | Get associated objects |
| associate(id, objectId, type) | string, string, string | true | Create association |
fastify.companies
| Method | Arguments | Returns | Description |
|--------|-----------|---------|-------------|
| create(data) | CrmProperties | CrmObject | Create a company |
| getById(id, props?) | string, string[] | CrmObject | Get company by ID |
| getByDomain(domain, props?) | string, string[] | CrmObject | Find company by domain |
| update(id, props) | string, CrmProperties | CrmObject | Update company |
| delete(id) | string | true | Archive company |
| list(opts?) | { limit?, after? } | { companies, paging } | List companies |
| search(prop, value) | string, string | CrmObject[] | Search by property |
| batchCreate(companies) | CrmProperties[] | CrmObject[] | Create up to 100 |
| batchUpdate(companies) | { id, properties }[] | CrmObject[] | Update up to 100 |
| getAssociations(id, type) | string, string | Association[] | Get associations |
fastify.deals
| Method | Arguments | Returns | Description |
|--------|-----------|---------|-------------|
| create(data) | CrmProperties | CrmObject | Create a deal |
| getById(id, props?) | string, string[] | CrmObject | Get deal by ID |
| update(id, props) | string, CrmProperties | CrmObject | Update deal |
| delete(id) | string | true | Archive deal |
| list(opts?) | { limit?, after? } | { deals, paging } | List deals |
| search(prop, value) | string, string | CrmObject[] | Search by property |
| batchCreate(deals) | CrmProperties[] | CrmObject[] | Create up to 100 |
| getAssociations(id, type) | string, string | Association[] | Get associations |
fastify.engagement
| Method | Arguments | Returns | Description |
|--------|-----------|---------|-------------|
| createNote(contactId, body, ownerId?) | string, string, string? | EngagementResult | Create a note |
| createTask(contactId, taskData) | string, TaskData | EngagementResult | Create a task |
| createCall(contactId, callData) | string, CallData | EngagementResult | Log a call |
| createEmail(contactId, emailData) | string, EmailData | EngagementResult | Log an email |
| getEngagements(contactId) | string | { engagements, total } | All engagements for contact |
| getNotes(contactId, limit?) | string, number? | CrmObject[] | List notes |
| getTasks(contactId, limit?) | string, number? | CrmObject[] | List tasks |
| getCalls(contactId, limit?) | string, number? | CrmObject[] | List calls |
| getEmails(contactId, limit?) | string, number? | CrmObject[] | List emails |
fastify.customObjects
| Method | Arguments | Returns | Description |
|--------|-----------|---------|-------------|
| create(type, data) | string, CrmProperties | CrmObject | Create custom object |
| getById(type, id, props?) | string, string, string[] | CrmObject | Get by ID |
| update(type, id, props) | string, string, CrmProperties | CrmObject | Update |
| delete(type, id) | string, string | true | Archive |
| list(type, opts?) | string, { limit?, after? } | { objects, paging } | List |
| search(type, prop, value) | string, string, string | CrmObject[] | Search |
| batchCreate(type, objects) | string, CrmProperties[] | CrmObject[] | Batch create |
| associate(type, id, toType, toId, assocTypeId?) | string, string, string, string, number? | true | Create association |
| getAssociations(type, id, assocType) | string, string, string | Association[] | Get associations |
Environment Variables
| Name | Required | Description |
|------|----------|-------------|
| HUBSPOT_ACCESS_TOKEN | Yes | HubSpot Private App access token |
Error Reference
All errors use the [xHubspot] prefix. Common errors:
| Error | Cause |
|-------|-------|
| [xHubspot] apiKey is required and must be a non-empty string | Missing or invalid apiKey option |
| [xHubspot] logRequests must be a boolean | Non-boolean logRequests value |
| [xHubspot] contacts.create requires a contactData object | Null/non-object passed to create |
| [xHubspot] contacts.getById requires a contactId | Empty/falsy contactId |
| [xHubspot] Company not found for domain: x | getByDomain() found no match (has .status = 404) |
All HubSpot API errors are propagated with their original message. Errors from the API include the HubSpot correlation ID.
How It Works
- Registration — the plugin validates
apiKeyandlogRequests, then creates a@hubspot/api-clientClient instance. - Decorators — five service objects are decorated onto the Fastify instance:
contacts,companies,deals,engagement, andcustomObjects. Each wraps the HubSpot v3 CRM API with input validation and error logging. - Input validation — every public method validates its arguments before calling HubSpot. Invalid inputs throw synchronously with descriptive messages.
- Error handling — API call failures are caught, logged via
fastify.log.error, and re-thrown so route handlers can respond with appropriate HTTP status codes. - Logging — when
logRequests: true, each API call logs a debug message before execution. No secrets or tokens are ever logged. - Stateless — the plugin holds no state beyond the HubSpot client reference. It is safe to register in multiple scopes.
License
UNLICENSED
