chub-dev 0.1.0 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1805 @@
1
+ ---
2
+ name: crm
3
+ description: "HubSpot Node.js SDK for managing CRM contacts, companies, deals, and marketing automation via the HubSpot API."
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "13.4.0"
7
+ updated-on: "2026-03-01"
8
+ source: maintainer
9
+ tags: "hubspot,crm,marketing,contacts,automation"
10
+ ---
11
+
12
+ # HubSpot JavaScript/Node.js SDK Coding Guidelines
13
+
14
+ You are a HubSpot API coding expert. Help me write code using the HubSpot API with the official Node.js SDK.
15
+
16
+ Official SDK documentation and code samples:
17
+ https://developers.hubspot.com/docs/api/overview
18
+
19
+ ## Golden Rule: Use the Correct and Current SDK
20
+
21
+ Always use the official HubSpot Node.js SDK (`@hubspot/api-client`), which is the standard library for all HubSpot API interactions. Do not use deprecated or unofficial packages.
22
+
23
+ - **Library Name:** HubSpot Node.js SDK
24
+ - **NPM Package:** `@hubspot/api-client`
25
+ - **Current Version:** 13.4.0
26
+ - **Deprecated Packages:** `hubspot`, `hubspot-api`, `@hubspot/integrations-framework-actions` (do not use these)
27
+
28
+ **Installation:**
29
+
30
+ - **Correct:** `npm install @hubspot/api-client`
31
+ - **Incorrect:** `npm install hubspot` or `npm install hubspot-api`
32
+
33
+ **APIs and Usage:**
34
+
35
+ - **Correct:** `const hubspot = require('@hubspot/api-client')`
36
+ - **Correct:** `const hubspotClient = new hubspot.Client({ accessToken: token })`
37
+ - **Correct:** `await hubspotClient.crm.contacts.basicApi.create(...)`
38
+ - **Incorrect:** `HubspotClient` or `HubspotAPI`
39
+ - **Incorrect:** Legacy v2 API endpoints
40
+
41
+ ## Installation
42
+
43
+ Install the SDK via npm:
44
+
45
+ ```bash
46
+ npm install @hubspot/api-client
47
+ ```
48
+
49
+ For TypeScript projects, the SDK includes built-in type definitions.
50
+
51
+ ## Authentication
52
+
53
+ HubSpot API uses access tokens for authentication. There are three types of access tokens:
54
+
55
+ 1. **Private App Access Tokens** (recommended for server-side integrations)
56
+ 2. **OAuth Access Tokens** (for public apps and integrations)
57
+ 3. **Legacy API Keys** (deprecated, will be revoked November 19, 2025)
58
+
59
+ ### Environment Variable Configuration
60
+
61
+ Set your access token as an environment variable:
62
+
63
+ ```bash
64
+ # .env file
65
+ HUBSPOT_ACCESS_TOKEN=your_access_token_here
66
+ ```
67
+
68
+ **Creating a Private App:**
69
+
70
+ 1. Navigate to Settings > Integrations > Private Apps in your HubSpot account
71
+ 2. Click "Create private app"
72
+ 3. Configure the required scopes (permissions)
73
+ 4. Click "Create app" and copy the access token
74
+
75
+ ## Initialization
76
+
77
+ ### Basic Initialization
78
+
79
+ ```javascript
80
+ const hubspot = require('@hubspot/api-client');
81
+
82
+ // Initialize with access token from environment variable
83
+ const hubspotClient = new hubspot.Client({
84
+ accessToken: process.env.HUBSPOT_ACCESS_TOKEN
85
+ });
86
+ ```
87
+
88
+ ### Initialization with OAuth
89
+
90
+ ```javascript
91
+ const hubspot = require('@hubspot/api-client');
92
+
93
+ const hubspotClient = new hubspot.Client({
94
+ accessToken: 'YOUR_OAUTH_ACCESS_TOKEN'
95
+ });
96
+
97
+ // Refresh token when needed
98
+ hubspotClient.setAccessToken('NEW_ACCESS_TOKEN');
99
+ ```
100
+
101
+ ### Initialization with Rate Limiting Options
102
+
103
+ ```javascript
104
+ const hubspot = require('@hubspot/api-client');
105
+
106
+ const hubspotClient = new hubspot.Client({
107
+ accessToken: process.env.HUBSPOT_ACCESS_TOKEN,
108
+ limiterOptions: {
109
+ maxConcurrent: 5,
110
+ minTime: 100
111
+ }
112
+ });
113
+ ```
114
+
115
+ ## CRM API - Contacts
116
+
117
+ ### Create a Contact
118
+
119
+ **Basic Example:**
120
+
121
+ ```javascript
122
+ const hubspot = require('@hubspot/api-client');
123
+ const hubspotClient = new hubspot.Client({ accessToken: process.env.HUBSPOT_ACCESS_TOKEN });
124
+
125
+ async function createContact() {
126
+ const contactObj = {
127
+ properties: {
128
+ email: 'example@company.com',
129
+ firstname: 'John',
130
+ lastname: 'Doe',
131
+ phone: '555-0100',
132
+ company: 'Example Company',
133
+ website: 'example.com'
134
+ }
135
+ };
136
+
137
+ try {
138
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.create(contactObj);
139
+ console.log('Contact created:', apiResponse.id);
140
+ return apiResponse;
141
+ } catch (error) {
142
+ console.error('Error creating contact:', error.message);
143
+ }
144
+ }
145
+
146
+ createContact();
147
+ ```
148
+
149
+ **Advanced Example with Custom Properties:**
150
+
151
+ ```javascript
152
+ async function createContactAdvanced() {
153
+ const contactObj = {
154
+ properties: {
155
+ email: 'jane@example.com',
156
+ firstname: 'Jane',
157
+ lastname: 'Smith',
158
+ phone: '555-0200',
159
+ company: 'Tech Corp',
160
+ jobtitle: 'Software Engineer',
161
+ lifecyclestage: 'lead',
162
+ hs_lead_status: 'NEW',
163
+ // Custom properties
164
+ custom_field: 'custom_value',
165
+ industry: 'Technology'
166
+ }
167
+ };
168
+
169
+ try {
170
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.create(contactObj);
171
+ console.log('Contact created with ID:', apiResponse.id);
172
+ console.log('Properties:', apiResponse.properties);
173
+ return apiResponse;
174
+ } catch (error) {
175
+ if (error.statusCode === 409) {
176
+ console.error('Contact with this email already exists');
177
+ } else {
178
+ console.error('Error creating contact:', error.message);
179
+ }
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### Get a Contact
185
+
186
+ **By ID:**
187
+
188
+ ```javascript
189
+ async function getContact(contactId) {
190
+ try {
191
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.getById(
192
+ contactId,
193
+ ['email', 'firstname', 'lastname', 'phone', 'company'] // properties to return
194
+ );
195
+ console.log('Contact:', apiResponse.properties);
196
+ return apiResponse;
197
+ } catch (error) {
198
+ console.error('Error fetching contact:', error.message);
199
+ }
200
+ }
201
+ ```
202
+
203
+ **By Email:**
204
+
205
+ ```javascript
206
+ async function getContactByEmail(email) {
207
+ const filter = { propertyName: 'email', operator: 'EQ', value: email };
208
+ const filterGroup = { filters: [filter] };
209
+ const sort = JSON.stringify({ propertyName: 'createdate', direction: 'DESCENDING' });
210
+ const properties = ['email', 'firstname', 'lastname'];
211
+ const limit = 1;
212
+
213
+ try {
214
+ const apiResponse = await hubspotClient.crm.contacts.searchApi.doSearch({
215
+ filterGroups: [filterGroup],
216
+ sorts: [sort],
217
+ properties,
218
+ limit
219
+ });
220
+
221
+ if (apiResponse.total > 0) {
222
+ return apiResponse.results[0];
223
+ }
224
+ return null;
225
+ } catch (error) {
226
+ console.error('Error searching contact:', error.message);
227
+ }
228
+ }
229
+ ```
230
+
231
+ ### Update a Contact
232
+
233
+ ```javascript
234
+ async function updateContact(contactId) {
235
+ const properties = {
236
+ firstname: 'Updated Name',
237
+ phone: '555-9999',
238
+ lifecyclestage: 'opportunity'
239
+ };
240
+
241
+ try {
242
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.update(
243
+ contactId,
244
+ { properties }
245
+ );
246
+ console.log('Contact updated:', apiResponse.id);
247
+ return apiResponse;
248
+ } catch (error) {
249
+ console.error('Error updating contact:', error.message);
250
+ }
251
+ }
252
+ ```
253
+
254
+ ### List Contacts
255
+
256
+ **Basic Pagination:**
257
+
258
+ ```javascript
259
+ async function listContacts() {
260
+ const limit = 10;
261
+ const properties = ['email', 'firstname', 'lastname', 'company'];
262
+
263
+ try {
264
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.getPage(
265
+ limit,
266
+ undefined, // after (for pagination)
267
+ properties
268
+ );
269
+
270
+ console.log(`Found ${apiResponse.results.length} contacts`);
271
+ apiResponse.results.forEach(contact => {
272
+ console.log(`${contact.properties.firstname} ${contact.properties.lastname}`);
273
+ });
274
+
275
+ return apiResponse;
276
+ } catch (error) {
277
+ console.error('Error listing contacts:', error.message);
278
+ }
279
+ }
280
+ ```
281
+
282
+ **Get All Contacts (with pagination handling):**
283
+
284
+ ```javascript
285
+ async function getAllContacts() {
286
+ const allContacts = [];
287
+ let after = undefined;
288
+ const limit = 100;
289
+
290
+ try {
291
+ do {
292
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.getPage(
293
+ limit,
294
+ after,
295
+ ['email', 'firstname', 'lastname']
296
+ );
297
+
298
+ allContacts.push(...apiResponse.results);
299
+ after = apiResponse.paging?.next?.after;
300
+
301
+ } while (after);
302
+
303
+ console.log(`Total contacts retrieved: ${allContacts.length}`);
304
+ return allContacts;
305
+ } catch (error) {
306
+ console.error('Error getting all contacts:', error.message);
307
+ }
308
+ }
309
+ ```
310
+
311
+ ### Delete a Contact
312
+
313
+ ```javascript
314
+ async function deleteContact(contactId) {
315
+ try {
316
+ await hubspotClient.crm.contacts.basicApi.archive(contactId);
317
+ console.log('Contact deleted:', contactId);
318
+ } catch (error) {
319
+ console.error('Error deleting contact:', error.message);
320
+ }
321
+ }
322
+ ```
323
+
324
+ ## CRM API - Companies
325
+
326
+ ### Create a Company
327
+
328
+ ```javascript
329
+ async function createCompany() {
330
+ const companyObj = {
331
+ properties: {
332
+ name: 'Example Company',
333
+ domain: 'example.com',
334
+ city: 'San Francisco',
335
+ state: 'California',
336
+ industry: 'Technology',
337
+ phone: '555-0100',
338
+ numberofemployees: '50',
339
+ description: 'A technology company'
340
+ }
341
+ };
342
+
343
+ try {
344
+ const apiResponse = await hubspotClient.crm.companies.basicApi.create(companyObj);
345
+ console.log('Company created:', apiResponse.id);
346
+ return apiResponse;
347
+ } catch (error) {
348
+ console.error('Error creating company:', error.message);
349
+ }
350
+ }
351
+ ```
352
+
353
+ ### Get a Company
354
+
355
+ ```javascript
356
+ async function getCompany(companyId) {
357
+ const properties = ['name', 'domain', 'city', 'industry', 'phone'];
358
+
359
+ try {
360
+ const apiResponse = await hubspotClient.crm.companies.basicApi.getById(
361
+ companyId,
362
+ properties
363
+ );
364
+ console.log('Company:', apiResponse.properties);
365
+ return apiResponse;
366
+ } catch (error) {
367
+ console.error('Error fetching company:', error.message);
368
+ }
369
+ }
370
+ ```
371
+
372
+ ### Update a Company
373
+
374
+ ```javascript
375
+ async function updateCompany(companyId) {
376
+ const properties = {
377
+ name: 'Updated Company Name',
378
+ numberofemployees: '100',
379
+ annualrevenue: '1000000'
380
+ };
381
+
382
+ try {
383
+ const apiResponse = await hubspotClient.crm.companies.basicApi.update(
384
+ companyId,
385
+ { properties }
386
+ );
387
+ console.log('Company updated:', apiResponse.id);
388
+ return apiResponse;
389
+ } catch (error) {
390
+ console.error('Error updating company:', error.message);
391
+ }
392
+ }
393
+ ```
394
+
395
+ ### List Companies
396
+
397
+ ```javascript
398
+ async function listCompanies() {
399
+ const limit = 10;
400
+ const properties = ['name', 'domain', 'city', 'industry'];
401
+
402
+ try {
403
+ const apiResponse = await hubspotClient.crm.companies.basicApi.getPage(
404
+ limit,
405
+ undefined,
406
+ properties
407
+ );
408
+
409
+ console.log(`Found ${apiResponse.results.length} companies`);
410
+ return apiResponse;
411
+ } catch (error) {
412
+ console.error('Error listing companies:', error.message);
413
+ }
414
+ }
415
+ ```
416
+
417
+ ## CRM API - Deals
418
+
419
+ ### Create a Deal
420
+
421
+ ```javascript
422
+ async function createDeal() {
423
+ const dealObj = {
424
+ properties: {
425
+ dealname: 'New Deal',
426
+ dealstage: 'appointmentscheduled',
427
+ amount: '10000',
428
+ closedate: '2025-12-31',
429
+ pipeline: 'default',
430
+ hubspot_owner_id: '12345'
431
+ }
432
+ };
433
+
434
+ try {
435
+ const apiResponse = await hubspotClient.crm.deals.basicApi.create(dealObj);
436
+ console.log('Deal created:', apiResponse.id);
437
+ return apiResponse;
438
+ } catch (error) {
439
+ console.error('Error creating deal:', error.message);
440
+ }
441
+ }
442
+ ```
443
+
444
+ ### Get a Deal
445
+
446
+ ```javascript
447
+ async function getDeal(dealId) {
448
+ const properties = ['dealname', 'dealstage', 'amount', 'closedate'];
449
+
450
+ try {
451
+ const apiResponse = await hubspotClient.crm.deals.basicApi.getById(
452
+ dealId,
453
+ properties
454
+ );
455
+ console.log('Deal:', apiResponse.properties);
456
+ return apiResponse;
457
+ } catch (error) {
458
+ console.error('Error fetching deal:', error.message);
459
+ }
460
+ }
461
+ ```
462
+
463
+ ### Update a Deal
464
+
465
+ ```javascript
466
+ async function updateDeal(dealId) {
467
+ const properties = {
468
+ dealstage: 'closedwon',
469
+ amount: '15000',
470
+ closedate: '2025-11-30'
471
+ };
472
+
473
+ try {
474
+ const apiResponse = await hubspotClient.crm.deals.basicApi.update(
475
+ dealId,
476
+ { properties }
477
+ );
478
+ console.log('Deal updated:', apiResponse.id);
479
+ return apiResponse;
480
+ } catch (error) {
481
+ console.error('Error updating deal:', error.message);
482
+ }
483
+ }
484
+ ```
485
+
486
+ ### List Deals
487
+
488
+ ```javascript
489
+ async function listDeals() {
490
+ const limit = 10;
491
+ const properties = ['dealname', 'dealstage', 'amount'];
492
+
493
+ try {
494
+ const apiResponse = await hubspotClient.crm.deals.basicApi.getPage(
495
+ limit,
496
+ undefined,
497
+ properties
498
+ );
499
+
500
+ console.log(`Found ${apiResponse.results.length} deals`);
501
+ return apiResponse;
502
+ } catch (error) {
503
+ console.error('Error listing deals:', error.message);
504
+ }
505
+ }
506
+ ```
507
+
508
+ ## CRM API - Tickets
509
+
510
+ ### Create a Ticket
511
+
512
+ ```javascript
513
+ async function createTicket() {
514
+ const ticketObj = {
515
+ properties: {
516
+ subject: 'Customer Support Request',
517
+ content: 'Customer needs help with product setup',
518
+ hs_pipeline: '0',
519
+ hs_pipeline_stage: '1',
520
+ hs_ticket_priority: 'HIGH',
521
+ hubspot_owner_id: '12345'
522
+ }
523
+ };
524
+
525
+ try {
526
+ const apiResponse = await hubspotClient.crm.tickets.basicApi.create(ticketObj);
527
+ console.log('Ticket created:', apiResponse.id);
528
+ return apiResponse;
529
+ } catch (error) {
530
+ console.error('Error creating ticket:', error.message);
531
+ }
532
+ }
533
+ ```
534
+
535
+ ### Get a Ticket
536
+
537
+ ```javascript
538
+ async function getTicket(ticketId) {
539
+ const properties = ['subject', 'content', 'hs_pipeline_stage', 'hs_ticket_priority'];
540
+
541
+ try {
542
+ const apiResponse = await hubspotClient.crm.tickets.basicApi.getById(
543
+ ticketId,
544
+ properties
545
+ );
546
+ console.log('Ticket:', apiResponse.properties);
547
+ return apiResponse;
548
+ } catch (error) {
549
+ console.error('Error fetching ticket:', error.message);
550
+ }
551
+ }
552
+ ```
553
+
554
+ ### Update a Ticket
555
+
556
+ ```javascript
557
+ async function updateTicket(ticketId) {
558
+ const properties = {
559
+ hs_pipeline_stage: '4', // Closed
560
+ hs_ticket_priority: 'LOW'
561
+ };
562
+
563
+ try {
564
+ const apiResponse = await hubspotClient.crm.tickets.basicApi.update(
565
+ ticketId,
566
+ { properties }
567
+ );
568
+ console.log('Ticket updated:', apiResponse.id);
569
+ return apiResponse;
570
+ } catch (error) {
571
+ console.error('Error updating ticket:', error.message);
572
+ }
573
+ }
574
+ ```
575
+
576
+ ## CRM API - Associations
577
+
578
+ Associations link objects together (e.g., contacts to companies, deals to contacts).
579
+
580
+ ### Create Association
581
+
582
+ **Associate Contact with Company:**
583
+
584
+ ```javascript
585
+ async function associateContactWithCompany(contactId, companyId) {
586
+ try {
587
+ const apiResponse = await hubspotClient.crm.contacts.associationsApi.create(
588
+ contactId,
589
+ 'companies',
590
+ companyId,
591
+ 'contact_to_company'
592
+ );
593
+ console.log('Association created');
594
+ return apiResponse;
595
+ } catch (error) {
596
+ console.error('Error creating association:', error.message);
597
+ }
598
+ }
599
+ ```
600
+
601
+ **Associate Deal with Contact:**
602
+
603
+ ```javascript
604
+ async function associateDealWithContact(dealId, contactId) {
605
+ try {
606
+ const apiResponse = await hubspotClient.crm.deals.associationsApi.create(
607
+ dealId,
608
+ 'contacts',
609
+ contactId,
610
+ 'deal_to_contact'
611
+ );
612
+ console.log('Association created');
613
+ return apiResponse;
614
+ } catch (error) {
615
+ console.error('Error creating association:', error.message);
616
+ }
617
+ }
618
+ ```
619
+
620
+ ### Get Associations
621
+
622
+ ```javascript
623
+ async function getContactAssociations(contactId) {
624
+ try {
625
+ const companies = await hubspotClient.crm.contacts.associationsApi.getAll(
626
+ contactId,
627
+ 'companies'
628
+ );
629
+
630
+ const deals = await hubspotClient.crm.contacts.associationsApi.getAll(
631
+ contactId,
632
+ 'deals'
633
+ );
634
+
635
+ console.log('Associated companies:', companies.results);
636
+ console.log('Associated deals:', deals.results);
637
+
638
+ return { companies, deals };
639
+ } catch (error) {
640
+ console.error('Error fetching associations:', error.message);
641
+ }
642
+ }
643
+ ```
644
+
645
+ ### Remove Association
646
+
647
+ ```javascript
648
+ async function removeAssociation(contactId, companyId) {
649
+ try {
650
+ await hubspotClient.crm.contacts.associationsApi.archive(
651
+ contactId,
652
+ 'companies',
653
+ companyId,
654
+ 'contact_to_company'
655
+ );
656
+ console.log('Association removed');
657
+ } catch (error) {
658
+ console.error('Error removing association:', error.message);
659
+ }
660
+ }
661
+ ```
662
+
663
+ ## CRM API - Batch Operations
664
+
665
+ Batch operations allow you to create, update, or read up to 100 records in a single API call.
666
+
667
+ ### Batch Create Contacts
668
+
669
+ ```javascript
670
+ async function batchCreateContacts() {
671
+ const batchInputs = {
672
+ inputs: [
673
+ {
674
+ properties: {
675
+ email: 'contact1@example.com',
676
+ firstname: 'Contact',
677
+ lastname: 'One'
678
+ }
679
+ },
680
+ {
681
+ properties: {
682
+ email: 'contact2@example.com',
683
+ firstname: 'Contact',
684
+ lastname: 'Two'
685
+ }
686
+ },
687
+ {
688
+ properties: {
689
+ email: 'contact3@example.com',
690
+ firstname: 'Contact',
691
+ lastname: 'Three'
692
+ }
693
+ }
694
+ ]
695
+ };
696
+
697
+ try {
698
+ const apiResponse = await hubspotClient.crm.contacts.batchApi.create(batchInputs);
699
+ console.log(`Created ${apiResponse.results.length} contacts`);
700
+ return apiResponse;
701
+ } catch (error) {
702
+ console.error('Error batch creating contacts:', error.message);
703
+ }
704
+ }
705
+ ```
706
+
707
+ ### Batch Update Contacts
708
+
709
+ ```javascript
710
+ async function batchUpdateContacts(contactIds) {
711
+ const batchInputs = {
712
+ inputs: contactIds.map(id => ({
713
+ id: id,
714
+ properties: {
715
+ lifecyclestage: 'customer',
716
+ hs_lead_status: 'CONNECTED'
717
+ }
718
+ }))
719
+ };
720
+
721
+ try {
722
+ const apiResponse = await hubspotClient.crm.contacts.batchApi.update(batchInputs);
723
+ console.log(`Updated ${apiResponse.results.length} contacts`);
724
+ return apiResponse;
725
+ } catch (error) {
726
+ console.error('Error batch updating contacts:', error.message);
727
+ }
728
+ }
729
+ ```
730
+
731
+ ### Batch Read Contacts
732
+
733
+ ```javascript
734
+ async function batchReadContacts(contactIds) {
735
+ const batchInputs = {
736
+ properties: ['email', 'firstname', 'lastname', 'phone'],
737
+ inputs: contactIds.map(id => ({ id }))
738
+ };
739
+
740
+ try {
741
+ const apiResponse = await hubspotClient.crm.contacts.batchApi.read(batchInputs);
742
+ console.log(`Retrieved ${apiResponse.results.length} contacts`);
743
+ return apiResponse;
744
+ } catch (error) {
745
+ console.error('Error batch reading contacts:', error.message);
746
+ }
747
+ }
748
+ ```
749
+
750
+ ### Batch Upsert Contacts
751
+
752
+ ```javascript
753
+ async function batchUpsertContacts() {
754
+ const batchInputs = {
755
+ inputs: [
756
+ {
757
+ properties: {
758
+ email: 'existing@example.com',
759
+ firstname: 'Updated',
760
+ lastname: 'Name'
761
+ },
762
+ idProperty: 'email'
763
+ },
764
+ {
765
+ properties: {
766
+ email: 'new@example.com',
767
+ firstname: 'New',
768
+ lastname: 'Contact'
769
+ },
770
+ idProperty: 'email'
771
+ }
772
+ ]
773
+ };
774
+
775
+ try {
776
+ const apiResponse = await hubspotClient.crm.contacts.batchApi.upsert(batchInputs);
777
+ console.log(`Upserted ${apiResponse.results.length} contacts`);
778
+ return apiResponse;
779
+ } catch (error) {
780
+ console.error('Error batch upserting contacts:', error.message);
781
+ }
782
+ }
783
+ ```
784
+
785
+ ## CRM API - Search
786
+
787
+ The Search API allows you to filter, sort, and search across CRM objects.
788
+
789
+ ### Basic Search
790
+
791
+ ```javascript
792
+ async function searchContacts() {
793
+ const filter = {
794
+ propertyName: 'lifecyclestage',
795
+ operator: 'EQ',
796
+ value: 'lead'
797
+ };
798
+
799
+ const filterGroup = {
800
+ filters: [filter]
801
+ };
802
+
803
+ const searchRequest = {
804
+ filterGroups: [filterGroup],
805
+ properties: ['email', 'firstname', 'lastname', 'lifecyclestage'],
806
+ limit: 10
807
+ };
808
+
809
+ try {
810
+ const apiResponse = await hubspotClient.crm.contacts.searchApi.doSearch(searchRequest);
811
+ console.log(`Found ${apiResponse.total} contacts`);
812
+ console.log(`Returned ${apiResponse.results.length} results`);
813
+ return apiResponse;
814
+ } catch (error) {
815
+ console.error('Error searching contacts:', error.message);
816
+ }
817
+ }
818
+ ```
819
+
820
+ ### Advanced Search with Multiple Filters
821
+
822
+ ```javascript
823
+ async function advancedSearchContacts() {
824
+ const searchRequest = {
825
+ filterGroups: [
826
+ {
827
+ filters: [
828
+ {
829
+ propertyName: 'lifecyclestage',
830
+ operator: 'EQ',
831
+ value: 'lead'
832
+ },
833
+ {
834
+ propertyName: 'createdate',
835
+ operator: 'GTE',
836
+ value: '2025-01-01'
837
+ }
838
+ ]
839
+ }
840
+ ],
841
+ sorts: [
842
+ {
843
+ propertyName: 'createdate',
844
+ direction: 'DESCENDING'
845
+ }
846
+ ],
847
+ properties: ['email', 'firstname', 'lastname', 'createdate', 'lifecyclestage'],
848
+ limit: 100,
849
+ after: 0
850
+ };
851
+
852
+ try {
853
+ const apiResponse = await hubspotClient.crm.contacts.searchApi.doSearch(searchRequest);
854
+ console.log(`Found ${apiResponse.total} matching contacts`);
855
+ return apiResponse;
856
+ } catch (error) {
857
+ console.error('Error searching contacts:', error.message);
858
+ }
859
+ }
860
+ ```
861
+
862
+ ### Search with Association Filters
863
+
864
+ ```javascript
865
+ async function searchContactsByCompany(companyId) {
866
+ const searchRequest = {
867
+ filterGroups: [
868
+ {
869
+ filters: [
870
+ {
871
+ propertyName: 'associations.company',
872
+ operator: 'EQ',
873
+ value: companyId
874
+ }
875
+ ]
876
+ }
877
+ ],
878
+ properties: ['email', 'firstname', 'lastname'],
879
+ limit: 100
880
+ };
881
+
882
+ try {
883
+ const apiResponse = await hubspotClient.crm.contacts.searchApi.doSearch(searchRequest);
884
+ console.log(`Found ${apiResponse.results.length} contacts for company`);
885
+ return apiResponse;
886
+ } catch (error) {
887
+ console.error('Error searching contacts by company:', error.message);
888
+ }
889
+ }
890
+ ```
891
+
892
+ ### Search Operators
893
+
894
+ Available operators for search filters:
895
+
896
+ - `EQ` - Equal to
897
+ - `NEQ` - Not equal to
898
+ - `LT` - Less than
899
+ - `LTE` - Less than or equal to
900
+ - `GT` - Greater than
901
+ - `GTE` - Greater than or equal to
902
+ - `IN` - In list of values
903
+ - `NOT_IN` - Not in list of values
904
+ - `HAS_PROPERTY` - Has property value set
905
+ - `NOT_HAS_PROPERTY` - Does not have property value set
906
+ - `CONTAINS_TOKEN` - Contains token (for text)
907
+ - `NOT_CONTAINS_TOKEN` - Does not contain token
908
+
909
+ ## CRM API - Properties
910
+
911
+ ### Get All Contact Properties
912
+
913
+ ```javascript
914
+ async function getAllContactProperties() {
915
+ try {
916
+ const apiResponse = await hubspotClient.crm.properties.coreApi.getAll('contacts');
917
+ console.log(`Found ${apiResponse.results.length} contact properties`);
918
+ return apiResponse;
919
+ } catch (error) {
920
+ console.error('Error fetching contact properties:', error.message);
921
+ }
922
+ }
923
+ ```
924
+
925
+ ### Create Custom Property
926
+
927
+ ```javascript
928
+ async function createCustomProperty() {
929
+ const propertyObj = {
930
+ name: 'favorite_color',
931
+ label: 'Favorite Color',
932
+ type: 'string',
933
+ fieldType: 'text',
934
+ groupName: 'contactinformation',
935
+ description: 'The contact\'s favorite color',
936
+ options: []
937
+ };
938
+
939
+ try {
940
+ const apiResponse = await hubspotClient.crm.properties.coreApi.create(
941
+ 'contacts',
942
+ propertyObj
943
+ );
944
+ console.log('Custom property created:', apiResponse.name);
945
+ return apiResponse;
946
+ } catch (error) {
947
+ console.error('Error creating custom property:', error.message);
948
+ }
949
+ }
950
+ ```
951
+
952
+ ### Create Dropdown Property
953
+
954
+ ```javascript
955
+ async function createDropdownProperty() {
956
+ const propertyObj = {
957
+ name: 'customer_tier',
958
+ label: 'Customer Tier',
959
+ type: 'enumeration',
960
+ fieldType: 'select',
961
+ groupName: 'contactinformation',
962
+ options: [
963
+ { label: 'Bronze', value: 'bronze', displayOrder: 0 },
964
+ { label: 'Silver', value: 'silver', displayOrder: 1 },
965
+ { label: 'Gold', value: 'gold', displayOrder: 2 },
966
+ { label: 'Platinum', value: 'platinum', displayOrder: 3 }
967
+ ]
968
+ };
969
+
970
+ try {
971
+ const apiResponse = await hubspotClient.crm.properties.coreApi.create(
972
+ 'contacts',
973
+ propertyObj
974
+ );
975
+ console.log('Dropdown property created:', apiResponse.name);
976
+ return apiResponse;
977
+ } catch (error) {
978
+ console.error('Error creating dropdown property:', error.message);
979
+ }
980
+ }
981
+ ```
982
+
983
+ ### Update Property
984
+
985
+ ```javascript
986
+ async function updateProperty(propertyName) {
987
+ const propertyUpdate = {
988
+ label: 'Updated Label',
989
+ description: 'Updated description'
990
+ };
991
+
992
+ try {
993
+ const apiResponse = await hubspotClient.crm.properties.coreApi.update(
994
+ 'contacts',
995
+ propertyName,
996
+ propertyUpdate
997
+ );
998
+ console.log('Property updated:', apiResponse.name);
999
+ return apiResponse;
1000
+ } catch (error) {
1001
+ console.error('Error updating property:', error.message);
1002
+ }
1003
+ }
1004
+ ```
1005
+
1006
+ ## Marketing API - Emails
1007
+
1008
+ ### Get All Marketing Emails
1009
+
1010
+ ```javascript
1011
+ async function getMarketingEmails() {
1012
+ try {
1013
+ const apiResponse = await hubspotClient.marketing.emails.emailsApi.getPage();
1014
+ console.log(`Found ${apiResponse.results.length} marketing emails`);
1015
+ return apiResponse;
1016
+ } catch (error) {
1017
+ console.error('Error fetching marketing emails:', error.message);
1018
+ }
1019
+ }
1020
+ ```
1021
+
1022
+ ### Get Email by ID
1023
+
1024
+ ```javascript
1025
+ async function getMarketingEmail(emailId) {
1026
+ try {
1027
+ const apiResponse = await hubspotClient.marketing.emails.emailsApi.getById(emailId);
1028
+ console.log('Email:', apiResponse.name);
1029
+ return apiResponse;
1030
+ } catch (error) {
1031
+ console.error('Error fetching marketing email:', error.message);
1032
+ }
1033
+ }
1034
+ ```
1035
+
1036
+ ## Marketing API - Forms
1037
+
1038
+ ### Get All Forms
1039
+
1040
+ ```javascript
1041
+ async function getAllForms() {
1042
+ try {
1043
+ const apiResponse = await hubspotClient.marketing.forms.formsApi.getPage();
1044
+ console.log(`Found ${apiResponse.results.length} forms`);
1045
+ return apiResponse;
1046
+ } catch (error) {
1047
+ console.error('Error fetching forms:', error.message);
1048
+ }
1049
+ }
1050
+ ```
1051
+
1052
+ ### Get Form by ID
1053
+
1054
+ ```javascript
1055
+ async function getForm(formId) {
1056
+ try {
1057
+ const apiResponse = await hubspotClient.marketing.forms.formsApi.getById(formId);
1058
+ console.log('Form:', apiResponse.name);
1059
+ return apiResponse;
1060
+ } catch (error) {
1061
+ console.error('Error fetching form:', error.message);
1062
+ }
1063
+ }
1064
+ ```
1065
+
1066
+ ### Submit Form Data
1067
+
1068
+ ```javascript
1069
+ async function submitFormData(formGuid, portalId) {
1070
+ const formData = {
1071
+ fields: [
1072
+ {
1073
+ name: 'email',
1074
+ value: 'test@example.com'
1075
+ },
1076
+ {
1077
+ name: 'firstname',
1078
+ value: 'John'
1079
+ },
1080
+ {
1081
+ name: 'lastname',
1082
+ value: 'Doe'
1083
+ }
1084
+ ],
1085
+ context: {
1086
+ pageUri: 'https://example.com/contact',
1087
+ pageName: 'Contact Us'
1088
+ }
1089
+ };
1090
+
1091
+ try {
1092
+ const axios = require('axios');
1093
+ const response = await axios.post(
1094
+ `https://api.hsforms.com/submissions/v3/integration/submit/${portalId}/${formGuid}`,
1095
+ formData
1096
+ );
1097
+ console.log('Form submitted successfully');
1098
+ return response.data;
1099
+ } catch (error) {
1100
+ console.error('Error submitting form:', error.message);
1101
+ }
1102
+ }
1103
+ ```
1104
+
1105
+ ## Events API - Timeline Events
1106
+
1107
+ ### Create Timeline Event Type
1108
+
1109
+ ```javascript
1110
+ async function createTimelineEventType() {
1111
+ const eventTypeObj = {
1112
+ name: 'Custom Event',
1113
+ applicationId: 12345, // Your app ID
1114
+ objectType: 'CONTACT',
1115
+ headerTemplate: '{{eventTitle}}',
1116
+ detailTemplate: '{{eventDescription}}'
1117
+ };
1118
+
1119
+ try {
1120
+ const apiResponse = await hubspotClient.crm.timeline.eventsApi.createEventType(
1121
+ eventTypeObj
1122
+ );
1123
+ console.log('Timeline event type created:', apiResponse.id);
1124
+ return apiResponse;
1125
+ } catch (error) {
1126
+ console.error('Error creating timeline event type:', error.message);
1127
+ }
1128
+ }
1129
+ ```
1130
+
1131
+ ### Create Timeline Event
1132
+
1133
+ ```javascript
1134
+ async function createTimelineEvent(eventTypeId, objectId) {
1135
+ const eventData = {
1136
+ eventTypeId: eventTypeId,
1137
+ objectId: objectId,
1138
+ extraData: {
1139
+ eventTitle: 'Purchase Completed',
1140
+ eventDescription: 'Customer completed a purchase of $99.99'
1141
+ },
1142
+ timestamp: new Date().toISOString()
1143
+ };
1144
+
1145
+ try {
1146
+ const apiResponse = await hubspotClient.crm.timeline.eventsApi.create(eventData);
1147
+ console.log('Timeline event created:', apiResponse.id);
1148
+ return apiResponse;
1149
+ } catch (error) {
1150
+ console.error('Error creating timeline event:', error.message);
1151
+ }
1152
+ }
1153
+ ```
1154
+
1155
+ ## Automation API - Workflows
1156
+
1157
+ ### Get All Workflows
1158
+
1159
+ ```javascript
1160
+ async function getAllWorkflows() {
1161
+ try {
1162
+ const axios = require('axios');
1163
+ const response = await axios.get(
1164
+ 'https://api.hubapi.com/automation/v3/workflows',
1165
+ {
1166
+ headers: {
1167
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`
1168
+ }
1169
+ }
1170
+ );
1171
+ console.log(`Found ${response.data.workflows.length} workflows`);
1172
+ return response.data;
1173
+ } catch (error) {
1174
+ console.error('Error fetching workflows:', error.message);
1175
+ }
1176
+ }
1177
+ ```
1178
+
1179
+ ### Get Workflow by ID
1180
+
1181
+ ```javascript
1182
+ async function getWorkflow(workflowId) {
1183
+ try {
1184
+ const axios = require('axios');
1185
+ const response = await axios.get(
1186
+ `https://api.hubapi.com/automation/v3/workflows/${workflowId}`,
1187
+ {
1188
+ headers: {
1189
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`
1190
+ }
1191
+ }
1192
+ );
1193
+ console.log('Workflow:', response.data.name);
1194
+ return response.data;
1195
+ } catch (error) {
1196
+ console.error('Error fetching workflow:', error.message);
1197
+ }
1198
+ }
1199
+ ```
1200
+
1201
+ ### Enroll Contact in Workflow
1202
+
1203
+ ```javascript
1204
+ async function enrollContactInWorkflow(workflowId, contactEmail) {
1205
+ try {
1206
+ const axios = require('axios');
1207
+ const response = await axios.post(
1208
+ `https://api.hubapi.com/automation/v2/workflows/${workflowId}/enrollments/contacts/${contactEmail}`,
1209
+ {},
1210
+ {
1211
+ headers: {
1212
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`,
1213
+ 'Content-Type': 'application/json'
1214
+ }
1215
+ }
1216
+ );
1217
+ console.log('Contact enrolled in workflow');
1218
+ return response.data;
1219
+ } catch (error) {
1220
+ console.error('Error enrolling contact in workflow:', error.message);
1221
+ }
1222
+ }
1223
+ ```
1224
+
1225
+ ## Webhooks API
1226
+
1227
+ ### Create Webhook Subscription
1228
+
1229
+ ```javascript
1230
+ async function createWebhookSubscription() {
1231
+ const subscriptionObj = {
1232
+ eventType: 'contact.creation',
1233
+ propertyName: undefined,
1234
+ active: true
1235
+ };
1236
+
1237
+ try {
1238
+ const apiResponse = await hubspotClient.webhooks.subscriptionsApi.create(
1239
+ 12345, // Your app ID
1240
+ subscriptionObj
1241
+ );
1242
+ console.log('Webhook subscription created:', apiResponse.id);
1243
+ return apiResponse;
1244
+ } catch (error) {
1245
+ console.error('Error creating webhook subscription:', error.message);
1246
+ }
1247
+ }
1248
+ ```
1249
+
1250
+ ### Get All Webhook Subscriptions
1251
+
1252
+ ```javascript
1253
+ async function getWebhookSubscriptions(appId) {
1254
+ try {
1255
+ const apiResponse = await hubspotClient.webhooks.subscriptionsApi.getAll(appId);
1256
+ console.log(`Found ${apiResponse.results.length} webhook subscriptions`);
1257
+ return apiResponse;
1258
+ } catch (error) {
1259
+ console.error('Error fetching webhook subscriptions:', error.message);
1260
+ }
1261
+ }
1262
+ ```
1263
+
1264
+ ### Delete Webhook Subscription
1265
+
1266
+ ```javascript
1267
+ async function deleteWebhookSubscription(appId, subscriptionId) {
1268
+ try {
1269
+ await hubspotClient.webhooks.subscriptionsApi.archive(appId, subscriptionId);
1270
+ console.log('Webhook subscription deleted');
1271
+ } catch (error) {
1272
+ console.error('Error deleting webhook subscription:', error.message);
1273
+ }
1274
+ }
1275
+ ```
1276
+
1277
+ ## Lists API
1278
+
1279
+ ### Get All Lists
1280
+
1281
+ ```javascript
1282
+ async function getAllLists() {
1283
+ try {
1284
+ const axios = require('axios');
1285
+ const response = await axios.get(
1286
+ 'https://api.hubapi.com/contacts/v1/lists',
1287
+ {
1288
+ headers: {
1289
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`
1290
+ },
1291
+ params: {
1292
+ count: 100,
1293
+ offset: 0
1294
+ }
1295
+ }
1296
+ );
1297
+ console.log(`Found ${response.data.lists.length} lists`);
1298
+ return response.data;
1299
+ } catch (error) {
1300
+ console.error('Error fetching lists:', error.message);
1301
+ }
1302
+ }
1303
+ ```
1304
+
1305
+ ### Add Contact to List
1306
+
1307
+ ```javascript
1308
+ async function addContactToList(listId, contactId) {
1309
+ try {
1310
+ const axios = require('axios');
1311
+ const response = await axios.post(
1312
+ `https://api.hubapi.com/contacts/v1/lists/${listId}/add`,
1313
+ {
1314
+ vids: [contactId]
1315
+ },
1316
+ {
1317
+ headers: {
1318
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`,
1319
+ 'Content-Type': 'application/json'
1320
+ }
1321
+ }
1322
+ );
1323
+ console.log('Contact added to list');
1324
+ return response.data;
1325
+ } catch (error) {
1326
+ console.error('Error adding contact to list:', error.message);
1327
+ }
1328
+ }
1329
+ ```
1330
+
1331
+ ### Remove Contact from List
1332
+
1333
+ ```javascript
1334
+ async function removeContactFromList(listId, contactId) {
1335
+ try {
1336
+ const axios = require('axios');
1337
+ const response = await axios.post(
1338
+ `https://api.hubapi.com/contacts/v1/lists/${listId}/remove`,
1339
+ {
1340
+ vids: [contactId]
1341
+ },
1342
+ {
1343
+ headers: {
1344
+ Authorization: `Bearer ${process.env.HUBSPOT_ACCESS_TOKEN}`,
1345
+ 'Content-Type': 'application/json'
1346
+ }
1347
+ }
1348
+ );
1349
+ console.log('Contact removed from list');
1350
+ return response.data;
1351
+ } catch (error) {
1352
+ console.error('Error removing contact from list:', error.message);
1353
+ }
1354
+ }
1355
+ ```
1356
+
1357
+ ## Owners API
1358
+
1359
+ ### Get All Owners
1360
+
1361
+ ```javascript
1362
+ async function getAllOwners() {
1363
+ try {
1364
+ const apiResponse = await hubspotClient.crm.owners.ownersApi.getPage();
1365
+ console.log(`Found ${apiResponse.results.length} owners`);
1366
+ return apiResponse;
1367
+ } catch (error) {
1368
+ console.error('Error fetching owners:', error.message);
1369
+ }
1370
+ }
1371
+ ```
1372
+
1373
+ ### Get Owner by ID
1374
+
1375
+ ```javascript
1376
+ async function getOwner(ownerId) {
1377
+ try {
1378
+ const apiResponse = await hubspotClient.crm.owners.ownersApi.getById(ownerId);
1379
+ console.log('Owner:', apiResponse.email);
1380
+ return apiResponse;
1381
+ } catch (error) {
1382
+ console.error('Error fetching owner:', error.message);
1383
+ }
1384
+ }
1385
+ ```
1386
+
1387
+ ## Error Handling
1388
+
1389
+ ### Comprehensive Error Handling
1390
+
1391
+ ```javascript
1392
+ async function handleApiCall() {
1393
+ try {
1394
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.getById('12345');
1395
+ return apiResponse;
1396
+ } catch (error) {
1397
+ if (error.statusCode === 401) {
1398
+ console.error('Authentication failed - check your access token');
1399
+ } else if (error.statusCode === 404) {
1400
+ console.error('Resource not found');
1401
+ } else if (error.statusCode === 409) {
1402
+ console.error('Conflict - resource already exists');
1403
+ } else if (error.statusCode === 429) {
1404
+ console.error('Rate limit exceeded - wait before retrying');
1405
+ } else if (error.statusCode >= 500) {
1406
+ console.error('HubSpot server error - try again later');
1407
+ } else {
1408
+ console.error('API error:', error.message);
1409
+ }
1410
+ throw error;
1411
+ }
1412
+ }
1413
+ ```
1414
+
1415
+ ### Retry Logic
1416
+
1417
+ ```javascript
1418
+ async function apiCallWithRetry(apiCall, maxRetries = 3) {
1419
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1420
+ try {
1421
+ return await apiCall();
1422
+ } catch (error) {
1423
+ if (error.statusCode === 429 && attempt < maxRetries) {
1424
+ const retryAfter = error.response?.headers['retry-after'] || 1;
1425
+ console.log(`Rate limited. Retrying after ${retryAfter} seconds...`);
1426
+ await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
1427
+ } else {
1428
+ throw error;
1429
+ }
1430
+ }
1431
+ }
1432
+ }
1433
+
1434
+ // Usage
1435
+ await apiCallWithRetry(() =>
1436
+ hubspotClient.crm.contacts.basicApi.getById('12345')
1437
+ );
1438
+ ```
1439
+
1440
+ ## Rate Limits
1441
+
1442
+ HubSpot API has the following rate limits:
1443
+
1444
+ - **Private Apps:** 100 requests per 10 seconds per account
1445
+ - **OAuth Apps:** 100 requests per 10 seconds per app per account
1446
+ - **Search API:** 5 requests per second, 1000 requests per day (per account)
1447
+ - **Batch API:** 100 objects per request, same rate limits as standard endpoints
1448
+
1449
+ The SDK automatically handles rate limiting with the `limiterOptions` configuration.
1450
+
1451
+ ## Pagination
1452
+
1453
+ Most list endpoints return paginated results. Use the `after` parameter for pagination:
1454
+
1455
+ ```javascript
1456
+ async function paginateThroughContacts() {
1457
+ let after = undefined;
1458
+ let allContacts = [];
1459
+
1460
+ do {
1461
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.getPage(
1462
+ 100,
1463
+ after,
1464
+ ['email', 'firstname', 'lastname']
1465
+ );
1466
+
1467
+ allContacts.push(...apiResponse.results);
1468
+ after = apiResponse.paging?.next?.after;
1469
+
1470
+ } while (after);
1471
+
1472
+ return allContacts;
1473
+ }
1474
+ ```
1475
+
1476
+ ## OAuth Implementation
1477
+
1478
+ ### Initialize OAuth Provider
1479
+
1480
+ ```javascript
1481
+ const hubspot = require('@hubspot/api-client');
1482
+
1483
+ const hubspotClient = new hubspot.Client({
1484
+ clientId: process.env.HUBSPOT_CLIENT_ID,
1485
+ clientSecret: process.env.HUBSPOT_CLIENT_SECRET,
1486
+ redirectUri: 'https://yourapp.com/oauth-callback'
1487
+ });
1488
+ ```
1489
+
1490
+ ### Get Authorization URL
1491
+
1492
+ ```javascript
1493
+ function getAuthorizationUrl() {
1494
+ const authUrl = hubspotClient.oauth.getAuthorizationUrl(
1495
+ process.env.HUBSPOT_CLIENT_ID,
1496
+ process.env.REDIRECT_URI,
1497
+ 'contacts crm.objects.contacts.read'
1498
+ );
1499
+ return authUrl;
1500
+ }
1501
+ ```
1502
+
1503
+ ### Exchange Authorization Code for Tokens
1504
+
1505
+ ```javascript
1506
+ async function getTokens(authorizationCode) {
1507
+ try {
1508
+ const tokenResponse = await hubspotClient.oauth.tokensApi.create(
1509
+ 'authorization_code',
1510
+ authorizationCode,
1511
+ process.env.REDIRECT_URI,
1512
+ process.env.HUBSPOT_CLIENT_ID,
1513
+ process.env.HUBSPOT_CLIENT_SECRET
1514
+ );
1515
+
1516
+ return {
1517
+ accessToken: tokenResponse.accessToken,
1518
+ refreshToken: tokenResponse.refreshToken,
1519
+ expiresIn: tokenResponse.expiresIn
1520
+ };
1521
+ } catch (error) {
1522
+ console.error('Error exchanging code for tokens:', error.message);
1523
+ }
1524
+ }
1525
+ ```
1526
+
1527
+ ### Refresh Access Token
1528
+
1529
+ ```javascript
1530
+ async function refreshAccessToken(refreshToken) {
1531
+ try {
1532
+ const tokenResponse = await hubspotClient.oauth.tokensApi.create(
1533
+ 'refresh_token',
1534
+ undefined,
1535
+ undefined,
1536
+ process.env.HUBSPOT_CLIENT_ID,
1537
+ process.env.HUBSPOT_CLIENT_SECRET,
1538
+ refreshToken
1539
+ );
1540
+
1541
+ return {
1542
+ accessToken: tokenResponse.accessToken,
1543
+ refreshToken: tokenResponse.refreshToken,
1544
+ expiresIn: tokenResponse.expiresIn
1545
+ };
1546
+ } catch (error) {
1547
+ console.error('Error refreshing token:', error.message);
1548
+ }
1549
+ }
1550
+ ```
1551
+
1552
+ ## Custom Objects
1553
+
1554
+ ### Create Custom Object Schema
1555
+
1556
+ ```javascript
1557
+ async function createCustomObjectSchema() {
1558
+ const schemaObj = {
1559
+ name: 'cars',
1560
+ labels: {
1561
+ singular: 'Car',
1562
+ plural: 'Cars'
1563
+ },
1564
+ primaryDisplayProperty: 'model',
1565
+ requiredProperties: ['model', 'make'],
1566
+ searchableProperties: ['model', 'make', 'year'],
1567
+ properties: [
1568
+ {
1569
+ name: 'model',
1570
+ label: 'Model',
1571
+ type: 'string',
1572
+ fieldType: 'text'
1573
+ },
1574
+ {
1575
+ name: 'make',
1576
+ label: 'Make',
1577
+ type: 'string',
1578
+ fieldType: 'text'
1579
+ },
1580
+ {
1581
+ name: 'year',
1582
+ label: 'Year',
1583
+ type: 'number',
1584
+ fieldType: 'number'
1585
+ }
1586
+ ]
1587
+ };
1588
+
1589
+ try {
1590
+ const apiResponse = await hubspotClient.crm.schemas.coreApi.create(schemaObj);
1591
+ console.log('Custom object schema created:', apiResponse.name);
1592
+ return apiResponse;
1593
+ } catch (error) {
1594
+ console.error('Error creating custom object schema:', error.message);
1595
+ }
1596
+ }
1597
+ ```
1598
+
1599
+ ### Create Custom Object Instance
1600
+
1601
+ ```javascript
1602
+ async function createCustomObject(objectType) {
1603
+ const objectData = {
1604
+ properties: {
1605
+ model: 'Model 3',
1606
+ make: 'Tesla',
1607
+ year: '2024'
1608
+ }
1609
+ };
1610
+
1611
+ try {
1612
+ const apiResponse = await hubspotClient.crm.objects.basicApi.create(
1613
+ objectType,
1614
+ objectData
1615
+ );
1616
+ console.log('Custom object created:', apiResponse.id);
1617
+ return apiResponse;
1618
+ } catch (error) {
1619
+ console.error('Error creating custom object:', error.message);
1620
+ }
1621
+ }
1622
+ ```
1623
+
1624
+ ## Complete Example Application
1625
+
1626
+ Here's a complete example that demonstrates multiple API operations:
1627
+
1628
+ ```javascript
1629
+ const hubspot = require('@hubspot/api-client');
1630
+ require('dotenv').config();
1631
+
1632
+ const hubspotClient = new hubspot.Client({
1633
+ accessToken: process.env.HUBSPOT_ACCESS_TOKEN
1634
+ });
1635
+
1636
+ async function main() {
1637
+ try {
1638
+ // Create a contact
1639
+ console.log('Creating contact...');
1640
+ const newContact = await hubspotClient.crm.contacts.basicApi.create({
1641
+ properties: {
1642
+ email: 'john.doe@example.com',
1643
+ firstname: 'John',
1644
+ lastname: 'Doe',
1645
+ phone: '555-0100',
1646
+ company: 'Example Corp'
1647
+ }
1648
+ });
1649
+ console.log(`Contact created with ID: ${newContact.id}`);
1650
+
1651
+ // Create a company
1652
+ console.log('\nCreating company...');
1653
+ const newCompany = await hubspotClient.crm.companies.basicApi.create({
1654
+ properties: {
1655
+ name: 'Example Corp',
1656
+ domain: 'example.com',
1657
+ city: 'San Francisco',
1658
+ industry: 'Technology'
1659
+ }
1660
+ });
1661
+ console.log(`Company created with ID: ${newCompany.id}`);
1662
+
1663
+ // Associate contact with company
1664
+ console.log('\nAssociating contact with company...');
1665
+ await hubspotClient.crm.contacts.associationsApi.create(
1666
+ newContact.id,
1667
+ 'companies',
1668
+ newCompany.id,
1669
+ 'contact_to_company'
1670
+ );
1671
+ console.log('Association created successfully');
1672
+
1673
+ // Create a deal
1674
+ console.log('\nCreating deal...');
1675
+ const newDeal = await hubspotClient.crm.deals.basicApi.create({
1676
+ properties: {
1677
+ dealname: 'Example Deal',
1678
+ dealstage: 'appointmentscheduled',
1679
+ amount: '10000',
1680
+ closedate: '2025-12-31'
1681
+ }
1682
+ });
1683
+ console.log(`Deal created with ID: ${newDeal.id}`);
1684
+
1685
+ // Associate deal with contact
1686
+ console.log('\nAssociating deal with contact...');
1687
+ await hubspotClient.crm.deals.associationsApi.create(
1688
+ newDeal.id,
1689
+ 'contacts',
1690
+ newContact.id,
1691
+ 'deal_to_contact'
1692
+ );
1693
+ console.log('Deal associated with contact');
1694
+
1695
+ // Search for contacts
1696
+ console.log('\nSearching for leads...');
1697
+ const searchResults = await hubspotClient.crm.contacts.searchApi.doSearch({
1698
+ filterGroups: [
1699
+ {
1700
+ filters: [
1701
+ {
1702
+ propertyName: 'email',
1703
+ operator: 'CONTAINS_TOKEN',
1704
+ value: 'example.com'
1705
+ }
1706
+ ]
1707
+ }
1708
+ ],
1709
+ properties: ['email', 'firstname', 'lastname', 'company'],
1710
+ limit: 10
1711
+ });
1712
+ console.log(`Found ${searchResults.total} contacts`);
1713
+
1714
+ // List all owners
1715
+ console.log('\nFetching owners...');
1716
+ const owners = await hubspotClient.crm.owners.ownersApi.getPage();
1717
+ console.log(`Found ${owners.results.length} owners`);
1718
+
1719
+ console.log('\nAll operations completed successfully!');
1720
+ } catch (error) {
1721
+ console.error('Error:', error.message);
1722
+ if (error.body) {
1723
+ console.error('Error details:', JSON.stringify(error.body, null, 2));
1724
+ }
1725
+ }
1726
+ }
1727
+
1728
+ main();
1729
+ ```
1730
+
1731
+ ## TypeScript Support
1732
+
1733
+ The SDK includes full TypeScript definitions:
1734
+
1735
+ ```typescript
1736
+ import { Client } from '@hubspot/api-client';
1737
+
1738
+ const hubspotClient = new Client({
1739
+ accessToken: process.env.HUBSPOT_ACCESS_TOKEN
1740
+ });
1741
+
1742
+ interface ContactProperties {
1743
+ email: string;
1744
+ firstname: string;
1745
+ lastname: string;
1746
+ phone?: string;
1747
+ }
1748
+
1749
+ async function createContact(props: ContactProperties) {
1750
+ const apiResponse = await hubspotClient.crm.contacts.basicApi.create({
1751
+ properties: props
1752
+ });
1753
+ return apiResponse;
1754
+ }
1755
+ ```
1756
+
1757
+ ## Environment Variables Template
1758
+
1759
+ ```bash
1760
+ # .env file
1761
+ HUBSPOT_ACCESS_TOKEN=your_private_app_access_token
1762
+ HUBSPOT_CLIENT_ID=your_client_id
1763
+ HUBSPOT_CLIENT_SECRET=your_client_secret
1764
+ REDIRECT_URI=https://yourapp.com/oauth-callback
1765
+ ```
1766
+
1767
+ ## API Scopes
1768
+
1769
+ When creating a private app or OAuth app, configure the following scopes based on your needs:
1770
+
1771
+ **CRM:**
1772
+ - `crm.objects.contacts.read` / `crm.objects.contacts.write`
1773
+ - `crm.objects.companies.read` / `crm.objects.companies.write`
1774
+ - `crm.objects.deals.read` / `crm.objects.deals.write`
1775
+ - `crm.objects.owners.read`
1776
+ - `crm.schemas.contacts.read` / `crm.schemas.contacts.write`
1777
+
1778
+ **Marketing:**
1779
+ - `forms` - Read and write forms
1780
+ - `content` - Read and write marketing emails
1781
+
1782
+ **Automation:**
1783
+ - `automation` - Access to workflows
1784
+
1785
+ **Timeline:**
1786
+ - `timeline` - Create timeline events
1787
+
1788
+ ## Migration from Legacy API Keys
1789
+
1790
+ If you're using legacy API keys (deprecated), migrate to private apps:
1791
+
1792
+ **Old (Deprecated):**
1793
+ ```javascript
1794
+ // DON'T USE THIS
1795
+ const hapikey = 'your-api-key';
1796
+ ```
1797
+
1798
+ **New (Correct):**
1799
+ ```javascript
1800
+ const hubspotClient = new hubspot.Client({
1801
+ accessToken: process.env.HUBSPOT_ACCESS_TOKEN
1802
+ });
1803
+ ```
1804
+
1805
+ Legacy API keys will be revoked on November 19, 2025.