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,1844 @@
1
+ ---
2
+ name: messaging
3
+ description: "Intercom JavaScript SDK for customer messaging and chat support"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "6.4.0"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "intercom,messaging,customer,chat,support"
10
+ ---
11
+
12
+ # Intercom JavaScript SDK (v6.4.0)
13
+
14
+ ## Golden Rule
15
+
16
+ **ALWAYS use `intercom-client` version 6.4.0 or later.**
17
+
18
+ ```bash
19
+ npm install intercom-client
20
+ ```
21
+
22
+ **DO NOT use these deprecated or unofficial packages:**
23
+ - `intercom.io` (deprecated)
24
+ - `@ludovicbret/intercom-client` (community fork)
25
+ - Any package not named exactly `intercom-client`
26
+
27
+ The official Intercom TypeScript/JavaScript SDK is `intercom-client`, maintained by Intercom at https://github.com/intercom/intercom-node
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ npm install intercom-client
33
+ ```
34
+
35
+ For TypeScript projects, types are included in the package.
36
+
37
+ **Environment Setup:**
38
+
39
+ ```bash
40
+ # .env file
41
+ INTERCOM_ACCESS_TOKEN=your_access_token_here
42
+ ```
43
+
44
+ **Loading environment variables:**
45
+
46
+ ```javascript
47
+ // Using dotenv
48
+ import 'dotenv/config';
49
+ // or
50
+ require('dotenv').config();
51
+ ```
52
+
53
+ ## Initialization
54
+
55
+ **Basic Client Setup:**
56
+
57
+ ```javascript
58
+ import { IntercomClient } from 'intercom-client';
59
+
60
+ const client = new IntercomClient({
61
+ token: process.env.INTERCOM_ACCESS_TOKEN
62
+ });
63
+ ```
64
+
65
+ **TypeScript with explicit typing:**
66
+
67
+ ```typescript
68
+ import { IntercomClient, Intercom } from 'intercom-client';
69
+
70
+ const client: IntercomClient = new IntercomClient({
71
+ token: process.env.INTERCOM_ACCESS_TOKEN
72
+ });
73
+ ```
74
+
75
+ **With custom configuration:**
76
+
77
+ ```javascript
78
+ const client = new IntercomClient({
79
+ token: process.env.INTERCOM_ACCESS_TOKEN,
80
+ timeoutInSeconds: 120, // Default is 60
81
+ maxRetries: 3, // Default is 2
82
+ });
83
+ ```
84
+
85
+ **API Version Selection:**
86
+
87
+ ```javascript
88
+ // Use specific API version
89
+ const client = new IntercomClient({
90
+ token: process.env.INTERCOM_ACCESS_TOKEN,
91
+ apiVersion: '2.11', // Default is latest stable (2.11)
92
+ });
93
+ ```
94
+
95
+ ## Core API Surfaces
96
+
97
+ ### Contacts
98
+
99
+ Contacts represent users, leads, and visitors in Intercom. They are the primary entities for customer communication.
100
+
101
+ **Create a contact:**
102
+
103
+ ```javascript
104
+ const contact = await client.contacts.create({
105
+ email: '[email protected]',
106
+ name: 'John Doe',
107
+ phone: '+1234567890',
108
+ role: 'user', // 'user' or 'lead'
109
+ });
110
+
111
+ console.log(contact.id);
112
+ ```
113
+
114
+ **Create with custom attributes:**
115
+
116
+ ```javascript
117
+ const contact = await client.contacts.create({
118
+ email: '[email protected]',
119
+ name: 'Jane Smith',
120
+ role: 'user',
121
+ custom_attributes: {
122
+ plan: 'premium',
123
+ signup_date: '2025-01-15',
124
+ total_spend: 599.99,
125
+ active: true,
126
+ },
127
+ });
128
+ ```
129
+
130
+ **Retrieve a contact:**
131
+
132
+ ```javascript
133
+ const contact = await client.contacts.find({
134
+ id: '65f9a5e4f5e5b40001234567',
135
+ });
136
+
137
+ console.log(contact.email, contact.name);
138
+ ```
139
+
140
+ **Update a contact:**
141
+
142
+ ```javascript
143
+ const updated = await client.contacts.update({
144
+ id: '65f9a5e4f5e5b40001234567',
145
+ name: 'John Updated',
146
+ custom_attributes: {
147
+ plan: 'enterprise',
148
+ },
149
+ });
150
+ ```
151
+
152
+ **Search contacts:**
153
+
154
+ ```javascript
155
+ const results = await client.contacts.search({
156
+ query: {
157
+ field: 'email',
158
+ operator: '=',
159
+ value: '[email protected]',
160
+ },
161
+ });
162
+
163
+ for (const contact of results.data) {
164
+ console.log(contact.name, contact.email);
165
+ }
166
+ ```
167
+
168
+ **Search with filters:**
169
+
170
+ ```javascript
171
+ const results = await client.contacts.search({
172
+ query: {
173
+ operator: 'AND',
174
+ value: [
175
+ {
176
+ field: 'role',
177
+ operator: '=',
178
+ value: 'user',
179
+ },
180
+ {
181
+ field: 'created_at',
182
+ operator: '>',
183
+ value: 1704067200, // Unix timestamp
184
+ },
185
+ ],
186
+ },
187
+ pagination: {
188
+ per_page: 50,
189
+ },
190
+ });
191
+ ```
192
+
193
+ **List all contacts:**
194
+
195
+ ```javascript
196
+ const response = await client.contacts.list({
197
+ per_page: 150,
198
+ });
199
+
200
+ // Iterate through paginated results
201
+ for await (const contact of response) {
202
+ console.log(contact.email);
203
+ }
204
+ ```
205
+
206
+ **Delete a contact:**
207
+
208
+ ```javascript
209
+ await client.contacts.delete({
210
+ id: '65f9a5e4f5e5b40001234567',
211
+ });
212
+ ```
213
+
214
+ **Archive a contact:**
215
+
216
+ ```javascript
217
+ const archived = await client.contacts.archive({
218
+ id: '65f9a5e4f5e5b40001234567',
219
+ });
220
+ ```
221
+
222
+ **Unarchive a contact:**
223
+
224
+ ```javascript
225
+ const unarchived = await client.contacts.unarchive({
226
+ id: '65f9a5e4f5e5b40001234567',
227
+ });
228
+ ```
229
+
230
+ **Merge contacts:**
231
+
232
+ ```javascript
233
+ const merged = await client.contacts.merge({
234
+ from: '65f9a5e4f5e5b40001234567',
235
+ into: '65f9a5e4f5e5b40009876543',
236
+ });
237
+ ```
238
+
239
+ ### Companies
240
+
241
+ Companies group contacts together by organization. They're useful for B2B use cases.
242
+
243
+ **Create a company:**
244
+
245
+ ```javascript
246
+ const company = await client.companies.create({
247
+ company_id: 'company_123',
248
+ name: 'Acme Corporation',
249
+ website: 'https://acme.com',
250
+ industry: 'Technology',
251
+ size: 500,
252
+ custom_attributes: {
253
+ plan_level: 'enterprise',
254
+ mrr: 50000,
255
+ },
256
+ });
257
+ ```
258
+
259
+ **Retrieve a company:**
260
+
261
+ ```javascript
262
+ const company = await client.companies.find({
263
+ company_id: 'company_123',
264
+ });
265
+ ```
266
+
267
+ **Update a company:**
268
+
269
+ ```javascript
270
+ const updated = await client.companies.update({
271
+ company_id: 'company_123',
272
+ name: 'Acme Corp',
273
+ size: 600,
274
+ custom_attributes: {
275
+ mrr: 60000,
276
+ },
277
+ });
278
+ ```
279
+
280
+ **List companies:**
281
+
282
+ ```javascript
283
+ const response = await client.companies.list({
284
+ per_page: 50,
285
+ });
286
+
287
+ for await (const company of response) {
288
+ console.log(company.name, company.company_id);
289
+ }
290
+ ```
291
+
292
+ **Attach contact to company:**
293
+
294
+ ```javascript
295
+ await client.contacts.update({
296
+ id: '65f9a5e4f5e5b40001234567',
297
+ companies: [
298
+ {
299
+ company_id: 'company_123',
300
+ },
301
+ ],
302
+ });
303
+ ```
304
+
305
+ **List company contacts:**
306
+
307
+ ```javascript
308
+ const contacts = await client.companies.listContacts({
309
+ company_id: 'company_123',
310
+ });
311
+
312
+ for await (const contact of contacts) {
313
+ console.log(contact.email);
314
+ }
315
+ ```
316
+
317
+ **Delete a company:**
318
+
319
+ ```javascript
320
+ await client.companies.delete({
321
+ company_id: 'company_123',
322
+ });
323
+ ```
324
+
325
+ ### Conversations
326
+
327
+ Conversations are threads of communication between contacts and your team.
328
+
329
+ **Create a conversation:**
330
+
331
+ ```javascript
332
+ const conversation = await client.conversations.create({
333
+ from: {
334
+ type: 'user',
335
+ id: '65f9a5e4f5e5b40001234567',
336
+ },
337
+ body: 'Hello, I need help with my account.',
338
+ });
339
+
340
+ console.log(conversation.id);
341
+ ```
342
+
343
+ **Create conversation with user:**
344
+
345
+ ```javascript
346
+ const conversation = await client.conversations.createConversation({
347
+ userId: '65f9a5e4f5e5b40001234567',
348
+ body: 'I have a question about billing.',
349
+ });
350
+ ```
351
+
352
+ **Retrieve a conversation:**
353
+
354
+ ```javascript
355
+ const conversation = await client.conversations.find({
356
+ id: '123456',
357
+ });
358
+
359
+ console.log(conversation.state); // 'open', 'closed', 'snoozed'
360
+ ```
361
+
362
+ **Reply to conversation as admin:**
363
+
364
+ ```javascript
365
+ const reply = await client.conversations.reply({
366
+ id: '123456',
367
+ message_type: 'comment',
368
+ type: 'admin',
369
+ admin_id: '987654',
370
+ body: 'Thanks for reaching out! How can I help?',
371
+ });
372
+ ```
373
+
374
+ **Reply with attachment:**
375
+
376
+ ```javascript
377
+ const reply = await client.conversations.reply({
378
+ id: '123456',
379
+ message_type: 'comment',
380
+ type: 'admin',
381
+ admin_id: '987654',
382
+ body: 'Here is the document you requested.',
383
+ attachment_urls: [
384
+ 'https://example.com/document.pdf',
385
+ ],
386
+ });
387
+ ```
388
+
389
+ **Reply as user:**
390
+
391
+ ```javascript
392
+ const reply = await client.conversations.reply({
393
+ id: '123456',
394
+ message_type: 'comment',
395
+ type: 'user',
396
+ user_id: '65f9a5e4f5e5b40001234567',
397
+ body: 'Thank you for your help!',
398
+ });
399
+ ```
400
+
401
+ **Search conversations:**
402
+
403
+ ```javascript
404
+ const results = await client.conversations.search({
405
+ query: {
406
+ field: 'state',
407
+ operator: '=',
408
+ value: 'open',
409
+ },
410
+ pagination: {
411
+ per_page: 50,
412
+ },
413
+ });
414
+
415
+ for (const conv of results.conversations) {
416
+ console.log(conv.id, conv.created_at);
417
+ }
418
+ ```
419
+
420
+ **Search with multiple filters:**
421
+
422
+ ```javascript
423
+ const results = await client.conversations.search({
424
+ query: {
425
+ operator: 'AND',
426
+ value: [
427
+ {
428
+ field: 'state',
429
+ operator: '=',
430
+ value: 'open',
431
+ },
432
+ {
433
+ field: 'updated_at',
434
+ operator: '>',
435
+ value: 1704067200,
436
+ },
437
+ ],
438
+ },
439
+ sort: {
440
+ field: 'updated_at',
441
+ order: 'descending',
442
+ },
443
+ });
444
+ ```
445
+
446
+ **List conversations:**
447
+
448
+ ```javascript
449
+ const response = await client.conversations.list();
450
+
451
+ for await (const conversation of response) {
452
+ console.log(conversation.id, conversation.state);
453
+ }
454
+ ```
455
+
456
+ **Close a conversation:**
457
+
458
+ ```javascript
459
+ const closed = await client.conversations.close({
460
+ id: '123456',
461
+ type: 'admin',
462
+ admin_id: '987654',
463
+ });
464
+ ```
465
+
466
+ **Open a conversation:**
467
+
468
+ ```javascript
469
+ const opened = await client.conversations.open({
470
+ id: '123456',
471
+ type: 'admin',
472
+ admin_id: '987654',
473
+ });
474
+ ```
475
+
476
+ **Snooze a conversation:**
477
+
478
+ ```javascript
479
+ const snoozed = await client.conversations.snooze({
480
+ id: '123456',
481
+ type: 'admin',
482
+ admin_id: '987654',
483
+ snoozed_until: 1704153600, // Unix timestamp
484
+ });
485
+ ```
486
+
487
+ **Assign conversation to admin:**
488
+
489
+ ```javascript
490
+ const assigned = await client.conversations.assign({
491
+ id: '123456',
492
+ type: 'admin',
493
+ admin_id: '987654',
494
+ assignee_id: '111222',
495
+ });
496
+ ```
497
+
498
+ **Assign to team:**
499
+
500
+ ```javascript
501
+ const assigned = await client.conversations.assign({
502
+ id: '123456',
503
+ type: 'admin',
504
+ admin_id: '987654',
505
+ assignee_id: '333444',
506
+ assignment_type: 'team',
507
+ });
508
+ ```
509
+
510
+ **Convert conversation to ticket:**
511
+
512
+ ```javascript
513
+ const ticket = await client.conversations.convertToTicket({
514
+ id: '123456',
515
+ ticket_type_id: '100',
516
+ });
517
+ ```
518
+
519
+ **Add tag to conversation:**
520
+
521
+ ```javascript
522
+ await client.conversations.attachTag({
523
+ conversationId: '123456',
524
+ id: 'tag_789',
525
+ adminId: '987654',
526
+ });
527
+ ```
528
+
529
+ **Remove tag from conversation:**
530
+
531
+ ```javascript
532
+ await client.conversations.detachTag({
533
+ conversationId: '123456',
534
+ id: 'tag_789',
535
+ adminId: '987654',
536
+ });
537
+ ```
538
+
539
+ ### Messages
540
+
541
+ Send messages to contacts via Intercom.
542
+
543
+ **Send a message to contact:**
544
+
545
+ ```javascript
546
+ const message = await client.messages.create({
547
+ message_type: 'email',
548
+ from: {
549
+ type: 'admin',
550
+ id: '987654',
551
+ },
552
+ to: {
553
+ type: 'user',
554
+ id: '65f9a5e4f5e5b40001234567',
555
+ },
556
+ subject: 'Welcome to our platform',
557
+ body: 'Thanks for signing up! Here are some tips to get started.',
558
+ });
559
+ ```
560
+
561
+ **Send message by email:**
562
+
563
+ ```javascript
564
+ const message = await client.messages.create({
565
+ message_type: 'email',
566
+ from: {
567
+ type: 'admin',
568
+ id: '987654',
569
+ },
570
+ to: {
571
+ type: 'user',
572
+ email: '[email protected]',
573
+ },
574
+ subject: 'Your monthly report',
575
+ body: 'Here is your activity summary for January.',
576
+ });
577
+ ```
578
+
579
+ **Send in-app message:**
580
+
581
+ ```javascript
582
+ const message = await client.messages.create({
583
+ message_type: 'inapp',
584
+ from: {
585
+ type: 'admin',
586
+ id: '987654',
587
+ },
588
+ to: {
589
+ type: 'user',
590
+ id: '65f9a5e4f5e5b40001234567',
591
+ },
592
+ body: 'Check out our new features!',
593
+ });
594
+ ```
595
+
596
+ **Send message with custom data:**
597
+
598
+ ```javascript
599
+ const message = await client.messages.create({
600
+ message_type: 'email',
601
+ from: {
602
+ type: 'admin',
603
+ id: '987654',
604
+ },
605
+ to: {
606
+ type: 'user',
607
+ id: '65f9a5e4f5e5b40001234567',
608
+ },
609
+ subject: 'Order confirmation',
610
+ body: 'Your order has been confirmed.',
611
+ template: 'plain',
612
+ create_conversation_without_contact_reply: false,
613
+ });
614
+ ```
615
+
616
+ ### Data Events
617
+
618
+ Track user behavior and custom events.
619
+
620
+ **Submit a data event:**
621
+
622
+ ```javascript
623
+ await client.events.create({
624
+ event_name: 'purchased_item',
625
+ created_at: Math.floor(Date.now() / 1000),
626
+ user_id: '65f9a5e4f5e5b40001234567',
627
+ metadata: {
628
+ item_name: 'Premium Plan',
629
+ item_price: 99.99,
630
+ currency: 'USD',
631
+ quantity: 1,
632
+ },
633
+ });
634
+ ```
635
+
636
+ **Event with email identifier:**
637
+
638
+ ```javascript
639
+ await client.events.create({
640
+ event_name: 'signed_up',
641
+ created_at: Math.floor(Date.now() / 1000),
642
+ email: '[email protected]',
643
+ metadata: {
644
+ source: 'landing_page',
645
+ campaign: 'winter_2025',
646
+ },
647
+ });
648
+ ```
649
+
650
+ **Complex event metadata:**
651
+
652
+ ```javascript
653
+ await client.events.create({
654
+ event_name: 'completed_onboarding',
655
+ created_at: Math.floor(Date.now() / 1000),
656
+ user_id: '65f9a5e4f5e5b40001234567',
657
+ metadata: {
658
+ steps_completed: 5,
659
+ time_taken_seconds: 320,
660
+ skipped_steps: ['profile_picture'],
661
+ completion_rate: 0.95,
662
+ device: 'mobile',
663
+ },
664
+ });
665
+ ```
666
+
667
+ **List events for user:**
668
+
669
+ ```javascript
670
+ const events = await client.events.list({
671
+ type: 'user',
672
+ user_id: '65f9a5e4f5e5b40001234567',
673
+ });
674
+
675
+ for (const event of events.events) {
676
+ console.log(event.event_name, event.created_at);
677
+ }
678
+ ```
679
+
680
+ **Event summaries:**
681
+
682
+ ```javascript
683
+ const summary = await client.events.summaries({
684
+ user_id: '65f9a5e4f5e5b40001234567',
685
+ event_name: 'purchased_item',
686
+ });
687
+
688
+ console.log(summary.count, summary.first, summary.last);
689
+ ```
690
+
691
+ ### Tags
692
+
693
+ Organize and categorize contacts, companies, and conversations.
694
+
695
+ **Create a tag:**
696
+
697
+ ```javascript
698
+ const tag = await client.tags.create({
699
+ name: 'VIP Customer',
700
+ });
701
+
702
+ console.log(tag.id);
703
+ ```
704
+
705
+ **Retrieve a tag:**
706
+
707
+ ```javascript
708
+ const tag = await client.tags.find({
709
+ id: 'tag_789',
710
+ });
711
+ ```
712
+
713
+ **List all tags:**
714
+
715
+ ```javascript
716
+ const tags = await client.tags.list();
717
+
718
+ for (const tag of tags.data) {
719
+ console.log(tag.name, tag.id);
720
+ }
721
+ ```
722
+
723
+ **Tag a contact:**
724
+
725
+ ```javascript
726
+ await client.contacts.tag({
727
+ contactId: '65f9a5e4f5e5b40001234567',
728
+ id: 'tag_789',
729
+ });
730
+ ```
731
+
732
+ **Tag a company:**
733
+
734
+ ```javascript
735
+ await client.companies.tag({
736
+ companyId: 'company_123',
737
+ id: 'tag_789',
738
+ });
739
+ ```
740
+
741
+ **Untag a contact:**
742
+
743
+ ```javascript
744
+ await client.contacts.untag({
745
+ contactId: '65f9a5e4f5e5b40001234567',
746
+ id: 'tag_789',
747
+ });
748
+ ```
749
+
750
+ **Delete a tag:**
751
+
752
+ ```javascript
753
+ await client.tags.delete({
754
+ id: 'tag_789',
755
+ });
756
+ ```
757
+
758
+ ### Data Attributes
759
+
760
+ Define custom attributes for contacts and companies.
761
+
762
+ **Create a contact attribute:**
763
+
764
+ ```javascript
765
+ const attribute = await client.dataAttributes.create({
766
+ name: 'subscription_tier',
767
+ model: 'contact',
768
+ data_type: 'string',
769
+ options: ['free', 'pro', 'enterprise'],
770
+ description: 'Customer subscription level',
771
+ });
772
+ ```
773
+
774
+ **Create a company attribute:**
775
+
776
+ ```javascript
777
+ const attribute = await client.dataAttributes.create({
778
+ name: 'annual_revenue',
779
+ model: 'company',
780
+ data_type: 'float',
781
+ description: 'Company annual revenue in USD',
782
+ });
783
+ ```
784
+
785
+ **Create boolean attribute:**
786
+
787
+ ```javascript
788
+ const attribute = await client.dataAttributes.create({
789
+ name: 'is_beta_tester',
790
+ model: 'contact',
791
+ data_type: 'boolean',
792
+ description: 'Whether user is enrolled in beta program',
793
+ });
794
+ ```
795
+
796
+ **Create date attribute:**
797
+
798
+ ```javascript
799
+ const attribute = await client.dataAttributes.create({
800
+ name: 'trial_end_date',
801
+ model: 'contact',
802
+ data_type: 'date',
803
+ description: 'Date when trial period ends',
804
+ });
805
+ ```
806
+
807
+ **List data attributes:**
808
+
809
+ ```javascript
810
+ const attributes = await client.dataAttributes.list({
811
+ model: 'contact',
812
+ });
813
+
814
+ for (const attr of attributes.data) {
815
+ console.log(attr.name, attr.data_type);
816
+ }
817
+ ```
818
+
819
+ **Update an attribute:**
820
+
821
+ ```javascript
822
+ const updated = await client.dataAttributes.update({
823
+ id: 'attr_123',
824
+ description: 'Updated description',
825
+ options: ['free', 'pro', 'enterprise', 'custom'],
826
+ });
827
+ ```
828
+
829
+ ### Notes
830
+
831
+ Add notes to contacts and companies for internal reference.
832
+
833
+ **Create a note for contact:**
834
+
835
+ ```javascript
836
+ const note = await client.notes.create({
837
+ contact_id: '65f9a5e4f5e5b40001234567',
838
+ admin_id: '987654',
839
+ body: 'Customer requested custom integration. Follow up next week.',
840
+ });
841
+ ```
842
+
843
+ **Create a note for company:**
844
+
845
+ ```javascript
846
+ const note = await client.notes.create({
847
+ company_id: 'company_123',
848
+ admin_id: '987654',
849
+ body: 'Contract renewal coming up in Q2 2025.',
850
+ });
851
+ ```
852
+
853
+ **Retrieve a note:**
854
+
855
+ ```javascript
856
+ const note = await client.notes.find({
857
+ id: 'note_456',
858
+ });
859
+ ```
860
+
861
+ **List notes for contact:**
862
+
863
+ ```javascript
864
+ const notes = await client.contacts.listNotes({
865
+ id: '65f9a5e4f5e5b40001234567',
866
+ });
867
+
868
+ for (const note of notes.data) {
869
+ console.log(note.body, note.created_at);
870
+ }
871
+ ```
872
+
873
+ ### Segments
874
+
875
+ Query and retrieve segments (groups of contacts).
876
+
877
+ **List all segments:**
878
+
879
+ ```javascript
880
+ const segments = await client.segments.list();
881
+
882
+ for (const segment of segments.segments) {
883
+ console.log(segment.name, segment.count);
884
+ }
885
+ ```
886
+
887
+ **Retrieve a segment:**
888
+
889
+ ```javascript
890
+ const segment = await client.segments.find({
891
+ id: 'segment_999',
892
+ });
893
+
894
+ console.log(segment.name, segment.person_type);
895
+ ```
896
+
897
+ **List contacts in segment:**
898
+
899
+ ```javascript
900
+ const contacts = await client.segments.listContacts({
901
+ id: 'segment_999',
902
+ });
903
+
904
+ for await (const contact of contacts) {
905
+ console.log(contact.email);
906
+ }
907
+ ```
908
+
909
+ ### Tickets
910
+
911
+ Manage customer support tickets.
912
+
913
+ **Create a ticket:**
914
+
915
+ ```javascript
916
+ const ticket = await client.tickets.create({
917
+ contact_id: '65f9a5e4f5e5b40001234567',
918
+ ticket_type_id: '100',
919
+ contacts: [
920
+ {
921
+ id: '65f9a5e4f5e5b40001234567',
922
+ },
923
+ ],
924
+ ticket_attributes: {
925
+ _default_title_: 'Payment issue',
926
+ _default_description_: 'Customer unable to process payment',
927
+ },
928
+ });
929
+ ```
930
+
931
+ **Retrieve a ticket:**
932
+
933
+ ```javascript
934
+ const ticket = await client.tickets.find({
935
+ id: 'ticket_888',
936
+ });
937
+
938
+ console.log(ticket.ticket_state);
939
+ ```
940
+
941
+ **Update a ticket:**
942
+
943
+ ```javascript
944
+ const updated = await client.tickets.update({
945
+ id: 'ticket_888',
946
+ ticket_attributes: {
947
+ _default_title_: 'Payment issue - RESOLVED',
948
+ },
949
+ ticket_state: 'submitted',
950
+ });
951
+ ```
952
+
953
+ **Reply to ticket:**
954
+
955
+ ```javascript
956
+ const reply = await client.tickets.reply({
957
+ id: 'ticket_888',
958
+ admin_id: '987654',
959
+ message_type: 'comment',
960
+ body: 'Issue has been resolved. Payment processed successfully.',
961
+ });
962
+ ```
963
+
964
+ **Search tickets:**
965
+
966
+ ```javascript
967
+ const results = await client.tickets.search({
968
+ query: {
969
+ field: 'ticket_state',
970
+ operator: '=',
971
+ value: 'submitted',
972
+ },
973
+ });
974
+
975
+ for (const ticket of results.tickets) {
976
+ console.log(ticket.id, ticket.ticket_attributes);
977
+ }
978
+ ```
979
+
980
+ ### Admins
981
+
982
+ Manage admin users and teams.
983
+
984
+ **List all admins:**
985
+
986
+ ```javascript
987
+ const admins = await client.admins.list();
988
+
989
+ for (const admin of admins.admins) {
990
+ console.log(admin.name, admin.email);
991
+ }
992
+ ```
993
+
994
+ **Retrieve an admin:**
995
+
996
+ ```javascript
997
+ const admin = await client.admins.find({
998
+ id: '987654',
999
+ });
1000
+
1001
+ console.log(admin.name, admin.away_mode_enabled);
1002
+ ```
1003
+
1004
+ **Retrieve current admin:**
1005
+
1006
+ ```javascript
1007
+ const me = await client.admins.me();
1008
+
1009
+ console.log(me.name, me.email);
1010
+ ```
1011
+
1012
+ **Set away mode:**
1013
+
1014
+ ```javascript
1015
+ const updated = await client.admins.setAwayMode({
1016
+ admin_id: '987654',
1017
+ away_mode_enabled: true,
1018
+ away_mode_reassign: true,
1019
+ });
1020
+ ```
1021
+
1022
+ **List teams:**
1023
+
1024
+ ```javascript
1025
+ const teams = await client.teams.list();
1026
+
1027
+ for (const team of teams.teams) {
1028
+ console.log(team.name, team.id);
1029
+ }
1030
+ ```
1031
+
1032
+ **Retrieve a team:**
1033
+
1034
+ ```javascript
1035
+ const team = await client.teams.find({
1036
+ id: '333444',
1037
+ });
1038
+ ```
1039
+
1040
+ ### Articles
1041
+
1042
+ Manage help center articles.
1043
+
1044
+ **Create an article:**
1045
+
1046
+ ```javascript
1047
+ const article = await client.articles.create({
1048
+ title: 'Getting Started Guide',
1049
+ description: 'Learn how to use our platform',
1050
+ body: '<h1>Welcome</h1><p>This guide will help you get started...</p>',
1051
+ author_id: 987654,
1052
+ state: 'published',
1053
+ });
1054
+ ```
1055
+
1056
+ **Retrieve an article:**
1057
+
1058
+ ```javascript
1059
+ const article = await client.articles.find({
1060
+ id: 'article_555',
1061
+ });
1062
+ ```
1063
+
1064
+ **Update an article:**
1065
+
1066
+ ```javascript
1067
+ const updated = await client.articles.update({
1068
+ id: 'article_555',
1069
+ title: 'Getting Started Guide (Updated)',
1070
+ body: '<h1>Welcome</h1><p>This updated guide...</p>',
1071
+ });
1072
+ ```
1073
+
1074
+ **List articles:**
1075
+
1076
+ ```javascript
1077
+ const response = await client.articles.list({
1078
+ per_page: 50,
1079
+ });
1080
+
1081
+ for await (const article of response) {
1082
+ console.log(article.title, article.state);
1083
+ }
1084
+ ```
1085
+
1086
+ **Delete an article:**
1087
+
1088
+ ```javascript
1089
+ await client.articles.delete({
1090
+ id: 'article_555',
1091
+ });
1092
+ ```
1093
+
1094
+ ### Subscription Types
1095
+
1096
+ Manage subscription preferences for contacts.
1097
+
1098
+ **List subscription types:**
1099
+
1100
+ ```javascript
1101
+ const types = await client.subscriptionTypes.list();
1102
+
1103
+ for (const type of types.data) {
1104
+ console.log(type.id, type.content_type);
1105
+ }
1106
+ ```
1107
+
1108
+ **Subscribe contact:**
1109
+
1110
+ ```javascript
1111
+ await client.contacts.subscribe({
1112
+ id: '65f9a5e4f5e5b40001234567',
1113
+ subscription_type_id: 'sub_123',
1114
+ });
1115
+ ```
1116
+
1117
+ **Unsubscribe contact:**
1118
+
1119
+ ```javascript
1120
+ await client.contacts.unsubscribe({
1121
+ id: '65f9a5e4f5e5b40001234567',
1122
+ subscription_type_id: 'sub_123',
1123
+ });
1124
+ ```
1125
+
1126
+ ## Error Handling
1127
+
1128
+ **Basic error handling:**
1129
+
1130
+ ```javascript
1131
+ import { IntercomError } from 'intercom-client';
1132
+
1133
+ try {
1134
+ const contact = await client.contacts.find({ id: 'invalid_id' });
1135
+ } catch (err) {
1136
+ if (err instanceof IntercomError) {
1137
+ console.error('Status:', err.statusCode);
1138
+ console.error('Message:', err.message);
1139
+ console.error('Body:', err.body);
1140
+ }
1141
+ }
1142
+ ```
1143
+
1144
+ **Handle specific error codes:**
1145
+
1146
+ ```javascript
1147
+ try {
1148
+ await client.contacts.create({ email: '[email protected]' });
1149
+ } catch (err) {
1150
+ if (err instanceof IntercomError) {
1151
+ switch (err.statusCode) {
1152
+ case 400:
1153
+ console.error('Bad request:', err.message);
1154
+ break;
1155
+ case 401:
1156
+ console.error('Unauthorized - check your token');
1157
+ break;
1158
+ case 404:
1159
+ console.error('Resource not found');
1160
+ break;
1161
+ case 429:
1162
+ console.error('Rate limit exceeded');
1163
+ break;
1164
+ default:
1165
+ console.error('Error:', err.message);
1166
+ }
1167
+ }
1168
+ }
1169
+ ```
1170
+
1171
+ **Retry on rate limit:**
1172
+
1173
+ ```javascript
1174
+ async function createContactWithRetry(data, maxRetries = 3) {
1175
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1176
+ try {
1177
+ return await client.contacts.create(data);
1178
+ } catch (err) {
1179
+ if (err instanceof IntercomError && err.statusCode === 429) {
1180
+ if (attempt < maxRetries) {
1181
+ const delay = Math.pow(2, attempt) * 1000;
1182
+ console.log(`Rate limited, retrying in ${delay}ms...`);
1183
+ await new Promise(resolve => setTimeout(resolve, delay));
1184
+ continue;
1185
+ }
1186
+ }
1187
+ throw err;
1188
+ }
1189
+ }
1190
+ }
1191
+ ```
1192
+
1193
+ ## Pagination
1194
+
1195
+ **Auto-pagination with for-await:**
1196
+
1197
+ ```javascript
1198
+ const response = await client.contacts.list();
1199
+
1200
+ for await (const contact of response) {
1201
+ console.log(contact.email);
1202
+ // Automatically fetches next page when needed
1203
+ }
1204
+ ```
1205
+
1206
+ **Manual pagination:**
1207
+
1208
+ ```javascript
1209
+ let hasMore = true;
1210
+ let startingAfter = null;
1211
+
1212
+ while (hasMore) {
1213
+ const response = await client.contacts.list({
1214
+ per_page: 50,
1215
+ starting_after: startingAfter,
1216
+ });
1217
+
1218
+ for (const contact of response.data) {
1219
+ console.log(contact.email);
1220
+ }
1221
+
1222
+ hasMore = response.pages && response.pages.next;
1223
+ startingAfter = response.pages?.next?.starting_after;
1224
+ }
1225
+ ```
1226
+
1227
+ **Get all pages at once:**
1228
+
1229
+ ```javascript
1230
+ const allContacts = [];
1231
+ const response = await client.contacts.list();
1232
+
1233
+ for await (const contact of response) {
1234
+ allContacts.push(contact);
1235
+ }
1236
+
1237
+ console.log(`Total contacts: ${allContacts.length}`);
1238
+ ```
1239
+
1240
+ ## Advanced Features
1241
+
1242
+ **Custom headers:**
1243
+
1244
+ ```javascript
1245
+ const contact = await client.contacts.create(
1246
+ {
1247
+ email: '[email protected]',
1248
+ name: 'Test User',
1249
+ },
1250
+ {
1251
+ headers: {
1252
+ 'X-Custom-Header': 'custom-value',
1253
+ },
1254
+ }
1255
+ );
1256
+ ```
1257
+
1258
+ **Request timeout:**
1259
+
1260
+ ```javascript
1261
+ const contact = await client.contacts.find(
1262
+ { id: '65f9a5e4f5e5b40001234567' },
1263
+ {
1264
+ timeoutInSeconds: 30,
1265
+ }
1266
+ );
1267
+ ```
1268
+
1269
+ **Abort requests:**
1270
+
1271
+ ```javascript
1272
+ const controller = new AbortController();
1273
+
1274
+ // Cancel after 5 seconds
1275
+ setTimeout(() => controller.abort(), 5000);
1276
+
1277
+ try {
1278
+ const contact = await client.contacts.create(
1279
+ {
1280
+ email: '[email protected]',
1281
+ },
1282
+ {
1283
+ abortSignal: controller.signal,
1284
+ }
1285
+ );
1286
+ } catch (err) {
1287
+ if (err.name === 'AbortError') {
1288
+ console.log('Request was aborted');
1289
+ }
1290
+ }
1291
+ ```
1292
+
1293
+ **Access raw response:**
1294
+
1295
+ ```javascript
1296
+ const response = await client.contacts
1297
+ .withRawResponse()
1298
+ .find({ id: '65f9a5e4f5e5b40001234567' });
1299
+
1300
+ console.log('Status:', response.statusCode);
1301
+ console.log('Headers:', response.headers);
1302
+ console.log('Body:', response.body);
1303
+ ```
1304
+
1305
+ **Disable automatic retries:**
1306
+
1307
+ ```javascript
1308
+ const client = new IntercomClient({
1309
+ token: process.env.INTERCOM_ACCESS_TOKEN,
1310
+ maxRetries: 0, // Disable retries
1311
+ });
1312
+ ```
1313
+
1314
+ **Custom retry configuration:**
1315
+
1316
+ ```javascript
1317
+ const client = new IntercomClient({
1318
+ token: process.env.INTERCOM_ACCESS_TOKEN,
1319
+ maxRetries: 5,
1320
+ timeoutInSeconds: 90,
1321
+ });
1322
+ ```
1323
+
1324
+ ## Type Definitions
1325
+
1326
+ **Using request types:**
1327
+
1328
+ ```typescript
1329
+ import { Intercom } from 'intercom-client';
1330
+
1331
+ const createRequest: Intercom.ContactCreateRequest = {
1332
+ email: '[email protected]',
1333
+ name: 'Jane Doe',
1334
+ role: 'user',
1335
+ custom_attributes: {
1336
+ plan: 'premium',
1337
+ },
1338
+ };
1339
+
1340
+ const contact = await client.contacts.create(createRequest);
1341
+ ```
1342
+
1343
+ **Using response types:**
1344
+
1345
+ ```typescript
1346
+ import { Intercom } from 'intercom-client';
1347
+
1348
+ const contact: Intercom.Contact = await client.contacts.find({
1349
+ id: '65f9a5e4f5e5b40001234567',
1350
+ });
1351
+
1352
+ console.log(contact.email, contact.created_at);
1353
+ ```
1354
+
1355
+ **Conversation types:**
1356
+
1357
+ ```typescript
1358
+ import { Intercom } from 'intercom-client';
1359
+
1360
+ const conversation: Intercom.Conversation = await client.conversations.find({
1361
+ id: '123456',
1362
+ });
1363
+
1364
+ const state: Intercom.ConversationState = conversation.state;
1365
+ // 'open' | 'closed' | 'snoozed'
1366
+ ```
1367
+
1368
+ **Event metadata typing:**
1369
+
1370
+ ```typescript
1371
+ interface PurchaseMetadata {
1372
+ item_name: string;
1373
+ item_price: number;
1374
+ currency: string;
1375
+ quantity: number;
1376
+ }
1377
+
1378
+ await client.events.create({
1379
+ event_name: 'purchased_item',
1380
+ created_at: Math.floor(Date.now() / 1000),
1381
+ user_id: '65f9a5e4f5e5b40001234567',
1382
+ metadata: {
1383
+ item_name: 'Premium Plan',
1384
+ item_price: 99.99,
1385
+ currency: 'USD',
1386
+ quantity: 1,
1387
+ } as PurchaseMetadata,
1388
+ });
1389
+ ```
1390
+
1391
+ ## Webhooks
1392
+
1393
+ **Verify webhook signature:**
1394
+
1395
+ ```javascript
1396
+ import crypto from 'crypto';
1397
+
1398
+ function verifyWebhook(body, signature, secret) {
1399
+ const hash = crypto
1400
+ .createHmac('sha256', secret)
1401
+ .update(body)
1402
+ .digest('hex');
1403
+
1404
+ return signature === hash;
1405
+ }
1406
+
1407
+ // Express example
1408
+ app.post('/webhooks/intercom', (req, res) => {
1409
+ const signature = req.headers['x-hub-signature'];
1410
+ const isValid = verifyWebhook(
1411
+ JSON.stringify(req.body),
1412
+ signature,
1413
+ process.env.INTERCOM_WEBHOOK_SECRET
1414
+ );
1415
+
1416
+ if (!isValid) {
1417
+ return res.status(401).send('Invalid signature');
1418
+ }
1419
+
1420
+ const event = req.body;
1421
+ console.log('Webhook event:', event.topic);
1422
+
1423
+ res.sendStatus(200);
1424
+ });
1425
+ ```
1426
+
1427
+ **Handle webhook events:**
1428
+
1429
+ ```javascript
1430
+ app.post('/webhooks/intercom', (req, res) => {
1431
+ const { topic, data } = req.body;
1432
+
1433
+ switch (topic) {
1434
+ case 'contact.created':
1435
+ console.log('New contact:', data.item.email);
1436
+ break;
1437
+
1438
+ case 'conversation.user.created':
1439
+ console.log('New conversation:', data.item.id);
1440
+ break;
1441
+
1442
+ case 'conversation.admin.replied':
1443
+ console.log('Admin replied to:', data.item.id);
1444
+ break;
1445
+
1446
+ case 'user.tag.created':
1447
+ console.log('User tagged:', data.item.user.email);
1448
+ break;
1449
+
1450
+ default:
1451
+ console.log('Unknown event:', topic);
1452
+ }
1453
+
1454
+ res.sendStatus(200);
1455
+ });
1456
+ ```
1457
+
1458
+ ## Rate Limiting
1459
+
1460
+ Intercom enforces rate limits on API requests. The SDK handles retries automatically.
1461
+
1462
+ **Default retry behavior:**
1463
+
1464
+ ```javascript
1465
+ // SDK automatically retries on 429 (rate limit) responses
1466
+ // with exponential backoff (2 retries by default)
1467
+
1468
+ const client = new IntercomClient({
1469
+ token: process.env.INTERCOM_ACCESS_TOKEN,
1470
+ maxRetries: 2, // Default
1471
+ });
1472
+ ```
1473
+
1474
+ **Rate limit headers:**
1475
+
1476
+ ```javascript
1477
+ const response = await client.contacts
1478
+ .withRawResponse()
1479
+ .list();
1480
+
1481
+ console.log('Rate limit:', response.headers['x-ratelimit-limit']);
1482
+ console.log('Remaining:', response.headers['x-ratelimit-remaining']);
1483
+ console.log('Reset:', response.headers['x-ratelimit-reset']);
1484
+ ```
1485
+
1486
+ **Handle rate limits manually:**
1487
+
1488
+ ```javascript
1489
+ async function makeRequestWithBackoff(requestFn, maxRetries = 5) {
1490
+ for (let i = 0; i < maxRetries; i++) {
1491
+ try {
1492
+ return await requestFn();
1493
+ } catch (err) {
1494
+ if (err instanceof IntercomError && err.statusCode === 429) {
1495
+ const resetHeader = err.headers?.['x-ratelimit-reset'];
1496
+ const resetTime = resetHeader ? parseInt(resetHeader) * 1000 : null;
1497
+
1498
+ if (resetTime && i < maxRetries - 1) {
1499
+ const waitTime = Math.max(resetTime - Date.now(), 0);
1500
+ console.log(`Rate limited. Waiting ${waitTime}ms...`);
1501
+ await new Promise(resolve => setTimeout(resolve, waitTime));
1502
+ continue;
1503
+ }
1504
+ }
1505
+ throw err;
1506
+ }
1507
+ }
1508
+ }
1509
+
1510
+ // Usage
1511
+ await makeRequestWithBackoff(() =>
1512
+ client.contacts.create({ email: '[email protected]' })
1513
+ );
1514
+ ```
1515
+
1516
+ ## Bulk Operations
1517
+
1518
+ **Bulk create contacts:**
1519
+
1520
+ ```javascript
1521
+ const contacts = [
1522
+ { email: '[email protected]', name: 'User 1' },
1523
+ { email: '[email protected]', name: 'User 2' },
1524
+ { email: '[email protected]', name: 'User 3' },
1525
+ ];
1526
+
1527
+ const results = await Promise.all(
1528
+ contacts.map(data => client.contacts.create(data))
1529
+ );
1530
+
1531
+ console.log(`Created ${results.length} contacts`);
1532
+ ```
1533
+
1534
+ **Bulk update with error handling:**
1535
+
1536
+ ```javascript
1537
+ const updates = [
1538
+ { id: '1', name: 'Updated 1' },
1539
+ { id: '2', name: 'Updated 2' },
1540
+ { id: '3', name: 'Updated 3' },
1541
+ ];
1542
+
1543
+ const results = await Promise.allSettled(
1544
+ updates.map(data => client.contacts.update(data))
1545
+ );
1546
+
1547
+ const succeeded = results.filter(r => r.status === 'fulfilled').length;
1548
+ const failed = results.filter(r => r.status === 'rejected').length;
1549
+
1550
+ console.log(`Success: ${succeeded}, Failed: ${failed}`);
1551
+ ```
1552
+
1553
+ **Rate-limited bulk operations:**
1554
+
1555
+ ```javascript
1556
+ async function bulkOperationWithRateLimit(items, operation, requestsPerSecond = 5) {
1557
+ const results = [];
1558
+ const delay = 1000 / requestsPerSecond;
1559
+
1560
+ for (const item of items) {
1561
+ try {
1562
+ const result = await operation(item);
1563
+ results.push({ success: true, data: result });
1564
+ } catch (err) {
1565
+ results.push({ success: false, error: err });
1566
+ }
1567
+
1568
+ await new Promise(resolve => setTimeout(resolve, delay));
1569
+ }
1570
+
1571
+ return results;
1572
+ }
1573
+
1574
+ // Usage
1575
+ const contactData = [
1576
+ { email: '[email protected]', name: 'User 1' },
1577
+ { email: '[email protected]', name: 'User 2' },
1578
+ // ... more contacts
1579
+ ];
1580
+
1581
+ const results = await bulkOperationWithRateLimit(
1582
+ contactData,
1583
+ data => client.contacts.create(data),
1584
+ 5 // 5 requests per second
1585
+ );
1586
+ ```
1587
+
1588
+ ## Environment-Specific Configuration
1589
+
1590
+ **Development:**
1591
+
1592
+ ```javascript
1593
+ const client = new IntercomClient({
1594
+ token: process.env.INTERCOM_ACCESS_TOKEN,
1595
+ timeoutInSeconds: 30,
1596
+ maxRetries: 1,
1597
+ });
1598
+ ```
1599
+
1600
+ **Production:**
1601
+
1602
+ ```javascript
1603
+ const client = new IntercomClient({
1604
+ token: process.env.INTERCOM_ACCESS_TOKEN,
1605
+ timeoutInSeconds: 120,
1606
+ maxRetries: 3,
1607
+ });
1608
+ ```
1609
+
1610
+ **Testing with mock:**
1611
+
1612
+ ```javascript
1613
+ // For testing, you can inject a custom httpx client
1614
+ import { IntercomClient } from 'intercom-client';
1615
+
1616
+ const mockClient = new IntercomClient({
1617
+ token: 'test_token',
1618
+ // Use mock HTTP client for tests
1619
+ });
1620
+ ```
1621
+
1622
+ ## Complete Examples
1623
+
1624
+ **User onboarding workflow:**
1625
+
1626
+ ```javascript
1627
+ async function onboardUser(email, name, plan) {
1628
+ try {
1629
+ // Create contact
1630
+ const contact = await client.contacts.create({
1631
+ email,
1632
+ name,
1633
+ role: 'user',
1634
+ custom_attributes: {
1635
+ plan,
1636
+ signup_date: new Date().toISOString(),
1637
+ },
1638
+ });
1639
+
1640
+ // Track signup event
1641
+ await client.events.create({
1642
+ event_name: 'signed_up',
1643
+ created_at: Math.floor(Date.now() / 1000),
1644
+ user_id: contact.id,
1645
+ metadata: {
1646
+ plan,
1647
+ source: 'web',
1648
+ },
1649
+ });
1650
+
1651
+ // Tag as new user
1652
+ const newUserTag = await client.tags.create({
1653
+ name: 'New User',
1654
+ });
1655
+
1656
+ await client.contacts.tag({
1657
+ contactId: contact.id,
1658
+ id: newUserTag.id,
1659
+ });
1660
+
1661
+ // Send welcome message
1662
+ await client.messages.create({
1663
+ message_type: 'email',
1664
+ from: {
1665
+ type: 'admin',
1666
+ id: process.env.ADMIN_ID,
1667
+ },
1668
+ to: {
1669
+ type: 'user',
1670
+ id: contact.id,
1671
+ },
1672
+ subject: 'Welcome to our platform!',
1673
+ body: `Hi ${name}, thanks for signing up!`,
1674
+ });
1675
+
1676
+ console.log('User onboarded successfully:', contact.id);
1677
+ return contact;
1678
+ } catch (err) {
1679
+ console.error('Onboarding failed:', err);
1680
+ throw err;
1681
+ }
1682
+ }
1683
+ ```
1684
+
1685
+ **Customer support workflow:**
1686
+
1687
+ ```javascript
1688
+ async function handleSupportRequest(userId, subject, message) {
1689
+ try {
1690
+ // Create conversation
1691
+ const conversation = await client.conversations.create({
1692
+ from: {
1693
+ type: 'user',
1694
+ id: userId,
1695
+ },
1696
+ body: message,
1697
+ });
1698
+
1699
+ // Assign to team
1700
+ await client.conversations.assign({
1701
+ id: conversation.id,
1702
+ type: 'admin',
1703
+ admin_id: process.env.ADMIN_ID,
1704
+ assignee_id: process.env.SUPPORT_TEAM_ID,
1705
+ assignment_type: 'team',
1706
+ });
1707
+
1708
+ // Add priority tag if urgent
1709
+ if (subject.toLowerCase().includes('urgent')) {
1710
+ const urgentTag = await client.tags.create({
1711
+ name: 'Urgent',
1712
+ });
1713
+
1714
+ await client.conversations.attachTag({
1715
+ conversationId: conversation.id,
1716
+ id: urgentTag.id,
1717
+ adminId: process.env.ADMIN_ID,
1718
+ });
1719
+ }
1720
+
1721
+ // Track support event
1722
+ await client.events.create({
1723
+ event_name: 'support_request_created',
1724
+ created_at: Math.floor(Date.now() / 1000),
1725
+ user_id: userId,
1726
+ metadata: {
1727
+ conversation_id: conversation.id,
1728
+ subject,
1729
+ urgent: subject.toLowerCase().includes('urgent'),
1730
+ },
1731
+ });
1732
+
1733
+ return conversation;
1734
+ } catch (err) {
1735
+ console.error('Support request failed:', err);
1736
+ throw err;
1737
+ }
1738
+ }
1739
+ ```
1740
+
1741
+ **Company and contact management:**
1742
+
1743
+ ```javascript
1744
+ async function addContactToCompany(contactEmail, companyId) {
1745
+ try {
1746
+ // Find or create contact
1747
+ let contact;
1748
+ try {
1749
+ const searchResults = await client.contacts.search({
1750
+ query: {
1751
+ field: 'email',
1752
+ operator: '=',
1753
+ value: contactEmail,
1754
+ },
1755
+ });
1756
+ contact = searchResults.data[0];
1757
+ } catch (err) {
1758
+ contact = await client.contacts.create({
1759
+ email: contactEmail,
1760
+ role: 'user',
1761
+ });
1762
+ }
1763
+
1764
+ // Attach to company
1765
+ await client.contacts.update({
1766
+ id: contact.id,
1767
+ companies: [
1768
+ {
1769
+ company_id: companyId,
1770
+ },
1771
+ ],
1772
+ });
1773
+
1774
+ // Get company details
1775
+ const company = await client.companies.find({
1776
+ company_id: companyId,
1777
+ });
1778
+
1779
+ console.log(`Added ${contactEmail} to ${company.name}`);
1780
+
1781
+ return { contact, company };
1782
+ } catch (err) {
1783
+ console.error('Failed to add contact to company:', err);
1784
+ throw err;
1785
+ }
1786
+ }
1787
+ ```
1788
+
1789
+ **Analytics and reporting:**
1790
+
1791
+ ```javascript
1792
+ async function generateUserReport(userId) {
1793
+ try {
1794
+ // Get user details
1795
+ const contact = await client.contacts.find({ id: userId });
1796
+
1797
+ // Get user events
1798
+ const events = await client.events.list({
1799
+ type: 'user',
1800
+ user_id: userId,
1801
+ });
1802
+
1803
+ // Get conversations
1804
+ const conversations = await client.conversations.search({
1805
+ query: {
1806
+ field: 'contact_ids',
1807
+ operator: '=',
1808
+ value: userId,
1809
+ },
1810
+ });
1811
+
1812
+ // Get notes
1813
+ const notes = await client.contacts.listNotes({ id: userId });
1814
+
1815
+ const report = {
1816
+ contact: {
1817
+ email: contact.email,
1818
+ name: contact.name,
1819
+ created_at: contact.created_at,
1820
+ custom_attributes: contact.custom_attributes,
1821
+ },
1822
+ events: events.events.map(e => ({
1823
+ name: e.event_name,
1824
+ created_at: e.created_at,
1825
+ metadata: e.metadata,
1826
+ })),
1827
+ conversations: {
1828
+ total: conversations.total_count,
1829
+ open: conversations.conversations.filter(c => c.state === 'open').length,
1830
+ closed: conversations.conversations.filter(c => c.state === 'closed').length,
1831
+ },
1832
+ notes: notes.data.map(n => ({
1833
+ body: n.body,
1834
+ created_at: n.created_at,
1835
+ })),
1836
+ };
1837
+
1838
+ return report;
1839
+ } catch (err) {
1840
+ console.error('Report generation failed:', err);
1841
+ throw err;
1842
+ }
1843
+ }
1844
+ ```