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,2033 @@
1
+ ---
2
+ name: crm
3
+ description: "HubSpot Python SDK for managing CRM contacts, companies, deals, and marketing automation via the HubSpot API."
4
+ metadata:
5
+ languages: "python"
6
+ versions: "12.0.0"
7
+ updated-on: "2026-03-01"
8
+ source: maintainer
9
+ tags: "hubspot,crm,marketing,contacts,automation"
10
+ ---
11
+
12
+ # HubSpot Python SDK Coding Guidelines
13
+
14
+ You are a HubSpot API coding expert. Help me write code using the HubSpot API with the official Python SDK.
15
+
16
+ Official SDK documentation and code samples:
17
+ https://developers.hubspot.com/docs/api/overview
18
+
19
+ ## Golden Rule: Use the Correct and Current SDK
20
+
21
+ Always use the official HubSpot Python SDK (`hubspot-api-client`), which is the standard library for all HubSpot API interactions. Do not use deprecated or unofficial packages.
22
+
23
+ - **Library Name:** HubSpot Python SDK
24
+ - **PyPI Package:** `hubspot-api-client`
25
+ - **Current Version:** 12.0.0
26
+ - **Deprecated Packages:** `hubspot-python`, `hubspot3` (do not use these)
27
+
28
+ **Installation:**
29
+
30
+ - **Correct:** `pip install hubspot-api-client`
31
+ - **Incorrect:** `pip install hubspot-python` or `pip install hubspot3`
32
+
33
+ **APIs and Usage:**
34
+
35
+ - **Correct:** `from hubspot import HubSpot`
36
+ - **Correct:** `api_client = HubSpot(access_token=token)`
37
+ - **Correct:** `api_client.crm.contacts.basic_api.create(...)`
38
+ - **Incorrect:** `HubspotClient` or `HubspotAPI`
39
+ - **Incorrect:** Legacy v2 API endpoints
40
+ - **Incorrect:** Using `hapikey` (removed after v5.1.0)
41
+
42
+ ## Installation
43
+
44
+ Install the SDK via pip:
45
+
46
+ ```bash
47
+ pip install hubspot-api-client
48
+ ```
49
+
50
+ The SDK requires Python 3.9 or higher.
51
+
52
+ For development with additional dependencies:
53
+
54
+ ```bash
55
+ pip install hubspot-api-client[dev]
56
+ ```
57
+
58
+ ## Authentication
59
+
60
+ HubSpot API uses access tokens for authentication. There are three types of access tokens:
61
+
62
+ 1. **Private App Access Tokens** (recommended for server-side integrations)
63
+ 2. **OAuth Access Tokens** (for public apps and integrations)
64
+ 3. **Legacy API Keys** (deprecated, will be revoked November 19, 2025)
65
+
66
+ ### Environment Variable Configuration
67
+
68
+ Set your access token as an environment variable:
69
+
70
+ ```bash
71
+ # .env file
72
+ HUBSPOT_ACCESS_TOKEN=your_access_token_here
73
+ ```
74
+
75
+ **Creating a Private App:**
76
+
77
+ 1. Navigate to Settings > Integrations > Private Apps in your HubSpot account
78
+ 2. Click "Create private app"
79
+ 3. Configure the required scopes (permissions)
80
+ 4. Click "Create app" and copy the access token
81
+
82
+ ## Initialization
83
+
84
+ ### Basic Initialization
85
+
86
+ ```python
87
+ from hubspot import HubSpot
88
+ import os
89
+
90
+ # Initialize with access token from environment variable
91
+ api_client = HubSpot(access_token=os.getenv('HUBSPOT_ACCESS_TOKEN'))
92
+ ```
93
+
94
+ ### Initialization with OAuth
95
+
96
+ ```python
97
+ from hubspot import HubSpot
98
+
99
+ api_client = HubSpot(access_token='YOUR_OAUTH_ACCESS_TOKEN')
100
+
101
+ # Update token when refreshed
102
+ api_client.access_token = 'NEW_ACCESS_TOKEN'
103
+ ```
104
+
105
+ ### Alternative Initialization Methods
106
+
107
+ ```python
108
+ from hubspot import HubSpot
109
+
110
+ # Option 1: Set token during initialization
111
+ api_client = HubSpot(access_token='your_access_token')
112
+
113
+ # Option 2: Set token after initialization
114
+ api_client = HubSpot()
115
+ api_client.access_token = 'your_access_token'
116
+
117
+ # Option 3: Using Client.create method
118
+ import hubspot
119
+ api_client = hubspot.Client.create(access_token='your_access_token')
120
+ ```
121
+
122
+ ## CRM API - Contacts
123
+
124
+ ### Create a Contact
125
+
126
+ **Basic Example:**
127
+
128
+ ```python
129
+ from hubspot import HubSpot
130
+ from hubspot.crm.contacts import SimplePublicObjectInputForCreate, ApiException
131
+ import os
132
+
133
+ api_client = HubSpot(access_token=os.getenv('HUBSPOT_ACCESS_TOKEN'))
134
+
135
+ def create_contact():
136
+ properties = {
137
+ "email": "example@company.com",
138
+ "firstname": "John",
139
+ "lastname": "Doe",
140
+ "phone": "555-0100",
141
+ "company": "Example Company",
142
+ "website": "example.com"
143
+ }
144
+
145
+ simple_public_object_input_for_create = SimplePublicObjectInputForCreate(
146
+ properties=properties
147
+ )
148
+
149
+ try:
150
+ api_response = api_client.crm.contacts.basic_api.create(
151
+ simple_public_object_input_for_create=simple_public_object_input_for_create
152
+ )
153
+ print(f"Contact created with ID: {api_response.id}")
154
+ return api_response
155
+ except ApiException as e:
156
+ print(f"Exception when creating contact: {e}")
157
+
158
+ create_contact()
159
+ ```
160
+
161
+ **Advanced Example with Custom Properties:**
162
+
163
+ ```python
164
+ from hubspot.crm.contacts import SimplePublicObjectInputForCreate, ApiException
165
+
166
+ def create_contact_advanced():
167
+ properties = {
168
+ "email": "jane@example.com",
169
+ "firstname": "Jane",
170
+ "lastname": "Smith",
171
+ "phone": "555-0200",
172
+ "company": "Tech Corp",
173
+ "jobtitle": "Software Engineer",
174
+ "lifecyclestage": "lead",
175
+ "hs_lead_status": "NEW",
176
+ # Custom properties
177
+ "custom_field": "custom_value",
178
+ "industry": "Technology"
179
+ }
180
+
181
+ simple_public_object_input = SimplePublicObjectInputForCreate(properties=properties)
182
+
183
+ try:
184
+ api_response = api_client.crm.contacts.basic_api.create(
185
+ simple_public_object_input_for_create=simple_public_object_input
186
+ )
187
+ print(f"Contact created with ID: {api_response.id}")
188
+ print(f"Properties: {api_response.properties}")
189
+ return api_response
190
+ except ApiException as e:
191
+ if e.status == 409:
192
+ print("Contact with this email already exists")
193
+ else:
194
+ print(f"Exception when creating contact: {e}")
195
+
196
+ create_contact_advanced()
197
+ ```
198
+
199
+ ### Get a Contact
200
+
201
+ **By ID:**
202
+
203
+ ```python
204
+ from hubspot.crm.contacts import ApiException
205
+
206
+ def get_contact(contact_id):
207
+ properties = ["email", "firstname", "lastname", "phone", "company"]
208
+
209
+ try:
210
+ api_response = api_client.crm.contacts.basic_api.get_by_id(
211
+ contact_id=contact_id,
212
+ properties=properties
213
+ )
214
+ print(f"Contact: {api_response.properties}")
215
+ return api_response
216
+ except ApiException as e:
217
+ print(f"Exception when fetching contact: {e}")
218
+
219
+ get_contact("12345")
220
+ ```
221
+
222
+ **By Email:**
223
+
224
+ ```python
225
+ from hubspot.crm.contacts import PublicObjectSearchRequest, ApiException
226
+
227
+ def get_contact_by_email(email):
228
+ filter_obj = {
229
+ "propertyName": "email",
230
+ "operator": "EQ",
231
+ "value": email
232
+ }
233
+
234
+ filter_group = {
235
+ "filters": [filter_obj]
236
+ }
237
+
238
+ sort = {
239
+ "propertyName": "createdate",
240
+ "direction": "DESCENDING"
241
+ }
242
+
243
+ public_object_search_request = PublicObjectSearchRequest(
244
+ filter_groups=[filter_group],
245
+ sorts=[sort],
246
+ properties=["email", "firstname", "lastname"],
247
+ limit=1
248
+ )
249
+
250
+ try:
251
+ api_response = api_client.crm.contacts.search_api.do_search(
252
+ public_object_search_request=public_object_search_request
253
+ )
254
+
255
+ if api_response.total > 0:
256
+ return api_response.results[0]
257
+ return None
258
+ except ApiException as e:
259
+ print(f"Exception when searching contact: {e}")
260
+
261
+ get_contact_by_email("example@company.com")
262
+ ```
263
+
264
+ ### Update a Contact
265
+
266
+ ```python
267
+ from hubspot.crm.contacts import SimplePublicObjectInput, ApiException
268
+
269
+ def update_contact(contact_id):
270
+ properties = {
271
+ "firstname": "Updated Name",
272
+ "phone": "555-9999",
273
+ "lifecyclestage": "opportunity"
274
+ }
275
+
276
+ simple_public_object_input = SimplePublicObjectInput(properties=properties)
277
+
278
+ try:
279
+ api_response = api_client.crm.contacts.basic_api.update(
280
+ contact_id=contact_id,
281
+ simple_public_object_input=simple_public_object_input
282
+ )
283
+ print(f"Contact updated: {api_response.id}")
284
+ return api_response
285
+ except ApiException as e:
286
+ print(f"Exception when updating contact: {e}")
287
+
288
+ update_contact("12345")
289
+ ```
290
+
291
+ ### List Contacts
292
+
293
+ **Basic Pagination:**
294
+
295
+ ```python
296
+ from hubspot.crm.contacts import ApiException
297
+
298
+ def list_contacts():
299
+ limit = 10
300
+ properties = ["email", "firstname", "lastname", "company"]
301
+
302
+ try:
303
+ api_response = api_client.crm.contacts.basic_api.get_page(
304
+ limit=limit,
305
+ properties=properties
306
+ )
307
+
308
+ print(f"Found {len(api_response.results)} contacts")
309
+ for contact in api_response.results:
310
+ print(f"{contact.properties.get('firstname')} {contact.properties.get('lastname')}")
311
+
312
+ return api_response
313
+ except ApiException as e:
314
+ print(f"Exception when listing contacts: {e}")
315
+
316
+ list_contacts()
317
+ ```
318
+
319
+ **Get All Contacts (with pagination handling):**
320
+
321
+ ```python
322
+ from hubspot.crm.contacts import ApiException
323
+
324
+ def get_all_contacts():
325
+ all_contacts = []
326
+ after = None
327
+ limit = 100
328
+ properties = ["email", "firstname", "lastname"]
329
+
330
+ try:
331
+ while True:
332
+ api_response = api_client.crm.contacts.basic_api.get_page(
333
+ limit=limit,
334
+ after=after,
335
+ properties=properties
336
+ )
337
+
338
+ all_contacts.extend(api_response.results)
339
+
340
+ if api_response.paging and api_response.paging.next:
341
+ after = api_response.paging.next.after
342
+ else:
343
+ break
344
+
345
+ print(f"Total contacts retrieved: {len(all_contacts)}")
346
+ return all_contacts
347
+ except ApiException as e:
348
+ print(f"Exception when getting all contacts: {e}")
349
+
350
+ get_all_contacts()
351
+ ```
352
+
353
+ **Using get_all method:**
354
+
355
+ ```python
356
+ from hubspot.crm.contacts import ApiException
357
+
358
+ def get_all_contacts_simple():
359
+ try:
360
+ # The get_all method handles pagination automatically
361
+ all_contacts = api_client.crm.contacts.get_all()
362
+ print(f"Total contacts: {len(all_contacts)}")
363
+ return all_contacts
364
+ except ApiException as e:
365
+ print(f"Exception when getting all contacts: {e}")
366
+
367
+ get_all_contacts_simple()
368
+ ```
369
+
370
+ ### Delete a Contact
371
+
372
+ ```python
373
+ from hubspot.crm.contacts import ApiException
374
+
375
+ def delete_contact(contact_id):
376
+ try:
377
+ api_client.crm.contacts.basic_api.archive(contact_id=contact_id)
378
+ print(f"Contact deleted: {contact_id}")
379
+ except ApiException as e:
380
+ print(f"Exception when deleting contact: {e}")
381
+
382
+ delete_contact("12345")
383
+ ```
384
+
385
+ ## CRM API - Companies
386
+
387
+ ### Create a Company
388
+
389
+ ```python
390
+ from hubspot.crm.companies import SimplePublicObjectInputForCreate, ApiException
391
+
392
+ def create_company():
393
+ properties = {
394
+ "name": "Example Company",
395
+ "domain": "example.com",
396
+ "city": "San Francisco",
397
+ "state": "California",
398
+ "industry": "Technology",
399
+ "phone": "555-0100",
400
+ "numberofemployees": "50",
401
+ "description": "A technology company"
402
+ }
403
+
404
+ simple_public_object_input = SimplePublicObjectInputForCreate(properties=properties)
405
+
406
+ try:
407
+ api_response = api_client.crm.companies.basic_api.create(
408
+ simple_public_object_input_for_create=simple_public_object_input
409
+ )
410
+ print(f"Company created with ID: {api_response.id}")
411
+ return api_response
412
+ except ApiException as e:
413
+ print(f"Exception when creating company: {e}")
414
+
415
+ create_company()
416
+ ```
417
+
418
+ ### Get a Company
419
+
420
+ ```python
421
+ from hubspot.crm.companies import ApiException
422
+
423
+ def get_company(company_id):
424
+ properties = ["name", "domain", "city", "industry", "phone"]
425
+
426
+ try:
427
+ api_response = api_client.crm.companies.basic_api.get_by_id(
428
+ company_id=company_id,
429
+ properties=properties
430
+ )
431
+ print(f"Company: {api_response.properties}")
432
+ return api_response
433
+ except ApiException as e:
434
+ print(f"Exception when fetching company: {e}")
435
+
436
+ get_company("12345")
437
+ ```
438
+
439
+ ### Update a Company
440
+
441
+ ```python
442
+ from hubspot.crm.companies import SimplePublicObjectInput, ApiException
443
+
444
+ def update_company(company_id):
445
+ properties = {
446
+ "name": "Updated Company Name",
447
+ "numberofemployees": "100",
448
+ "annualrevenue": "1000000"
449
+ }
450
+
451
+ simple_public_object_input = SimplePublicObjectInput(properties=properties)
452
+
453
+ try:
454
+ api_response = api_client.crm.companies.basic_api.update(
455
+ company_id=company_id,
456
+ simple_public_object_input=simple_public_object_input
457
+ )
458
+ print(f"Company updated: {api_response.id}")
459
+ return api_response
460
+ except ApiException as e:
461
+ print(f"Exception when updating company: {e}")
462
+
463
+ update_company("12345")
464
+ ```
465
+
466
+ ### List Companies
467
+
468
+ ```python
469
+ from hubspot.crm.companies import ApiException
470
+
471
+ def list_companies():
472
+ limit = 10
473
+ properties = ["name", "domain", "city", "industry"]
474
+
475
+ try:
476
+ api_response = api_client.crm.companies.basic_api.get_page(
477
+ limit=limit,
478
+ properties=properties
479
+ )
480
+
481
+ print(f"Found {len(api_response.results)} companies")
482
+ return api_response
483
+ except ApiException as e:
484
+ print(f"Exception when listing companies: {e}")
485
+
486
+ list_companies()
487
+ ```
488
+
489
+ ## CRM API - Deals
490
+
491
+ ### Create a Deal
492
+
493
+ ```python
494
+ from hubspot.crm.deals import SimplePublicObjectInputForCreate, ApiException
495
+
496
+ def create_deal():
497
+ properties = {
498
+ "dealname": "New Deal",
499
+ "dealstage": "appointmentscheduled",
500
+ "amount": "10000",
501
+ "closedate": "2025-12-31",
502
+ "pipeline": "default",
503
+ "hubspot_owner_id": "12345"
504
+ }
505
+
506
+ simple_public_object_input = SimplePublicObjectInputForCreate(properties=properties)
507
+
508
+ try:
509
+ api_response = api_client.crm.deals.basic_api.create(
510
+ simple_public_object_input_for_create=simple_public_object_input
511
+ )
512
+ print(f"Deal created with ID: {api_response.id}")
513
+ return api_response
514
+ except ApiException as e:
515
+ print(f"Exception when creating deal: {e}")
516
+
517
+ create_deal()
518
+ ```
519
+
520
+ ### Get a Deal
521
+
522
+ ```python
523
+ from hubspot.crm.deals import ApiException
524
+
525
+ def get_deal(deal_id):
526
+ properties = ["dealname", "dealstage", "amount", "closedate"]
527
+
528
+ try:
529
+ api_response = api_client.crm.deals.basic_api.get_by_id(
530
+ deal_id=deal_id,
531
+ properties=properties
532
+ )
533
+ print(f"Deal: {api_response.properties}")
534
+ return api_response
535
+ except ApiException as e:
536
+ print(f"Exception when fetching deal: {e}")
537
+
538
+ get_deal("12345")
539
+ ```
540
+
541
+ ### Update a Deal
542
+
543
+ ```python
544
+ from hubspot.crm.deals import SimplePublicObjectInput, ApiException
545
+
546
+ def update_deal(deal_id):
547
+ properties = {
548
+ "dealstage": "closedwon",
549
+ "amount": "15000",
550
+ "closedate": "2025-11-30"
551
+ }
552
+
553
+ simple_public_object_input = SimplePublicObjectInput(properties=properties)
554
+
555
+ try:
556
+ api_response = api_client.crm.deals.basic_api.update(
557
+ deal_id=deal_id,
558
+ simple_public_object_input=simple_public_object_input
559
+ )
560
+ print(f"Deal updated: {api_response.id}")
561
+ return api_response
562
+ except ApiException as e:
563
+ print(f"Exception when updating deal: {e}")
564
+
565
+ update_deal("12345")
566
+ ```
567
+
568
+ ### List Deals
569
+
570
+ ```python
571
+ from hubspot.crm.deals import ApiException
572
+
573
+ def list_deals():
574
+ limit = 10
575
+ properties = ["dealname", "dealstage", "amount"]
576
+
577
+ try:
578
+ api_response = api_client.crm.deals.basic_api.get_page(
579
+ limit=limit,
580
+ properties=properties
581
+ )
582
+
583
+ print(f"Found {len(api_response.results)} deals")
584
+ return api_response
585
+ except ApiException as e:
586
+ print(f"Exception when listing deals: {e}")
587
+
588
+ list_deals()
589
+ ```
590
+
591
+ ## CRM API - Tickets
592
+
593
+ ### Create a Ticket
594
+
595
+ ```python
596
+ from hubspot.crm.tickets import SimplePublicObjectInputForCreate, ApiException
597
+
598
+ def create_ticket():
599
+ properties = {
600
+ "subject": "Customer Support Request",
601
+ "content": "Customer needs help with product setup",
602
+ "hs_pipeline": "0",
603
+ "hs_pipeline_stage": "1",
604
+ "hs_ticket_priority": "HIGH",
605
+ "hubspot_owner_id": "12345"
606
+ }
607
+
608
+ simple_public_object_input = SimplePublicObjectInputForCreate(properties=properties)
609
+
610
+ try:
611
+ api_response = api_client.crm.tickets.basic_api.create(
612
+ simple_public_object_input_for_create=simple_public_object_input
613
+ )
614
+ print(f"Ticket created with ID: {api_response.id}")
615
+ return api_response
616
+ except ApiException as e:
617
+ print(f"Exception when creating ticket: {e}")
618
+
619
+ create_ticket()
620
+ ```
621
+
622
+ ### Get a Ticket
623
+
624
+ ```python
625
+ from hubspot.crm.tickets import ApiException
626
+
627
+ def get_ticket(ticket_id):
628
+ properties = ["subject", "content", "hs_pipeline_stage", "hs_ticket_priority"]
629
+
630
+ try:
631
+ api_response = api_client.crm.tickets.basic_api.get_by_id(
632
+ ticket_id=ticket_id,
633
+ properties=properties
634
+ )
635
+ print(f"Ticket: {api_response.properties}")
636
+ return api_response
637
+ except ApiException as e:
638
+ print(f"Exception when fetching ticket: {e}")
639
+
640
+ get_ticket("12345")
641
+ ```
642
+
643
+ ### Update a Ticket
644
+
645
+ ```python
646
+ from hubspot.crm.tickets import SimplePublicObjectInput, ApiException
647
+
648
+ def update_ticket(ticket_id):
649
+ properties = {
650
+ "hs_pipeline_stage": "4", # Closed
651
+ "hs_ticket_priority": "LOW"
652
+ }
653
+
654
+ simple_public_object_input = SimplePublicObjectInput(properties=properties)
655
+
656
+ try:
657
+ api_response = api_client.crm.tickets.basic_api.update(
658
+ ticket_id=ticket_id,
659
+ simple_public_object_input=simple_public_object_input
660
+ )
661
+ print(f"Ticket updated: {api_response.id}")
662
+ return api_response
663
+ except ApiException as e:
664
+ print(f"Exception when updating ticket: {e}")
665
+
666
+ update_ticket("12345")
667
+ ```
668
+
669
+ ## CRM API - Associations
670
+
671
+ Associations link objects together (e.g., contacts to companies, deals to contacts).
672
+
673
+ ### Create Association
674
+
675
+ **Associate Contact with Company:**
676
+
677
+ ```python
678
+ from hubspot.crm.associations import ApiException
679
+
680
+ def associate_contact_with_company(contact_id, company_id):
681
+ try:
682
+ api_response = api_client.crm.contacts.associations_api.create(
683
+ contact_id=contact_id,
684
+ to_object_type="companies",
685
+ to_object_id=company_id,
686
+ association_type="contact_to_company"
687
+ )
688
+ print("Association created")
689
+ return api_response
690
+ except ApiException as e:
691
+ print(f"Exception when creating association: {e}")
692
+
693
+ associate_contact_with_company("12345", "67890")
694
+ ```
695
+
696
+ **Associate Deal with Contact:**
697
+
698
+ ```python
699
+ from hubspot.crm.associations import ApiException
700
+
701
+ def associate_deal_with_contact(deal_id, contact_id):
702
+ try:
703
+ api_response = api_client.crm.deals.associations_api.create(
704
+ deal_id=deal_id,
705
+ to_object_type="contacts",
706
+ to_object_id=contact_id,
707
+ association_type="deal_to_contact"
708
+ )
709
+ print("Association created")
710
+ return api_response
711
+ except ApiException as e:
712
+ print(f"Exception when creating association: {e}")
713
+
714
+ associate_deal_with_contact("12345", "67890")
715
+ ```
716
+
717
+ ### Get Associations
718
+
719
+ ```python
720
+ from hubspot.crm.associations import ApiException
721
+
722
+ def get_contact_associations(contact_id):
723
+ try:
724
+ # Get associated companies
725
+ companies = api_client.crm.contacts.associations_api.get_all(
726
+ contact_id=contact_id,
727
+ to_object_type="companies"
728
+ )
729
+
730
+ # Get associated deals
731
+ deals = api_client.crm.contacts.associations_api.get_all(
732
+ contact_id=contact_id,
733
+ to_object_type="deals"
734
+ )
735
+
736
+ print(f"Associated companies: {companies.results}")
737
+ print(f"Associated deals: {deals.results}")
738
+
739
+ return {"companies": companies, "deals": deals}
740
+ except ApiException as e:
741
+ print(f"Exception when fetching associations: {e}")
742
+
743
+ get_contact_associations("12345")
744
+ ```
745
+
746
+ ### Remove Association
747
+
748
+ ```python
749
+ from hubspot.crm.associations import ApiException
750
+
751
+ def remove_association(contact_id, company_id):
752
+ try:
753
+ api_client.crm.contacts.associations_api.archive(
754
+ contact_id=contact_id,
755
+ to_object_type="companies",
756
+ to_object_id=company_id,
757
+ association_type="contact_to_company"
758
+ )
759
+ print("Association removed")
760
+ except ApiException as e:
761
+ print(f"Exception when removing association: {e}")
762
+
763
+ remove_association("12345", "67890")
764
+ ```
765
+
766
+ ## CRM API - Batch Operations
767
+
768
+ Batch operations allow you to create, update, or read up to 100 records in a single API call.
769
+
770
+ ### Batch Create Contacts
771
+
772
+ ```python
773
+ from hubspot.crm.contacts import BatchInputSimplePublicObjectInputForCreate, SimplePublicObjectInputForCreate, ApiException
774
+
775
+ def batch_create_contacts():
776
+ inputs = [
777
+ SimplePublicObjectInputForCreate(
778
+ properties={
779
+ "email": "contact1@example.com",
780
+ "firstname": "Contact",
781
+ "lastname": "One"
782
+ }
783
+ ),
784
+ SimplePublicObjectInputForCreate(
785
+ properties={
786
+ "email": "contact2@example.com",
787
+ "firstname": "Contact",
788
+ "lastname": "Two"
789
+ }
790
+ ),
791
+ SimplePublicObjectInputForCreate(
792
+ properties={
793
+ "email": "contact3@example.com",
794
+ "firstname": "Contact",
795
+ "lastname": "Three"
796
+ }
797
+ )
798
+ ]
799
+
800
+ batch_input = BatchInputSimplePublicObjectInputForCreate(inputs=inputs)
801
+
802
+ try:
803
+ api_response = api_client.crm.contacts.batch_api.create(
804
+ batch_input_simple_public_object_input_for_create=batch_input
805
+ )
806
+ print(f"Created {len(api_response.results)} contacts")
807
+ return api_response
808
+ except ApiException as e:
809
+ print(f"Exception when batch creating contacts: {e}")
810
+
811
+ batch_create_contacts()
812
+ ```
813
+
814
+ ### Batch Update Contacts
815
+
816
+ ```python
817
+ from hubspot.crm.contacts import BatchInputSimplePublicObjectBatchInput, SimplePublicObjectBatchInput, ApiException
818
+
819
+ def batch_update_contacts(contact_ids):
820
+ inputs = []
821
+ for contact_id in contact_ids:
822
+ inputs.append(
823
+ SimplePublicObjectBatchInput(
824
+ id=contact_id,
825
+ properties={
826
+ "lifecyclestage": "customer",
827
+ "hs_lead_status": "CONNECTED"
828
+ }
829
+ )
830
+ )
831
+
832
+ batch_input = BatchInputSimplePublicObjectBatchInput(inputs=inputs)
833
+
834
+ try:
835
+ api_response = api_client.crm.contacts.batch_api.update(
836
+ batch_input_simple_public_object_batch_input=batch_input
837
+ )
838
+ print(f"Updated {len(api_response.results)} contacts")
839
+ return api_response
840
+ except ApiException as e:
841
+ print(f"Exception when batch updating contacts: {e}")
842
+
843
+ batch_update_contacts(["12345", "67890", "11111"])
844
+ ```
845
+
846
+ ### Batch Read Contacts
847
+
848
+ ```python
849
+ from hubspot.crm.contacts import BatchReadInputSimplePublicObjectId, SimplePublicObjectId, ApiException
850
+
851
+ def batch_read_contacts(contact_ids):
852
+ inputs = [SimplePublicObjectId(id=contact_id) for contact_id in contact_ids]
853
+
854
+ batch_input = BatchReadInputSimplePublicObjectId(
855
+ properties=["email", "firstname", "lastname", "phone"],
856
+ inputs=inputs
857
+ )
858
+
859
+ try:
860
+ api_response = api_client.crm.contacts.batch_api.read(
861
+ batch_read_input_simple_public_object_id=batch_input
862
+ )
863
+ print(f"Retrieved {len(api_response.results)} contacts")
864
+ return api_response
865
+ except ApiException as e:
866
+ print(f"Exception when batch reading contacts: {e}")
867
+
868
+ batch_read_contacts(["12345", "67890", "11111"])
869
+ ```
870
+
871
+ ### Batch Upsert Contacts
872
+
873
+ ```python
874
+ from hubspot.crm.contacts import BatchInputSimplePublicObjectInputForCreate, SimplePublicObjectInputForCreate, ApiException
875
+
876
+ def batch_upsert_contacts():
877
+ inputs = [
878
+ SimplePublicObjectInputForCreate(
879
+ properties={
880
+ "email": "existing@example.com",
881
+ "firstname": "Updated",
882
+ "lastname": "Name"
883
+ },
884
+ id_property="email"
885
+ ),
886
+ SimplePublicObjectInputForCreate(
887
+ properties={
888
+ "email": "new@example.com",
889
+ "firstname": "New",
890
+ "lastname": "Contact"
891
+ },
892
+ id_property="email"
893
+ )
894
+ ]
895
+
896
+ batch_input = BatchInputSimplePublicObjectInputForCreate(inputs=inputs)
897
+
898
+ try:
899
+ api_response = api_client.crm.contacts.batch_api.upsert(
900
+ batch_input_simple_public_object_input_for_create=batch_input
901
+ )
902
+ print(f"Upserted {len(api_response.results)} contacts")
903
+ return api_response
904
+ except ApiException as e:
905
+ print(f"Exception when batch upserting contacts: {e}")
906
+
907
+ batch_upsert_contacts()
908
+ ```
909
+
910
+ ## CRM API - Search
911
+
912
+ The Search API allows you to filter, sort, and search across CRM objects.
913
+
914
+ ### Basic Search
915
+
916
+ ```python
917
+ from hubspot.crm.contacts import PublicObjectSearchRequest, ApiException
918
+
919
+ def search_contacts():
920
+ filter_obj = {
921
+ "propertyName": "lifecyclestage",
922
+ "operator": "EQ",
923
+ "value": "lead"
924
+ }
925
+
926
+ filter_group = {
927
+ "filters": [filter_obj]
928
+ }
929
+
930
+ public_object_search_request = PublicObjectSearchRequest(
931
+ filter_groups=[filter_group],
932
+ properties=["email", "firstname", "lastname", "lifecyclestage"],
933
+ limit=10
934
+ )
935
+
936
+ try:
937
+ api_response = api_client.crm.contacts.search_api.do_search(
938
+ public_object_search_request=public_object_search_request
939
+ )
940
+ print(f"Found {api_response.total} contacts")
941
+ print(f"Returned {len(api_response.results)} results")
942
+ return api_response
943
+ except ApiException as e:
944
+ print(f"Exception when searching contacts: {e}")
945
+
946
+ search_contacts()
947
+ ```
948
+
949
+ ### Advanced Search with Multiple Filters
950
+
951
+ ```python
952
+ from hubspot.crm.contacts import PublicObjectSearchRequest, ApiException
953
+
954
+ def advanced_search_contacts():
955
+ filter_group = {
956
+ "filters": [
957
+ {
958
+ "propertyName": "lifecyclestage",
959
+ "operator": "EQ",
960
+ "value": "lead"
961
+ },
962
+ {
963
+ "propertyName": "createdate",
964
+ "operator": "GTE",
965
+ "value": "2025-01-01"
966
+ }
967
+ ]
968
+ }
969
+
970
+ sort = {
971
+ "propertyName": "createdate",
972
+ "direction": "DESCENDING"
973
+ }
974
+
975
+ public_object_search_request = PublicObjectSearchRequest(
976
+ filter_groups=[filter_group],
977
+ sorts=[sort],
978
+ properties=["email", "firstname", "lastname", "createdate", "lifecyclestage"],
979
+ limit=100,
980
+ after=0
981
+ )
982
+
983
+ try:
984
+ api_response = api_client.crm.contacts.search_api.do_search(
985
+ public_object_search_request=public_object_search_request
986
+ )
987
+ print(f"Found {api_response.total} matching contacts")
988
+ return api_response
989
+ except ApiException as e:
990
+ print(f"Exception when searching contacts: {e}")
991
+
992
+ advanced_search_contacts()
993
+ ```
994
+
995
+ ### Search with Association Filters
996
+
997
+ ```python
998
+ from hubspot.crm.contacts import PublicObjectSearchRequest, ApiException
999
+
1000
+ def search_contacts_by_company(company_id):
1001
+ filter_obj = {
1002
+ "propertyName": "associations.company",
1003
+ "operator": "EQ",
1004
+ "value": company_id
1005
+ }
1006
+
1007
+ filter_group = {
1008
+ "filters": [filter_obj]
1009
+ }
1010
+
1011
+ public_object_search_request = PublicObjectSearchRequest(
1012
+ filter_groups=[filter_group],
1013
+ properties=["email", "firstname", "lastname"],
1014
+ limit=100
1015
+ )
1016
+
1017
+ try:
1018
+ api_response = api_client.crm.contacts.search_api.do_search(
1019
+ public_object_search_request=public_object_search_request
1020
+ )
1021
+ print(f"Found {len(api_response.results)} contacts for company")
1022
+ return api_response
1023
+ except ApiException as e:
1024
+ print(f"Exception when searching contacts by company: {e}")
1025
+
1026
+ search_contacts_by_company("12345")
1027
+ ```
1028
+
1029
+ ### Search Operators
1030
+
1031
+ Available operators for search filters:
1032
+
1033
+ - `EQ` - Equal to
1034
+ - `NEQ` - Not equal to
1035
+ - `LT` - Less than
1036
+ - `LTE` - Less than or equal to
1037
+ - `GT` - Greater than
1038
+ - `GTE` - Greater than or equal to
1039
+ - `IN` - In list of values
1040
+ - `NOT_IN` - Not in list of values
1041
+ - `HAS_PROPERTY` - Has property value set
1042
+ - `NOT_HAS_PROPERTY` - Does not have property value set
1043
+ - `CONTAINS_TOKEN` - Contains token (for text)
1044
+ - `NOT_CONTAINS_TOKEN` - Does not contain token
1045
+
1046
+ ## CRM API - Properties
1047
+
1048
+ ### Get All Contact Properties
1049
+
1050
+ ```python
1051
+ from hubspot.crm.properties import ApiException
1052
+
1053
+ def get_all_contact_properties():
1054
+ try:
1055
+ api_response = api_client.crm.properties.core_api.get_all(
1056
+ object_type="contacts"
1057
+ )
1058
+ print(f"Found {len(api_response.results)} contact properties")
1059
+ return api_response
1060
+ except ApiException as e:
1061
+ print(f"Exception when fetching contact properties: {e}")
1062
+
1063
+ get_all_contact_properties()
1064
+ ```
1065
+
1066
+ ### Create Custom Property
1067
+
1068
+ ```python
1069
+ from hubspot.crm.properties import PropertyCreate, ApiException
1070
+
1071
+ def create_custom_property():
1072
+ property_create = PropertyCreate(
1073
+ name="favorite_color",
1074
+ label="Favorite Color",
1075
+ type="string",
1076
+ field_type="text",
1077
+ group_name="contactinformation",
1078
+ description="The contact's favorite color"
1079
+ )
1080
+
1081
+ try:
1082
+ api_response = api_client.crm.properties.core_api.create(
1083
+ object_type="contacts",
1084
+ property_create=property_create
1085
+ )
1086
+ print(f"Custom property created: {api_response.name}")
1087
+ return api_response
1088
+ except ApiException as e:
1089
+ print(f"Exception when creating custom property: {e}")
1090
+
1091
+ create_custom_property()
1092
+ ```
1093
+
1094
+ ### Create Dropdown Property
1095
+
1096
+ ```python
1097
+ from hubspot.crm.properties import PropertyCreate, OptionInput, ApiException
1098
+
1099
+ def create_dropdown_property():
1100
+ options = [
1101
+ OptionInput(label="Bronze", value="bronze", display_order=0),
1102
+ OptionInput(label="Silver", value="silver", display_order=1),
1103
+ OptionInput(label="Gold", value="gold", display_order=2),
1104
+ OptionInput(label="Platinum", value="platinum", display_order=3)
1105
+ ]
1106
+
1107
+ property_create = PropertyCreate(
1108
+ name="customer_tier",
1109
+ label="Customer Tier",
1110
+ type="enumeration",
1111
+ field_type="select",
1112
+ group_name="contactinformation",
1113
+ options=options
1114
+ )
1115
+
1116
+ try:
1117
+ api_response = api_client.crm.properties.core_api.create(
1118
+ object_type="contacts",
1119
+ property_create=property_create
1120
+ )
1121
+ print(f"Dropdown property created: {api_response.name}")
1122
+ return api_response
1123
+ except ApiException as e:
1124
+ print(f"Exception when creating dropdown property: {e}")
1125
+
1126
+ create_dropdown_property()
1127
+ ```
1128
+
1129
+ ### Update Property
1130
+
1131
+ ```python
1132
+ from hubspot.crm.properties import PropertyUpdate, ApiException
1133
+
1134
+ def update_property(property_name):
1135
+ property_update = PropertyUpdate(
1136
+ label="Updated Label",
1137
+ description="Updated description"
1138
+ )
1139
+
1140
+ try:
1141
+ api_response = api_client.crm.properties.core_api.update(
1142
+ object_type="contacts",
1143
+ property_name=property_name,
1144
+ property_update=property_update
1145
+ )
1146
+ print(f"Property updated: {api_response.name}")
1147
+ return api_response
1148
+ except ApiException as e:
1149
+ print(f"Exception when updating property: {e}")
1150
+
1151
+ update_property("favorite_color")
1152
+ ```
1153
+
1154
+ ## Marketing API - Emails
1155
+
1156
+ ### Get All Marketing Emails
1157
+
1158
+ ```python
1159
+ from hubspot.marketing.emails import ApiException
1160
+
1161
+ def get_marketing_emails():
1162
+ try:
1163
+ api_response = api_client.marketing.emails.emails_api.get_page()
1164
+ print(f"Found {len(api_response.results)} marketing emails")
1165
+ return api_response
1166
+ except ApiException as e:
1167
+ print(f"Exception when fetching marketing emails: {e}")
1168
+
1169
+ get_marketing_emails()
1170
+ ```
1171
+
1172
+ ### Get Email by ID
1173
+
1174
+ ```python
1175
+ from hubspot.marketing.emails import ApiException
1176
+
1177
+ def get_marketing_email(email_id):
1178
+ try:
1179
+ api_response = api_client.marketing.emails.emails_api.get_by_id(
1180
+ email_id=email_id
1181
+ )
1182
+ print(f"Email: {api_response.name}")
1183
+ return api_response
1184
+ except ApiException as e:
1185
+ print(f"Exception when fetching marketing email: {e}")
1186
+
1187
+ get_marketing_email("12345")
1188
+ ```
1189
+
1190
+ ## Marketing API - Forms
1191
+
1192
+ ### Get All Forms
1193
+
1194
+ ```python
1195
+ from hubspot.marketing.forms import ApiException
1196
+
1197
+ def get_all_forms():
1198
+ try:
1199
+ api_response = api_client.marketing.forms.forms_api.get_page()
1200
+ print(f"Found {len(api_response.results)} forms")
1201
+ return api_response
1202
+ except ApiException as e:
1203
+ print(f"Exception when fetching forms: {e}")
1204
+
1205
+ get_all_forms()
1206
+ ```
1207
+
1208
+ ### Get Form by ID
1209
+
1210
+ ```python
1211
+ from hubspot.marketing.forms import ApiException
1212
+
1213
+ def get_form(form_id):
1214
+ try:
1215
+ api_response = api_client.marketing.forms.forms_api.get_by_id(
1216
+ form_id=form_id
1217
+ )
1218
+ print(f"Form: {api_response.name}")
1219
+ return api_response
1220
+ except ApiException as e:
1221
+ print(f"Exception when fetching form: {e}")
1222
+
1223
+ get_form("12345")
1224
+ ```
1225
+
1226
+ ### Submit Form Data
1227
+
1228
+ ```python
1229
+ import requests
1230
+
1231
+ def submit_form_data(form_guid, portal_id):
1232
+ form_data = {
1233
+ "fields": [
1234
+ {
1235
+ "name": "email",
1236
+ "value": "test@example.com"
1237
+ },
1238
+ {
1239
+ "name": "firstname",
1240
+ "value": "John"
1241
+ },
1242
+ {
1243
+ "name": "lastname",
1244
+ "value": "Doe"
1245
+ }
1246
+ ],
1247
+ "context": {
1248
+ "pageUri": "https://example.com/contact",
1249
+ "pageName": "Contact Us"
1250
+ }
1251
+ }
1252
+
1253
+ try:
1254
+ response = requests.post(
1255
+ f"https://api.hsforms.com/submissions/v3/integration/submit/{portal_id}/{form_guid}",
1256
+ json=form_data
1257
+ )
1258
+ response.raise_for_status()
1259
+ print("Form submitted successfully")
1260
+ return response.json()
1261
+ except requests.exceptions.RequestException as e:
1262
+ print(f"Error submitting form: {e}")
1263
+
1264
+ submit_form_data("form-guid-here", "12345")
1265
+ ```
1266
+
1267
+ ## Events API - Timeline Events
1268
+
1269
+ ### Create Timeline Event
1270
+
1271
+ ```python
1272
+ import requests
1273
+ import os
1274
+
1275
+ def create_timeline_event(event_type_id, object_id):
1276
+ event_data = {
1277
+ "eventTypeId": event_type_id,
1278
+ "objectId": object_id,
1279
+ "extraData": {
1280
+ "eventTitle": "Purchase Completed",
1281
+ "eventDescription": "Customer completed a purchase of $99.99"
1282
+ },
1283
+ "timestamp": "2025-11-07T12:00:00Z"
1284
+ }
1285
+
1286
+ headers = {
1287
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}",
1288
+ "Content-Type": "application/json"
1289
+ }
1290
+
1291
+ try:
1292
+ response = requests.post(
1293
+ "https://api.hubapi.com/crm/v3/timeline/events",
1294
+ json=event_data,
1295
+ headers=headers
1296
+ )
1297
+ response.raise_for_status()
1298
+ print(f"Timeline event created: {response.json()['id']}")
1299
+ return response.json()
1300
+ except requests.exceptions.RequestException as e:
1301
+ print(f"Error creating timeline event: {e}")
1302
+
1303
+ create_timeline_event("event_type_id_here", "12345")
1304
+ ```
1305
+
1306
+ ## Automation API - Workflows
1307
+
1308
+ ### Get All Workflows
1309
+
1310
+ ```python
1311
+ import requests
1312
+ import os
1313
+
1314
+ def get_all_workflows():
1315
+ headers = {
1316
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}"
1317
+ }
1318
+
1319
+ try:
1320
+ response = requests.get(
1321
+ "https://api.hubapi.com/automation/v3/workflows",
1322
+ headers=headers
1323
+ )
1324
+ response.raise_for_status()
1325
+ workflows = response.json()['workflows']
1326
+ print(f"Found {len(workflows)} workflows")
1327
+ return workflows
1328
+ except requests.exceptions.RequestException as e:
1329
+ print(f"Error fetching workflows: {e}")
1330
+
1331
+ get_all_workflows()
1332
+ ```
1333
+
1334
+ ### Get Workflow by ID
1335
+
1336
+ ```python
1337
+ import requests
1338
+ import os
1339
+
1340
+ def get_workflow(workflow_id):
1341
+ headers = {
1342
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}"
1343
+ }
1344
+
1345
+ try:
1346
+ response = requests.get(
1347
+ f"https://api.hubapi.com/automation/v3/workflows/{workflow_id}",
1348
+ headers=headers
1349
+ )
1350
+ response.raise_for_status()
1351
+ workflow = response.json()
1352
+ print(f"Workflow: {workflow['name']}")
1353
+ return workflow
1354
+ except requests.exceptions.RequestException as e:
1355
+ print(f"Error fetching workflow: {e}")
1356
+
1357
+ get_workflow("12345")
1358
+ ```
1359
+
1360
+ ### Enroll Contact in Workflow
1361
+
1362
+ ```python
1363
+ import requests
1364
+ import os
1365
+
1366
+ def enroll_contact_in_workflow(workflow_id, contact_email):
1367
+ headers = {
1368
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}",
1369
+ "Content-Type": "application/json"
1370
+ }
1371
+
1372
+ try:
1373
+ response = requests.post(
1374
+ f"https://api.hubapi.com/automation/v2/workflows/{workflow_id}/enrollments/contacts/{contact_email}",
1375
+ headers=headers,
1376
+ json={}
1377
+ )
1378
+ response.raise_for_status()
1379
+ print("Contact enrolled in workflow")
1380
+ return response.json()
1381
+ except requests.exceptions.RequestException as e:
1382
+ print(f"Error enrolling contact in workflow: {e}")
1383
+
1384
+ enroll_contact_in_workflow("12345", "contact@example.com")
1385
+ ```
1386
+
1387
+ ## Webhooks API
1388
+
1389
+ ### Create Webhook Subscription
1390
+
1391
+ ```python
1392
+ from hubspot.webhooks import SubscriptionCreateRequest, ApiException
1393
+
1394
+ def create_webhook_subscription(app_id):
1395
+ subscription_create = SubscriptionCreateRequest(
1396
+ event_type="contact.creation",
1397
+ active=True
1398
+ )
1399
+
1400
+ try:
1401
+ api_response = api_client.webhooks.subscriptions_api.create(
1402
+ app_id=app_id,
1403
+ subscription_create_request=subscription_create
1404
+ )
1405
+ print(f"Webhook subscription created: {api_response.id}")
1406
+ return api_response
1407
+ except ApiException as e:
1408
+ print(f"Exception when creating webhook subscription: {e}")
1409
+
1410
+ create_webhook_subscription(12345)
1411
+ ```
1412
+
1413
+ ### Get All Webhook Subscriptions
1414
+
1415
+ ```python
1416
+ from hubspot.webhooks import ApiException
1417
+
1418
+ def get_webhook_subscriptions(app_id):
1419
+ try:
1420
+ api_response = api_client.webhooks.subscriptions_api.get_all(
1421
+ app_id=app_id
1422
+ )
1423
+ print(f"Found {len(api_response.results)} webhook subscriptions")
1424
+ return api_response
1425
+ except ApiException as e:
1426
+ print(f"Exception when fetching webhook subscriptions: {e}")
1427
+
1428
+ get_webhook_subscriptions(12345)
1429
+ ```
1430
+
1431
+ ### Delete Webhook Subscription
1432
+
1433
+ ```python
1434
+ from hubspot.webhooks import ApiException
1435
+
1436
+ def delete_webhook_subscription(app_id, subscription_id):
1437
+ try:
1438
+ api_client.webhooks.subscriptions_api.archive(
1439
+ subscription_id=subscription_id,
1440
+ app_id=app_id
1441
+ )
1442
+ print("Webhook subscription deleted")
1443
+ except ApiException as e:
1444
+ print(f"Exception when deleting webhook subscription: {e}")
1445
+
1446
+ delete_webhook_subscription(12345, 67890)
1447
+ ```
1448
+
1449
+ ## Lists API
1450
+
1451
+ ### Get All Lists
1452
+
1453
+ ```python
1454
+ import requests
1455
+ import os
1456
+
1457
+ def get_all_lists():
1458
+ headers = {
1459
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}"
1460
+ }
1461
+
1462
+ params = {
1463
+ "count": 100,
1464
+ "offset": 0
1465
+ }
1466
+
1467
+ try:
1468
+ response = requests.get(
1469
+ "https://api.hubapi.com/contacts/v1/lists",
1470
+ headers=headers,
1471
+ params=params
1472
+ )
1473
+ response.raise_for_status()
1474
+ lists = response.json()['lists']
1475
+ print(f"Found {len(lists)} lists")
1476
+ return lists
1477
+ except requests.exceptions.RequestException as e:
1478
+ print(f"Error fetching lists: {e}")
1479
+
1480
+ get_all_lists()
1481
+ ```
1482
+
1483
+ ### Add Contact to List
1484
+
1485
+ ```python
1486
+ import requests
1487
+ import os
1488
+
1489
+ def add_contact_to_list(list_id, contact_id):
1490
+ headers = {
1491
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}",
1492
+ "Content-Type": "application/json"
1493
+ }
1494
+
1495
+ data = {
1496
+ "vids": [contact_id]
1497
+ }
1498
+
1499
+ try:
1500
+ response = requests.post(
1501
+ f"https://api.hubapi.com/contacts/v1/lists/{list_id}/add",
1502
+ headers=headers,
1503
+ json=data
1504
+ )
1505
+ response.raise_for_status()
1506
+ print("Contact added to list")
1507
+ return response.json()
1508
+ except requests.exceptions.RequestException as e:
1509
+ print(f"Error adding contact to list: {e}")
1510
+
1511
+ add_contact_to_list(123, 456)
1512
+ ```
1513
+
1514
+ ### Remove Contact from List
1515
+
1516
+ ```python
1517
+ import requests
1518
+ import os
1519
+
1520
+ def remove_contact_from_list(list_id, contact_id):
1521
+ headers = {
1522
+ "Authorization": f"Bearer {os.getenv('HUBSPOT_ACCESS_TOKEN')}",
1523
+ "Content-Type": "application/json"
1524
+ }
1525
+
1526
+ data = {
1527
+ "vids": [contact_id]
1528
+ }
1529
+
1530
+ try:
1531
+ response = requests.post(
1532
+ f"https://api.hubapi.com/contacts/v1/lists/{list_id}/remove",
1533
+ headers=headers,
1534
+ json=data
1535
+ )
1536
+ response.raise_for_status()
1537
+ print("Contact removed from list")
1538
+ return response.json()
1539
+ except requests.exceptions.RequestException as e:
1540
+ print(f"Error removing contact from list: {e}")
1541
+
1542
+ remove_contact_from_list(123, 456)
1543
+ ```
1544
+
1545
+ ## Owners API
1546
+
1547
+ ### Get All Owners
1548
+
1549
+ ```python
1550
+ from hubspot.crm.owners import ApiException
1551
+
1552
+ def get_all_owners():
1553
+ try:
1554
+ api_response = api_client.crm.owners.owners_api.get_page()
1555
+ print(f"Found {len(api_response.results)} owners")
1556
+ return api_response
1557
+ except ApiException as e:
1558
+ print(f"Exception when fetching owners: {e}")
1559
+
1560
+ get_all_owners()
1561
+ ```
1562
+
1563
+ ### Get Owner by ID
1564
+
1565
+ ```python
1566
+ from hubspot.crm.owners import ApiException
1567
+
1568
+ def get_owner(owner_id):
1569
+ try:
1570
+ api_response = api_client.crm.owners.owners_api.get_by_id(
1571
+ owner_id=owner_id
1572
+ )
1573
+ print(f"Owner: {api_response.email}")
1574
+ return api_response
1575
+ except ApiException as e:
1576
+ print(f"Exception when fetching owner: {e}")
1577
+
1578
+ get_owner("12345")
1579
+ ```
1580
+
1581
+ ## Error Handling
1582
+
1583
+ ### Comprehensive Error Handling
1584
+
1585
+ ```python
1586
+ from hubspot.crm.contacts import ApiException
1587
+
1588
+ def handle_api_call():
1589
+ try:
1590
+ api_response = api_client.crm.contacts.basic_api.get_by_id(
1591
+ contact_id="12345"
1592
+ )
1593
+ return api_response
1594
+ except ApiException as e:
1595
+ if e.status == 401:
1596
+ print("Authentication failed - check your access token")
1597
+ elif e.status == 404:
1598
+ print("Resource not found")
1599
+ elif e.status == 409:
1600
+ print("Conflict - resource already exists")
1601
+ elif e.status == 429:
1602
+ print("Rate limit exceeded - wait before retrying")
1603
+ elif e.status >= 500:
1604
+ print("HubSpot server error - try again later")
1605
+ else:
1606
+ print(f"API error: {e}")
1607
+ raise
1608
+
1609
+ handle_api_call()
1610
+ ```
1611
+
1612
+ ### Retry Logic
1613
+
1614
+ ```python
1615
+ import time
1616
+ from hubspot.crm.contacts import ApiException
1617
+
1618
+ def api_call_with_retry(api_call, max_retries=3):
1619
+ for attempt in range(1, max_retries + 1):
1620
+ try:
1621
+ return api_call()
1622
+ except ApiException as e:
1623
+ if e.status == 429 and attempt < max_retries:
1624
+ retry_after = int(e.headers.get('Retry-After', 1))
1625
+ print(f"Rate limited. Retrying after {retry_after} seconds...")
1626
+ time.sleep(retry_after)
1627
+ else:
1628
+ raise
1629
+
1630
+ # Usage
1631
+ result = api_call_with_retry(
1632
+ lambda: api_client.crm.contacts.basic_api.get_by_id(contact_id="12345")
1633
+ )
1634
+ ```
1635
+
1636
+ ## Rate Limits
1637
+
1638
+ HubSpot API has the following rate limits:
1639
+
1640
+ - **Private Apps:** 100 requests per 10 seconds per account
1641
+ - **OAuth Apps:** 100 requests per 10 seconds per app per account
1642
+ - **Search API:** 5 requests per second, 1000 requests per day (per account)
1643
+ - **Batch API:** 100 objects per request, same rate limits as standard endpoints
1644
+
1645
+ Monitor rate limit headers in responses:
1646
+
1647
+ ```python
1648
+ from hubspot.crm.contacts import ApiException
1649
+
1650
+ def check_rate_limits():
1651
+ try:
1652
+ api_response = api_client.crm.contacts.basic_api.get_page(limit=1)
1653
+
1654
+ # Rate limit information is in the response headers
1655
+ # These are typically accessed via the underlying HTTP client
1656
+ print("Request successful")
1657
+ return api_response
1658
+ except ApiException as e:
1659
+ if e.status == 429:
1660
+ print("Rate limit exceeded")
1661
+ print(f"Retry after: {e.headers.get('Retry-After')} seconds")
1662
+
1663
+ check_rate_limits()
1664
+ ```
1665
+
1666
+ ## Pagination
1667
+
1668
+ Most list endpoints return paginated results. Use the `after` parameter for pagination:
1669
+
1670
+ ```python
1671
+ from hubspot.crm.contacts import ApiException
1672
+
1673
+ def paginate_through_contacts():
1674
+ after = None
1675
+ all_contacts = []
1676
+
1677
+ while True:
1678
+ try:
1679
+ api_response = api_client.crm.contacts.basic_api.get_page(
1680
+ limit=100,
1681
+ after=after,
1682
+ properties=["email", "firstname", "lastname"]
1683
+ )
1684
+
1685
+ all_contacts.extend(api_response.results)
1686
+
1687
+ if api_response.paging and api_response.paging.next:
1688
+ after = api_response.paging.next.after
1689
+ else:
1690
+ break
1691
+ except ApiException as e:
1692
+ print(f"Exception during pagination: {e}")
1693
+ break
1694
+
1695
+ return all_contacts
1696
+
1697
+ all_contacts = paginate_through_contacts()
1698
+ print(f"Total contacts: {len(all_contacts)}")
1699
+ ```
1700
+
1701
+ ## OAuth Implementation
1702
+
1703
+ ### Initialize OAuth Provider
1704
+
1705
+ ```python
1706
+ from hubspot import HubSpot
1707
+ import os
1708
+
1709
+ api_client = HubSpot(
1710
+ access_token=None, # Will be set after OAuth flow
1711
+ client_id=os.getenv('HUBSPOT_CLIENT_ID'),
1712
+ client_secret=os.getenv('HUBSPOT_CLIENT_SECRET'),
1713
+ redirect_uri='https://yourapp.com/oauth-callback'
1714
+ )
1715
+ ```
1716
+
1717
+ ### Get Authorization URL
1718
+
1719
+ ```python
1720
+ import os
1721
+
1722
+ def get_authorization_url():
1723
+ scopes = ['contacts', 'crm.objects.contacts.read']
1724
+
1725
+ auth_url = (
1726
+ f"https://app.hubspot.com/oauth/authorize"
1727
+ f"?client_id={os.getenv('HUBSPOT_CLIENT_ID')}"
1728
+ f"&redirect_uri={os.getenv('REDIRECT_URI')}"
1729
+ f"&scope={' '.join(scopes)}"
1730
+ )
1731
+
1732
+ return auth_url
1733
+
1734
+ print(get_authorization_url())
1735
+ ```
1736
+
1737
+ ### Exchange Authorization Code for Tokens
1738
+
1739
+ ```python
1740
+ from hubspot.auth.oauth import ApiException
1741
+
1742
+ def get_tokens(authorization_code):
1743
+ try:
1744
+ token_response = api_client.auth.oauth.tokens_api.create(
1745
+ grant_type='authorization_code',
1746
+ code=authorization_code,
1747
+ redirect_uri=os.getenv('REDIRECT_URI'),
1748
+ client_id=os.getenv('HUBSPOT_CLIENT_ID'),
1749
+ client_secret=os.getenv('HUBSPOT_CLIENT_SECRET')
1750
+ )
1751
+
1752
+ return {
1753
+ "access_token": token_response.access_token,
1754
+ "refresh_token": token_response.refresh_token,
1755
+ "expires_in": token_response.expires_in
1756
+ }
1757
+ except ApiException as e:
1758
+ print(f"Error exchanging code for tokens: {e}")
1759
+
1760
+ tokens = get_tokens("authorization_code_here")
1761
+ ```
1762
+
1763
+ ### Refresh Access Token
1764
+
1765
+ ```python
1766
+ from hubspot.auth.oauth import ApiException
1767
+ import os
1768
+
1769
+ def refresh_access_token(refresh_token):
1770
+ try:
1771
+ token_response = api_client.auth.oauth.tokens_api.create(
1772
+ grant_type='refresh_token',
1773
+ redirect_uri=None,
1774
+ refresh_token=refresh_token,
1775
+ client_id=os.getenv('HUBSPOT_CLIENT_ID'),
1776
+ client_secret=os.getenv('HUBSPOT_CLIENT_SECRET')
1777
+ )
1778
+
1779
+ return {
1780
+ "access_token": token_response.access_token,
1781
+ "refresh_token": token_response.refresh_token,
1782
+ "expires_in": token_response.expires_in
1783
+ }
1784
+ except ApiException as e:
1785
+ print(f"Error refreshing token: {e}")
1786
+
1787
+ new_tokens = refresh_access_token("refresh_token_here")
1788
+ ```
1789
+
1790
+ ## Custom Objects
1791
+
1792
+ ### Create Custom Object Schema
1793
+
1794
+ ```python
1795
+ from hubspot.crm.schemas import ObjectSchemaEgg, ObjectTypePropertyCreate, ApiException
1796
+
1797
+ def create_custom_object_schema():
1798
+ properties = [
1799
+ ObjectTypePropertyCreate(
1800
+ name="model",
1801
+ label="Model",
1802
+ type="string",
1803
+ field_type="text"
1804
+ ),
1805
+ ObjectTypePropertyCreate(
1806
+ name="make",
1807
+ label="Make",
1808
+ type="string",
1809
+ field_type="text"
1810
+ ),
1811
+ ObjectTypePropertyCreate(
1812
+ name="year",
1813
+ label="Year",
1814
+ type="number",
1815
+ field_type="number"
1816
+ )
1817
+ ]
1818
+
1819
+ schema_egg = ObjectSchemaEgg(
1820
+ name="cars",
1821
+ labels={
1822
+ "singular": "Car",
1823
+ "plural": "Cars"
1824
+ },
1825
+ primary_display_property="model",
1826
+ required_properties=["model", "make"],
1827
+ searchable_properties=["model", "make", "year"],
1828
+ properties=properties
1829
+ )
1830
+
1831
+ try:
1832
+ api_response = api_client.crm.schemas.core_api.create(
1833
+ object_schema_egg=schema_egg
1834
+ )
1835
+ print(f"Custom object schema created: {api_response.name}")
1836
+ return api_response
1837
+ except ApiException as e:
1838
+ print(f"Exception when creating custom object schema: {e}")
1839
+
1840
+ create_custom_object_schema()
1841
+ ```
1842
+
1843
+ ### Create Custom Object Instance
1844
+
1845
+ ```python
1846
+ from hubspot.crm.objects import SimplePublicObjectInputForCreate, ApiException
1847
+
1848
+ def create_custom_object(object_type):
1849
+ object_data = SimplePublicObjectInputForCreate(
1850
+ properties={
1851
+ "model": "Model 3",
1852
+ "make": "Tesla",
1853
+ "year": "2024"
1854
+ }
1855
+ )
1856
+
1857
+ try:
1858
+ api_response = api_client.crm.objects.basic_api.create(
1859
+ object_type=object_type,
1860
+ simple_public_object_input_for_create=object_data
1861
+ )
1862
+ print(f"Custom object created: {api_response.id}")
1863
+ return api_response
1864
+ except ApiException as e:
1865
+ print(f"Exception when creating custom object: {e}")
1866
+
1867
+ create_custom_object("cars")
1868
+ ```
1869
+
1870
+ ## Complete Example Application
1871
+
1872
+ Here's a complete example that demonstrates multiple API operations:
1873
+
1874
+ ```python
1875
+ from hubspot import HubSpot
1876
+ from hubspot.crm.contacts import SimplePublicObjectInputForCreate, PublicObjectSearchRequest
1877
+ from hubspot.crm.companies import SimplePublicObjectInputForCreate as CompanyInput
1878
+ from hubspot.crm.deals import SimplePublicObjectInputForCreate as DealInput
1879
+ from hubspot.crm.contacts import ApiException
1880
+ import os
1881
+ from dotenv import load_dotenv
1882
+
1883
+ load_dotenv()
1884
+
1885
+ api_client = HubSpot(access_token=os.getenv('HUBSPOT_ACCESS_TOKEN'))
1886
+
1887
+ def main():
1888
+ try:
1889
+ # Create a contact
1890
+ print("Creating contact...")
1891
+ new_contact = api_client.crm.contacts.basic_api.create(
1892
+ simple_public_object_input_for_create=SimplePublicObjectInputForCreate(
1893
+ properties={
1894
+ "email": "john.doe@example.com",
1895
+ "firstname": "John",
1896
+ "lastname": "Doe",
1897
+ "phone": "555-0100",
1898
+ "company": "Example Corp"
1899
+ }
1900
+ )
1901
+ )
1902
+ print(f"Contact created with ID: {new_contact.id}")
1903
+
1904
+ # Create a company
1905
+ print("\nCreating company...")
1906
+ new_company = api_client.crm.companies.basic_api.create(
1907
+ simple_public_object_input_for_create=CompanyInput(
1908
+ properties={
1909
+ "name": "Example Corp",
1910
+ "domain": "example.com",
1911
+ "city": "San Francisco",
1912
+ "industry": "Technology"
1913
+ }
1914
+ )
1915
+ )
1916
+ print(f"Company created with ID: {new_company.id}")
1917
+
1918
+ # Associate contact with company
1919
+ print("\nAssociating contact with company...")
1920
+ api_client.crm.contacts.associations_api.create(
1921
+ contact_id=new_contact.id,
1922
+ to_object_type="companies",
1923
+ to_object_id=new_company.id,
1924
+ association_type="contact_to_company"
1925
+ )
1926
+ print("Association created successfully")
1927
+
1928
+ # Create a deal
1929
+ print("\nCreating deal...")
1930
+ new_deal = api_client.crm.deals.basic_api.create(
1931
+ simple_public_object_input_for_create=DealInput(
1932
+ properties={
1933
+ "dealname": "Example Deal",
1934
+ "dealstage": "appointmentscheduled",
1935
+ "amount": "10000",
1936
+ "closedate": "2025-12-31"
1937
+ }
1938
+ )
1939
+ )
1940
+ print(f"Deal created with ID: {new_deal.id}")
1941
+
1942
+ # Associate deal with contact
1943
+ print("\nAssociating deal with contact...")
1944
+ api_client.crm.deals.associations_api.create(
1945
+ deal_id=new_deal.id,
1946
+ to_object_type="contacts",
1947
+ to_object_id=new_contact.id,
1948
+ association_type="deal_to_contact"
1949
+ )
1950
+ print("Deal associated with contact")
1951
+
1952
+ # Search for contacts
1953
+ print("\nSearching for leads...")
1954
+ search_results = api_client.crm.contacts.search_api.do_search(
1955
+ public_object_search_request=PublicObjectSearchRequest(
1956
+ filter_groups=[
1957
+ {
1958
+ "filters": [
1959
+ {
1960
+ "propertyName": "email",
1961
+ "operator": "CONTAINS_TOKEN",
1962
+ "value": "example.com"
1963
+ }
1964
+ ]
1965
+ }
1966
+ ],
1967
+ properties=["email", "firstname", "lastname", "company"],
1968
+ limit=10
1969
+ )
1970
+ )
1971
+ print(f"Found {search_results.total} contacts")
1972
+
1973
+ # List all owners
1974
+ print("\nFetching owners...")
1975
+ owners = api_client.crm.owners.owners_api.get_page()
1976
+ print(f"Found {len(owners.results)} owners")
1977
+
1978
+ print("\nAll operations completed successfully!")
1979
+
1980
+ except ApiException as e:
1981
+ print(f"Error: {e}")
1982
+
1983
+ if __name__ == "__main__":
1984
+ main()
1985
+ ```
1986
+
1987
+ ## Environment Variables Template
1988
+
1989
+ ```bash
1990
+ # .env file
1991
+ HUBSPOT_ACCESS_TOKEN=your_private_app_access_token
1992
+ HUBSPOT_CLIENT_ID=your_client_id
1993
+ HUBSPOT_CLIENT_SECRET=your_client_secret
1994
+ REDIRECT_URI=https://yourapp.com/oauth-callback
1995
+ ```
1996
+
1997
+ ## API Scopes
1998
+
1999
+ When creating a private app or OAuth app, configure the following scopes based on your needs:
2000
+
2001
+ **CRM:**
2002
+ - `crm.objects.contacts.read` / `crm.objects.contacts.write`
2003
+ - `crm.objects.companies.read` / `crm.objects.companies.write`
2004
+ - `crm.objects.deals.read` / `crm.objects.deals.write`
2005
+ - `crm.objects.owners.read`
2006
+ - `crm.schemas.contacts.read` / `crm.schemas.contacts.write`
2007
+
2008
+ **Marketing:**
2009
+ - `forms` - Read and write forms
2010
+ - `content` - Read and write marketing emails
2011
+
2012
+ **Automation:**
2013
+ - `automation` - Access to workflows
2014
+
2015
+ **Timeline:**
2016
+ - `timeline` - Create timeline events
2017
+
2018
+ ## Migration from Legacy API Keys
2019
+
2020
+ If you're using legacy API keys (deprecated), migrate to private apps:
2021
+
2022
+ **Old (Deprecated):**
2023
+ ```python
2024
+ # DON'T USE THIS - hapikey is no longer supported
2025
+ api_client = HubSpot(api_key='your-api-key') # Removed after v5.1.0
2026
+ ```
2027
+
2028
+ **New (Correct):**
2029
+ ```python
2030
+ api_client = HubSpot(access_token=os.getenv('HUBSPOT_ACCESS_TOKEN'))
2031
+ ```
2032
+
2033
+ Legacy API keys will be revoked on November 19, 2025.