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