universal-mcp-applications 0.1.30rc1__py3-none-any.whl → 0.1.36rc1__py3-none-any.whl

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.

Potentially problematic release.


This version of universal-mcp-applications might be problematic. Click here for more details.

Files changed (106) hide show
  1. universal_mcp/applications/ahrefs/app.py +52 -198
  2. universal_mcp/applications/airtable/app.py +23 -122
  3. universal_mcp/applications/apollo/app.py +111 -464
  4. universal_mcp/applications/asana/app.py +417 -1567
  5. universal_mcp/applications/aws_s3/app.py +33 -100
  6. universal_mcp/applications/bill/app.py +546 -1957
  7. universal_mcp/applications/box/app.py +1068 -3981
  8. universal_mcp/applications/braze/app.py +364 -1430
  9. universal_mcp/applications/browser_use/app.py +2 -8
  10. universal_mcp/applications/cal_com_v2/app.py +207 -625
  11. universal_mcp/applications/calendly/app.py +61 -200
  12. universal_mcp/applications/canva/app.py +45 -110
  13. universal_mcp/applications/clickup/app.py +207 -674
  14. universal_mcp/applications/coda/app.py +146 -426
  15. universal_mcp/applications/confluence/app.py +310 -1098
  16. universal_mcp/applications/contentful/app.py +36 -151
  17. universal_mcp/applications/crustdata/app.py +28 -107
  18. universal_mcp/applications/dialpad/app.py +283 -756
  19. universal_mcp/applications/digitalocean/app.py +1766 -5777
  20. universal_mcp/applications/domain_checker/app.py +3 -54
  21. universal_mcp/applications/e2b/app.py +14 -64
  22. universal_mcp/applications/elevenlabs/app.py +9 -47
  23. universal_mcp/applications/exa/app.py +6 -17
  24. universal_mcp/applications/falai/app.py +23 -100
  25. universal_mcp/applications/figma/app.py +53 -137
  26. universal_mcp/applications/file_system/app.py +2 -13
  27. universal_mcp/applications/firecrawl/app.py +51 -152
  28. universal_mcp/applications/fireflies/app.py +59 -281
  29. universal_mcp/applications/fpl/app.py +91 -528
  30. universal_mcp/applications/fpl/utils/fixtures.py +15 -49
  31. universal_mcp/applications/fpl/utils/helper.py +25 -89
  32. universal_mcp/applications/fpl/utils/league_utils.py +20 -64
  33. universal_mcp/applications/ghost_content/app.py +52 -161
  34. universal_mcp/applications/github/app.py +19 -56
  35. universal_mcp/applications/gong/app.py +88 -248
  36. universal_mcp/applications/google_calendar/app.py +16 -68
  37. universal_mcp/applications/google_docs/app.py +88 -188
  38. universal_mcp/applications/google_drive/app.py +140 -462
  39. universal_mcp/applications/google_gemini/app.py +12 -64
  40. universal_mcp/applications/google_mail/app.py +28 -157
  41. universal_mcp/applications/google_searchconsole/app.py +15 -48
  42. universal_mcp/applications/google_sheet/app.py +101 -578
  43. universal_mcp/applications/google_sheet/helper.py +10 -37
  44. universal_mcp/applications/hashnode/app.py +57 -269
  45. universal_mcp/applications/heygen/app.py +44 -122
  46. universal_mcp/applications/http_tools/app.py +10 -32
  47. universal_mcp/applications/hubspot/api_segments/crm_api.py +460 -1573
  48. universal_mcp/applications/hubspot/api_segments/marketing_api.py +74 -262
  49. universal_mcp/applications/hubspot/app.py +23 -87
  50. universal_mcp/applications/jira/app.py +2071 -7986
  51. universal_mcp/applications/klaviyo/app.py +494 -1376
  52. universal_mcp/applications/linkedin/README.md +23 -4
  53. universal_mcp/applications/linkedin/app.py +392 -212
  54. universal_mcp/applications/mailchimp/app.py +450 -1605
  55. universal_mcp/applications/markitdown/app.py +8 -20
  56. universal_mcp/applications/miro/app.py +217 -699
  57. universal_mcp/applications/ms_teams/app.py +64 -186
  58. universal_mcp/applications/neon/app.py +86 -192
  59. universal_mcp/applications/notion/app.py +21 -36
  60. universal_mcp/applications/onedrive/app.py +14 -36
  61. universal_mcp/applications/openai/app.py +42 -165
  62. universal_mcp/applications/outlook/app.py +16 -76
  63. universal_mcp/applications/perplexity/app.py +4 -19
  64. universal_mcp/applications/pipedrive/app.py +832 -3142
  65. universal_mcp/applications/posthog/app.py +163 -432
  66. universal_mcp/applications/reddit/app.py +40 -139
  67. universal_mcp/applications/resend/app.py +41 -107
  68. universal_mcp/applications/retell/app.py +14 -41
  69. universal_mcp/applications/rocketlane/app.py +221 -934
  70. universal_mcp/applications/scraper/README.md +7 -4
  71. universal_mcp/applications/scraper/app.py +280 -93
  72. universal_mcp/applications/semanticscholar/app.py +22 -64
  73. universal_mcp/applications/semrush/app.py +43 -77
  74. universal_mcp/applications/sendgrid/app.py +512 -1262
  75. universal_mcp/applications/sentry/app.py +271 -906
  76. universal_mcp/applications/serpapi/app.py +40 -143
  77. universal_mcp/applications/sharepoint/app.py +15 -37
  78. universal_mcp/applications/shopify/app.py +1551 -4287
  79. universal_mcp/applications/shortcut/app.py +155 -417
  80. universal_mcp/applications/slack/app.py +50 -101
  81. universal_mcp/applications/spotify/app.py +126 -325
  82. universal_mcp/applications/supabase/app.py +104 -213
  83. universal_mcp/applications/tavily/app.py +1 -1
  84. universal_mcp/applications/trello/app.py +693 -2656
  85. universal_mcp/applications/twilio/app.py +14 -50
  86. universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
  87. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
  88. universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
  89. universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
  90. universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
  91. universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
  92. universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
  93. universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
  94. universal_mcp/applications/whatsapp/app.py +35 -186
  95. universal_mcp/applications/whatsapp/audio.py +2 -6
  96. universal_mcp/applications/whatsapp/whatsapp.py +17 -51
  97. universal_mcp/applications/whatsapp_business/app.py +70 -283
  98. universal_mcp/applications/wrike/app.py +45 -118
  99. universal_mcp/applications/yahoo_finance/app.py +19 -65
  100. universal_mcp/applications/youtube/app.py +75 -261
  101. universal_mcp/applications/zenquotes/app.py +2 -2
  102. {universal_mcp_applications-0.1.30rc1.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/METADATA +2 -2
  103. {universal_mcp_applications-0.1.30rc1.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/RECORD +105 -106
  104. universal_mcp/applications/scraper/scraper_testers.py +0 -17
  105. {universal_mcp_applications-0.1.30rc1.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/WHEEL +0 -0
  106. {universal_mcp_applications-0.1.30rc1.dist-info → universal_mcp_applications-0.1.36rc1.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,4 @@
1
1
  from typing import Any
2
-
3
2
  from loguru import logger
4
3
  from universal_mcp.applications.application import APIApplication
5
4
  from universal_mcp.integrations import Integration
@@ -16,41 +15,17 @@ class ApolloApp(APIApplication):
16
15
  Overrides the base class method to use X-Api-Key.
17
16
  """
18
17
  if not self.integration:
19
- logger.warning(
20
- "ApolloApp: No integration configured, returning empty headers."
21
- )
18
+ logger.warning("ApolloApp: No integration configured, returning empty headers.")
22
19
  return {}
23
-
24
- # ApiKeyIntegration's get_credentials() returns a dict like:
25
- # {'api_key': 'your_actual_key_value'}
26
20
  credentials = self.integration.get_credentials()
27
-
28
- # The key in the credentials dict from ApiKeyIntegration is 'api_key'
29
- api_key = (
30
- credentials.get("api_key")
31
- or credentials.get("API_KEY")
32
- or credentials.get("apiKey")
33
- )
34
-
21
+ api_key = credentials.get("api_key") or credentials.get("API_KEY") or credentials.get("apiKey")
35
22
  if not api_key:
36
- logger.error(
37
- "ApolloApp: API key not found in integration credentials for Apollo."
38
- )
39
- # You might want to raise an error here if an API key is absolutely required
40
- # For example: raise ValueError("API key is missing for Apollo integration.")
41
- return { # Or return minimal headers if some calls might not need auth (unlikely for Apollo)
42
- "Content-Type": "application/json",
43
- "Cache-Control": "no-cache",
44
- }
45
-
23
+ logger.error("ApolloApp: API key not found in integration credentials for Apollo.")
24
+ return {"Content-Type": "application/json", "Cache-Control": "no-cache"}
46
25
  logger.debug("ApolloApp: Using X-Api-Key for authentication.")
47
- return {
48
- "X-Api-Key": api_key,
49
- "Content-Type": "application/json",
50
- "Cache-Control": "no-cache", # Often good practice for APIs
51
- }
26
+ return {"X-Api-Key": api_key, "Content-Type": "application/json", "Cache-Control": "no-cache"}
52
27
 
53
- def people_enrichment(
28
+ async def people_enrichment(
54
29
  self,
55
30
  first_name: str | None = None,
56
31
  last_name: str | None = None,
@@ -112,25 +87,16 @@ class ApolloApp(APIApplication):
112
87
  ]
113
88
  if v is not None
114
89
  }
115
- response = self._post(
116
- url,
117
- data=request_body_data,
118
- params=query_params,
119
- content_type="application/json",
120
- )
90
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
121
91
  response.raise_for_status()
122
- if (
123
- response.status_code == 204
124
- or not response.content
125
- or not response.text.strip()
126
- ):
92
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
127
93
  return None
128
94
  try:
129
95
  return response.json()
130
96
  except ValueError:
131
97
  return None
132
98
 
133
- def bulk_people_enrichment(
99
+ async def bulk_people_enrichment(
134
100
  self,
135
101
  reveal_personal_emails: bool | None = None,
136
102
  reveal_phone_number: bool | None = None,
@@ -157,12 +123,8 @@ class ApolloApp(APIApplication):
157
123
  People
158
124
  """
159
125
  request_body_data = None
160
- request_body_data = {
161
- "details": details,
162
- }
163
- request_body_data = {
164
- k: v for k, v in request_body_data.items() if v is not None
165
- }
126
+ request_body_data = {"details": details}
127
+ request_body_data = {k: v for k, v in request_body_data.items() if v is not None}
166
128
  url = f"{self.base_url}/people/bulk_match"
167
129
  query_params = {
168
130
  k: v
@@ -173,25 +135,16 @@ class ApolloApp(APIApplication):
173
135
  ]
174
136
  if v is not None
175
137
  }
176
- response = self._post(
177
- url,
178
- data=request_body_data,
179
- params=query_params,
180
- content_type="application/json",
181
- )
138
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
182
139
  response.raise_for_status()
183
- if (
184
- response.status_code == 204
185
- or not response.content
186
- or not response.text.strip()
187
- ):
140
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
188
141
  return None
189
142
  try:
190
143
  return response.json()
191
144
  except ValueError:
192
145
  return None
193
146
 
194
- def organization_enrichment(self, domain: str) -> dict[str, Any]:
147
+ async def organization_enrichment(self, domain: str) -> dict[str, Any]:
195
148
  """
196
149
  Retrieves enriched organization data for a company specified by its domain name.
197
150
 
@@ -212,18 +165,14 @@ class ApolloApp(APIApplication):
212
165
  query_params = {k: v for k, v in [("domain", domain)] if v is not None}
213
166
  response = self._get(url, params=query_params)
214
167
  response.raise_for_status()
215
- if (
216
- response.status_code == 204
217
- or not response.content
218
- or not response.text.strip()
219
- ):
168
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
220
169
  return None
221
170
  try:
222
171
  return response.json()
223
172
  except ValueError:
224
173
  return None
225
174
 
226
- def bulk_organization_enrichment(self, domains_: list[str]) -> dict[str, Any]:
175
+ async def bulk_organization_enrichment(self, domains_: list[str]) -> dict[str, Any]:
227
176
  """
228
177
  Enriches multiple organizations in bulk by submitting an array of domain names and returns detailed company profiles in a single request.
229
178
 
@@ -243,25 +192,16 @@ class ApolloApp(APIApplication):
243
192
  request_body_data = None
244
193
  url = f"{self.base_url}/organizations/bulk_enrich"
245
194
  query_params = {k: v for k, v in [("domains[]", domains_)] if v is not None}
246
- response = self._post(
247
- url,
248
- data=request_body_data,
249
- params=query_params,
250
- content_type="application/json",
251
- )
195
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
252
196
  response.raise_for_status()
253
- if (
254
- response.status_code == 204
255
- or not response.content
256
- or not response.text.strip()
257
- ):
197
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
258
198
  return None
259
199
  try:
260
200
  return response.json()
261
201
  except ValueError:
262
202
  return None
263
203
 
264
- def people_search(
204
+ async def people_search(
265
205
  self,
266
206
  person_titles_: list[str] | None = None,
267
207
  include_similar_titles: bool | None = None,
@@ -316,35 +256,23 @@ class ApolloApp(APIApplication):
316
256
  ("q_organization_domains_list[]", q_organization_domains_list_),
317
257
  ("contact_email_status[]", contact_email_status_),
318
258
  ("organization_ids[]", organization_ids_),
319
- (
320
- "organization_num_employees_ranges[]",
321
- organization_num_employees_ranges_,
322
- ),
259
+ ("organization_num_employees_ranges[]", organization_num_employees_ranges_),
323
260
  ("q_keywords", q_keywords),
324
261
  ("page", page),
325
262
  ("per_page", per_page),
326
263
  ]
327
264
  if v is not None
328
265
  }
329
- response = self._post(
330
- url,
331
- data=request_body_data,
332
- params=query_params,
333
- content_type="application/json",
334
- )
266
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
335
267
  response.raise_for_status()
336
- if (
337
- response.status_code == 204
338
- or not response.content
339
- or not response.text.strip()
340
- ):
268
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
341
269
  return None
342
270
  try:
343
271
  return response.json()
344
272
  except ValueError:
345
273
  return None
346
274
 
347
- def organization_search(
275
+ async def organization_search(
348
276
  self,
349
277
  organization_num_employees_ranges_: list[str] | None = None,
350
278
  organization_locations_: list[str] | None = None,
@@ -389,18 +317,12 @@ class ApolloApp(APIApplication):
389
317
  query_params = {
390
318
  k: v
391
319
  for k, v in [
392
- (
393
- "organization_num_employees_ranges[]",
394
- organization_num_employees_ranges_,
395
- ),
320
+ ("organization_num_employees_ranges[]", organization_num_employees_ranges_),
396
321
  ("organization_locations[]", organization_locations_),
397
322
  ("organization_not_locations[]", organization_not_locations_),
398
323
  ("revenue_range[min]", revenue_range_min),
399
324
  ("revenue_range[max]", revenue_range_max),
400
- (
401
- "currently_using_any_of_technology_uids[]",
402
- currently_using_any_of_technology_uids_,
403
- ),
325
+ ("currently_using_any_of_technology_uids[]", currently_using_any_of_technology_uids_),
404
326
  ("q_organization_keyword_tags[]", q_organization_keyword_tags_),
405
327
  ("q_organization_name", q_organization_name),
406
328
  ("organization_ids[]", organization_ids_),
@@ -409,29 +331,17 @@ class ApolloApp(APIApplication):
409
331
  ]
410
332
  if v is not None
411
333
  }
412
- response = self._post(
413
- url,
414
- data=request_body_data,
415
- params=query_params,
416
- content_type="application/json",
417
- )
334
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
418
335
  response.raise_for_status()
419
- if (
420
- response.status_code == 204
421
- or not response.content
422
- or not response.text.strip()
423
- ):
336
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
424
337
  return None
425
338
  try:
426
339
  return response.json()
427
340
  except ValueError:
428
341
  return None
429
342
 
430
- def organization_jobs_postings(
431
- self,
432
- organization_id: str,
433
- page: int | None = None,
434
- per_page: int | None = None,
343
+ async def organization_jobs_postings(
344
+ self, organization_id: str, page: int | None = None, per_page: int | None = None
435
345
  ) -> dict[str, Any]:
436
346
  """
437
347
  Retrieves a paginated list of job postings for a specified organization using the "GET" method, allowing optional pagination parameters for page and items per page.
@@ -454,23 +364,17 @@ class ApolloApp(APIApplication):
454
364
  if organization_id is None:
455
365
  raise ValueError("Missing required parameter 'organization_id'.")
456
366
  url = f"{self.base_url}/organizations/{organization_id}/job_postings"
457
- query_params = {
458
- k: v for k, v in [("page", page), ("per_page", per_page)] if v is not None
459
- }
367
+ query_params = {k: v for k, v in [("page", page), ("per_page", per_page)] if v is not None}
460
368
  response = self._get(url, params=query_params)
461
369
  response.raise_for_status()
462
- if (
463
- response.status_code == 204
464
- or not response.content
465
- or not response.text.strip()
466
- ):
370
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
467
371
  return None
468
372
  try:
469
373
  return response.json()
470
374
  except ValueError:
471
375
  return None
472
376
 
473
- def create_an_account(
377
+ async def create_an_account(
474
378
  self,
475
379
  name: str | None = None,
476
380
  domain: str | None = None,
@@ -514,25 +418,16 @@ class ApolloApp(APIApplication):
514
418
  ]
515
419
  if v is not None
516
420
  }
517
- response = self._post(
518
- url,
519
- data=request_body_data,
520
- params=query_params,
521
- content_type="application/json",
522
- )
421
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
523
422
  response.raise_for_status()
524
- if (
525
- response.status_code == 204
526
- or not response.content
527
- or not response.text.strip()
528
- ):
423
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
529
424
  return None
530
425
  try:
531
426
  return response.json()
532
427
  except ValueError:
533
428
  return None
534
429
 
535
- def update_an_account(
430
+ async def update_an_account(
536
431
  self,
537
432
  account_id: str,
538
433
  name: str | None = None,
@@ -580,25 +475,16 @@ class ApolloApp(APIApplication):
580
475
  ]
581
476
  if v is not None
582
477
  }
583
- response = self._put(
584
- url,
585
- data=request_body_data,
586
- params=query_params,
587
- content_type="application/json",
588
- )
478
+ response = self._put(url, data=request_body_data, params=query_params, content_type="application/json")
589
479
  response.raise_for_status()
590
- if (
591
- response.status_code == 204
592
- or not response.content
593
- or not response.text.strip()
594
- ):
480
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
595
481
  return None
596
482
  try:
597
483
  return response.json()
598
484
  except ValueError:
599
485
  return None
600
486
 
601
- def search_for_accounts(
487
+ async def search_for_accounts(
602
488
  self,
603
489
  q_organization_name: str | None = None,
604
490
  account_stage_ids_: list[str] | None = None,
@@ -642,27 +528,16 @@ class ApolloApp(APIApplication):
642
528
  ]
643
529
  if v is not None
644
530
  }
645
- response = self._post(
646
- url,
647
- data=request_body_data,
648
- params=query_params,
649
- content_type="application/json",
650
- )
531
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
651
532
  response.raise_for_status()
652
- if (
653
- response.status_code == 204
654
- or not response.content
655
- or not response.text.strip()
656
- ):
533
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
657
534
  return None
658
535
  try:
659
536
  return response.json()
660
537
  except ValueError:
661
538
  return None
662
539
 
663
- def update_account_stage(
664
- self, account_ids_: list[str], account_stage_id: str
665
- ) -> dict[str, Any]:
540
+ async def update_account_stage(self, account_ids_: list[str], account_stage_id: str) -> dict[str, Any]:
666
541
  """
667
542
  Updates multiple account records in bulk by their specified IDs, assigning each to the given account stage ID.
668
543
 
@@ -682,35 +557,17 @@ class ApolloApp(APIApplication):
682
557
  """
683
558
  request_body_data = None
684
559
  url = f"{self.base_url}/accounts/bulk_update"
685
- query_params = {
686
- k: v
687
- for k, v in [
688
- ("account_ids[]", account_ids_),
689
- ("account_stage_id", account_stage_id),
690
- ]
691
- if v is not None
692
- }
693
- response = self._post(
694
- url,
695
- data=request_body_data,
696
- params=query_params,
697
- content_type="application/json",
698
- )
560
+ query_params = {k: v for k, v in [("account_ids[]", account_ids_), ("account_stage_id", account_stage_id)] if v is not None}
561
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
699
562
  response.raise_for_status()
700
- if (
701
- response.status_code == 204
702
- or not response.content
703
- or not response.text.strip()
704
- ):
563
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
705
564
  return None
706
565
  try:
707
566
  return response.json()
708
567
  except ValueError:
709
568
  return None
710
569
 
711
- def update_account_ownership(
712
- self, account_ids_: list[str], owner_id: str
713
- ) -> dict[str, Any]:
570
+ async def update_account_ownership(self, account_ids_: list[str], owner_id: str) -> dict[str, Any]:
714
571
  """
715
572
  Updates the owners of multiple accounts by assigning a specified owner ID to the given list of account IDs.
716
573
 
@@ -730,30 +587,17 @@ class ApolloApp(APIApplication):
730
587
  """
731
588
  request_body_data = None
732
589
  url = f"{self.base_url}/accounts/update_owners"
733
- query_params = {
734
- k: v
735
- for k, v in [("account_ids[]", account_ids_), ("owner_id", owner_id)]
736
- if v is not None
737
- }
738
- response = self._post(
739
- url,
740
- data=request_body_data,
741
- params=query_params,
742
- content_type="application/json",
743
- )
590
+ query_params = {k: v for k, v in [("account_ids[]", account_ids_), ("owner_id", owner_id)] if v is not None}
591
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
744
592
  response.raise_for_status()
745
- if (
746
- response.status_code == 204
747
- or not response.content
748
- or not response.text.strip()
749
- ):
593
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
750
594
  return None
751
595
  try:
752
596
  return response.json()
753
597
  except ValueError:
754
598
  return None
755
599
 
756
- def list_account_stages(self) -> dict[str, Any]:
600
+ async def list_account_stages(self) -> dict[str, Any]:
757
601
  """
758
602
  Retrieves a list of account stages.
759
603
 
@@ -771,18 +615,14 @@ class ApolloApp(APIApplication):
771
615
  query_params = {}
772
616
  response = self._get(url, params=query_params)
773
617
  response.raise_for_status()
774
- if (
775
- response.status_code == 204
776
- or not response.content
777
- or not response.text.strip()
778
- ):
618
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
779
619
  return None
780
620
  try:
781
621
  return response.json()
782
622
  except ValueError:
783
623
  return None
784
624
 
785
- def create_a_contact(
625
+ async def create_a_contact(
786
626
  self,
787
627
  first_name: str | None = None,
788
628
  last_name: str | None = None,
@@ -853,25 +693,16 @@ class ApolloApp(APIApplication):
853
693
  ]
854
694
  if v is not None
855
695
  }
856
- response = self._post(
857
- url,
858
- data=request_body_data,
859
- params=query_params,
860
- content_type="application/json",
861
- )
696
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
862
697
  response.raise_for_status()
863
- if (
864
- response.status_code == 204
865
- or not response.content
866
- or not response.text.strip()
867
- ):
698
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
868
699
  return None
869
700
  try:
870
701
  return response.json()
871
702
  except ValueError:
872
703
  return None
873
704
 
874
- def update_a_contact(
705
+ async def update_a_contact(
875
706
  self,
876
707
  contact_id: str,
877
708
  first_name: str | None = None,
@@ -946,25 +777,16 @@ class ApolloApp(APIApplication):
946
777
  ]
947
778
  if v is not None
948
779
  }
949
- response = self._put(
950
- url,
951
- data=request_body_data,
952
- params=query_params,
953
- content_type="application/json",
954
- )
780
+ response = self._put(url, data=request_body_data, params=query_params, content_type="application/json")
955
781
  response.raise_for_status()
956
- if (
957
- response.status_code == 204
958
- or not response.content
959
- or not response.text.strip()
960
- ):
782
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
961
783
  return None
962
784
  try:
963
785
  return response.json()
964
786
  except ValueError:
965
787
  return None
966
788
 
967
- def search_for_contacts(
789
+ async def search_for_contacts(
968
790
  self,
969
791
  q_keywords: str | None = None,
970
792
  contact_stage_ids_: list[str] | None = None,
@@ -1008,27 +830,16 @@ class ApolloApp(APIApplication):
1008
830
  ]
1009
831
  if v is not None
1010
832
  }
1011
- response = self._post(
1012
- url,
1013
- data=request_body_data,
1014
- params=query_params,
1015
- content_type="application/json",
1016
- )
833
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1017
834
  response.raise_for_status()
1018
- if (
1019
- response.status_code == 204
1020
- or not response.content
1021
- or not response.text.strip()
1022
- ):
835
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1023
836
  return None
1024
837
  try:
1025
838
  return response.json()
1026
839
  except ValueError:
1027
840
  return None
1028
841
 
1029
- def update_contact_stage(
1030
- self, contact_ids_: list[str], contact_stage_id: str
1031
- ) -> dict[str, Any]:
842
+ async def update_contact_stage(self, contact_ids_: list[str], contact_stage_id: str) -> dict[str, Any]:
1032
843
  """
1033
844
  Updates the stage of multiple contacts by specifying their IDs and the new contact stage ID via a POST request.
1034
845
 
@@ -1048,35 +859,17 @@ class ApolloApp(APIApplication):
1048
859
  """
1049
860
  request_body_data = None
1050
861
  url = f"{self.base_url}/contacts/update_stages"
1051
- query_params = {
1052
- k: v
1053
- for k, v in [
1054
- ("contact_ids[]", contact_ids_),
1055
- ("contact_stage_id", contact_stage_id),
1056
- ]
1057
- if v is not None
1058
- }
1059
- response = self._post(
1060
- url,
1061
- data=request_body_data,
1062
- params=query_params,
1063
- content_type="application/json",
1064
- )
862
+ query_params = {k: v for k, v in [("contact_ids[]", contact_ids_), ("contact_stage_id", contact_stage_id)] if v is not None}
863
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1065
864
  response.raise_for_status()
1066
- if (
1067
- response.status_code == 204
1068
- or not response.content
1069
- or not response.text.strip()
1070
- ):
865
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1071
866
  return None
1072
867
  try:
1073
868
  return response.json()
1074
869
  except ValueError:
1075
870
  return None
1076
871
 
1077
- def update_contact_ownership(
1078
- self, contact_ids_: list[str], owner_id: str
1079
- ) -> dict[str, Any]:
872
+ async def update_contact_ownership(self, contact_ids_: list[str], owner_id: str) -> dict[str, Any]:
1080
873
  """
1081
874
  Updates the owners of specified contacts by assigning a new owner ID to the provided list of contact IDs.
1082
875
 
@@ -1096,30 +889,17 @@ class ApolloApp(APIApplication):
1096
889
  """
1097
890
  request_body_data = None
1098
891
  url = f"{self.base_url}/contacts/update_owners"
1099
- query_params = {
1100
- k: v
1101
- for k, v in [("contact_ids[]", contact_ids_), ("owner_id", owner_id)]
1102
- if v is not None
1103
- }
1104
- response = self._post(
1105
- url,
1106
- data=request_body_data,
1107
- params=query_params,
1108
- content_type="application/json",
1109
- )
892
+ query_params = {k: v for k, v in [("contact_ids[]", contact_ids_), ("owner_id", owner_id)] if v is not None}
893
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1110
894
  response.raise_for_status()
1111
- if (
1112
- response.status_code == 204
1113
- or not response.content
1114
- or not response.text.strip()
1115
- ):
895
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1116
896
  return None
1117
897
  try:
1118
898
  return response.json()
1119
899
  except ValueError:
1120
900
  return None
1121
901
 
1122
- def list_contact_stages(self) -> Any:
902
+ async def list_contact_stages(self) -> Any:
1123
903
  """
1124
904
  Retrieves a list of all available contact stage IDs from the Apollo account[2][4].
1125
905
 
@@ -1137,18 +917,14 @@ class ApolloApp(APIApplication):
1137
917
  query_params = {}
1138
918
  response = self._get(url, params=query_params)
1139
919
  response.raise_for_status()
1140
- if (
1141
- response.status_code == 204
1142
- or not response.content
1143
- or not response.text.strip()
1144
- ):
920
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1145
921
  return None
1146
922
  try:
1147
923
  return response.json()
1148
924
  except ValueError:
1149
925
  return None
1150
926
 
1151
- def create_deal(
927
+ async def create_deal(
1152
928
  self,
1153
929
  name: str,
1154
930
  owner_id: str | None = None,
@@ -1192,29 +968,17 @@ class ApolloApp(APIApplication):
1192
968
  ]
1193
969
  if v is not None
1194
970
  }
1195
- response = self._post(
1196
- url,
1197
- data=request_body_data,
1198
- params=query_params,
1199
- content_type="application/json",
1200
- )
971
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1201
972
  response.raise_for_status()
1202
- if (
1203
- response.status_code == 204
1204
- or not response.content
1205
- or not response.text.strip()
1206
- ):
973
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1207
974
  return None
1208
975
  try:
1209
976
  return response.json()
1210
977
  except ValueError:
1211
978
  return None
1212
979
 
1213
- def list_all_deals(
1214
- self,
1215
- sort_by_field: str | None = None,
1216
- page: int | None = None,
1217
- per_page: int | None = None,
980
+ async def list_all_deals(
981
+ self, sort_by_field: str | None = None, page: int | None = None, per_page: int | None = None
1218
982
  ) -> dict[str, Any]:
1219
983
  """
1220
984
  Searches and retrieves a paginated list of opportunities with optional sorting by a specified field.
@@ -1235,29 +999,17 @@ class ApolloApp(APIApplication):
1235
999
  Deals, important
1236
1000
  """
1237
1001
  url = f"{self.base_url}/opportunities/search"
1238
- query_params = {
1239
- k: v
1240
- for k, v in [
1241
- ("sort_by_field", sort_by_field),
1242
- ("page", page),
1243
- ("per_page", per_page),
1244
- ]
1245
- if v is not None
1246
- }
1002
+ query_params = {k: v for k, v in [("sort_by_field", sort_by_field), ("page", page), ("per_page", per_page)] if v is not None}
1247
1003
  response = self._get(url, params=query_params)
1248
1004
  response.raise_for_status()
1249
- if (
1250
- response.status_code == 204
1251
- or not response.content
1252
- or not response.text.strip()
1253
- ):
1005
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1254
1006
  return None
1255
1007
  try:
1256
1008
  return response.json()
1257
1009
  except ValueError:
1258
1010
  return None
1259
1011
 
1260
- def update_deal(
1012
+ async def update_deal(
1261
1013
  self,
1262
1014
  opportunity_id: str,
1263
1015
  owner_id: str | None = None,
@@ -1316,18 +1068,14 @@ class ApolloApp(APIApplication):
1316
1068
  }
1317
1069
  response = self._patch(url, data=request_body_data, params=query_params)
1318
1070
  response.raise_for_status()
1319
- if (
1320
- response.status_code == 204
1321
- or not response.content
1322
- or not response.text.strip()
1323
- ):
1071
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1324
1072
  return None
1325
1073
  try:
1326
1074
  return response.json()
1327
1075
  except ValueError:
1328
1076
  return None
1329
1077
 
1330
- def list_deal_stages(self) -> dict[str, Any]:
1078
+ async def list_deal_stages(self) -> dict[str, Any]:
1331
1079
  """
1332
1080
  Retrieves a list of opportunity stages representing the different phases in the sales pipeline.
1333
1081
 
@@ -1345,18 +1093,14 @@ class ApolloApp(APIApplication):
1345
1093
  query_params = {}
1346
1094
  response = self._get(url, params=query_params)
1347
1095
  response.raise_for_status()
1348
- if (
1349
- response.status_code == 204
1350
- or not response.content
1351
- or not response.text.strip()
1352
- ):
1096
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1353
1097
  return None
1354
1098
  try:
1355
1099
  return response.json()
1356
1100
  except ValueError:
1357
1101
  return None
1358
1102
 
1359
- def add_contacts_to_sequence(
1103
+ async def add_contacts_to_sequence(
1360
1104
  self,
1361
1105
  sequence_id: str,
1362
1106
  emailer_campaign_id: str,
@@ -1407,39 +1151,22 @@ class ApolloApp(APIApplication):
1407
1151
  ("sequence_no_email", sequence_no_email),
1408
1152
  ("sequence_unverified_email", sequence_unverified_email),
1409
1153
  ("sequence_job_change", sequence_job_change),
1410
- (
1411
- "sequence_active_in_other_campaigns",
1412
- sequence_active_in_other_campaigns,
1413
- ),
1414
- (
1415
- "sequence_finished_in_other_campaigns",
1416
- sequence_finished_in_other_campaigns,
1417
- ),
1154
+ ("sequence_active_in_other_campaigns", sequence_active_in_other_campaigns),
1155
+ ("sequence_finished_in_other_campaigns", sequence_finished_in_other_campaigns),
1418
1156
  ("user_id", user_id),
1419
1157
  ]
1420
1158
  if v is not None
1421
1159
  }
1422
- response = self._post(
1423
- url,
1424
- data=request_body_data,
1425
- params=query_params,
1426
- content_type="application/json",
1427
- )
1160
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1428
1161
  response.raise_for_status()
1429
- if (
1430
- response.status_code == 204
1431
- or not response.content
1432
- or not response.text.strip()
1433
- ):
1162
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1434
1163
  return None
1435
1164
  try:
1436
1165
  return response.json()
1437
1166
  except ValueError:
1438
1167
  return None
1439
1168
 
1440
- def update_contact_status_sequence(
1441
- self, emailer_campaign_ids_: list[str], contact_ids_: list[str], mode: str
1442
- ) -> dict[str, Any]:
1169
+ async def update_contact_status_sequence(self, emailer_campaign_ids_: list[str], contact_ids_: list[str], mode: str) -> dict[str, Any]:
1443
1170
  """
1444
1171
  Posts a request to remove or stop specified contact IDs from given emailer campaign IDs based on the selected mode.
1445
1172
 
@@ -1462,40 +1189,20 @@ class ApolloApp(APIApplication):
1462
1189
  url = f"{self.base_url}/emailer_campaigns/remove_or_stop_contact_ids"
1463
1190
  query_params = {
1464
1191
  k: v
1465
- for k, v in [
1466
- ("emailer_campaign_ids[]", emailer_campaign_ids_),
1467
- ("contact_ids[]", contact_ids_),
1468
- ("mode", mode),
1469
- ]
1192
+ for k, v in [("emailer_campaign_ids[]", emailer_campaign_ids_), ("contact_ids[]", contact_ids_), ("mode", mode)]
1470
1193
  if v is not None
1471
1194
  }
1472
- response = self._post(
1473
- url,
1474
- data=request_body_data,
1475
- params=query_params,
1476
- content_type="application/json",
1477
- )
1195
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1478
1196
  response.raise_for_status()
1479
- if (
1480
- response.status_code == 204
1481
- or not response.content
1482
- or not response.text.strip()
1483
- ):
1197
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1484
1198
  return None
1485
1199
  try:
1486
1200
  return response.json()
1487
1201
  except ValueError:
1488
1202
  return None
1489
1203
 
1490
- def create_task(
1491
- self,
1492
- user_id: str,
1493
- contact_ids_: list[str],
1494
- priority: str,
1495
- due_at: str,
1496
- type: str,
1497
- status: str,
1498
- note: str | None = None,
1204
+ async def create_task(
1205
+ self, user_id: str, contact_ids_: list[str], priority: str, due_at: str, type: str, status: str, note: str | None = None
1499
1206
  ) -> Any:
1500
1207
  """
1501
1208
  Creates multiple tasks in bulk with specified user, contact IDs, priority, due date, type, status, and optional note parameters.
@@ -1534,25 +1241,16 @@ class ApolloApp(APIApplication):
1534
1241
  ]
1535
1242
  if v is not None
1536
1243
  }
1537
- response = self._post(
1538
- url,
1539
- data=request_body_data,
1540
- params=query_params,
1541
- content_type="application/json",
1542
- )
1244
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1543
1245
  response.raise_for_status()
1544
- if (
1545
- response.status_code == 204
1546
- or not response.content
1547
- or not response.text.strip()
1548
- ):
1246
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1549
1247
  return None
1550
1248
  try:
1551
1249
  return response.json()
1552
1250
  except ValueError:
1553
1251
  return None
1554
1252
 
1555
- def search_tasks(
1253
+ async def search_tasks(
1556
1254
  self,
1557
1255
  sort_by_field: str | None = None,
1558
1256
  open_factor_names_: list[str] | None = None,
@@ -1590,27 +1288,16 @@ class ApolloApp(APIApplication):
1590
1288
  ]
1591
1289
  if v is not None
1592
1290
  }
1593
- response = self._post(
1594
- url,
1595
- data=request_body_data,
1596
- params=query_params,
1597
- content_type="application/json",
1598
- )
1291
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1599
1292
  response.raise_for_status()
1600
- if (
1601
- response.status_code == 204
1602
- or not response.content
1603
- or not response.text.strip()
1604
- ):
1293
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1605
1294
  return None
1606
1295
  try:
1607
1296
  return response.json()
1608
1297
  except ValueError:
1609
1298
  return None
1610
1299
 
1611
- def get_a_list_of_users(
1612
- self, page: int | None = None, per_page: int | None = None
1613
- ) -> dict[str, Any]:
1300
+ async def get_a_list_of_users(self, page: int | None = None, per_page: int | None = None) -> dict[str, Any]:
1614
1301
  """
1615
1302
  Searches for users with optional pagination parameters to specify the page number and number of results per page.
1616
1303
 
@@ -1629,23 +1316,17 @@ class ApolloApp(APIApplication):
1629
1316
  Users
1630
1317
  """
1631
1318
  url = f"{self.base_url}/users/search"
1632
- query_params = {
1633
- k: v for k, v in [("page", page), ("per_page", per_page)] if v is not None
1634
- }
1319
+ query_params = {k: v for k, v in [("page", page), ("per_page", per_page)] if v is not None}
1635
1320
  response = self._get(url, params=query_params)
1636
1321
  response.raise_for_status()
1637
- if (
1638
- response.status_code == 204
1639
- or not response.content
1640
- or not response.text.strip()
1641
- ):
1322
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1642
1323
  return None
1643
1324
  try:
1644
1325
  return response.json()
1645
1326
  except ValueError:
1646
1327
  return None
1647
1328
 
1648
- def get_a_list_of_email_accounts(self) -> dict[str, Any]:
1329
+ async def get_a_list_of_email_accounts(self) -> dict[str, Any]:
1649
1330
  """
1650
1331
  Retrieves a list of all available email accounts and their summary information.
1651
1332
 
@@ -1663,18 +1344,14 @@ class ApolloApp(APIApplication):
1663
1344
  query_params = {}
1664
1345
  response = self._get(url, params=query_params)
1665
1346
  response.raise_for_status()
1666
- if (
1667
- response.status_code == 204
1668
- or not response.content
1669
- or not response.text.strip()
1670
- ):
1347
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1671
1348
  return None
1672
1349
  try:
1673
1350
  return response.json()
1674
1351
  except ValueError:
1675
1352
  return None
1676
1353
 
1677
- def get_a_list_of_all_liststags(self) -> list[Any]:
1354
+ async def get_a_list_of_all_liststags(self) -> list[Any]:
1678
1355
  """
1679
1356
  Retrieves a list of labels.
1680
1357
 
@@ -1692,18 +1369,14 @@ class ApolloApp(APIApplication):
1692
1369
  query_params = {}
1693
1370
  response = self._get(url, params=query_params)
1694
1371
  response.raise_for_status()
1695
- if (
1696
- response.status_code == 204
1697
- or not response.content
1698
- or not response.text.strip()
1699
- ):
1372
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1700
1373
  return None
1701
1374
  try:
1702
1375
  return response.json()
1703
1376
  except ValueError:
1704
1377
  return None
1705
1378
 
1706
- def get_a_list_of_all_custom_fields(self) -> dict[str, Any]:
1379
+ async def get_a_list_of_all_custom_fields(self) -> dict[str, Any]:
1707
1380
  """
1708
1381
  Retrieves a list of all typed custom fields configured in the system.
1709
1382
 
@@ -1721,18 +1394,14 @@ class ApolloApp(APIApplication):
1721
1394
  query_params = {}
1722
1395
  response = self._get(url, params=query_params)
1723
1396
  response.raise_for_status()
1724
- if (
1725
- response.status_code == 204
1726
- or not response.content
1727
- or not response.text.strip()
1728
- ):
1397
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1729
1398
  return None
1730
1399
  try:
1731
1400
  return response.json()
1732
1401
  except ValueError:
1733
1402
  return None
1734
1403
 
1735
- def view_deal(self, opportunity_id: str) -> dict[str, Any]:
1404
+ async def view_deal(self, opportunity_id: str) -> dict[str, Any]:
1736
1405
  """
1737
1406
  View Deal by opportunity_id
1738
1407
 
@@ -1752,23 +1421,14 @@ class ApolloApp(APIApplication):
1752
1421
  query_params = {}
1753
1422
  response = self._get(url, params=query_params)
1754
1423
  response.raise_for_status()
1755
- if (
1756
- response.status_code == 204
1757
- or not response.content
1758
- or not response.text.strip()
1759
- ):
1424
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1760
1425
  return None
1761
1426
  try:
1762
1427
  return response.json()
1763
1428
  except ValueError:
1764
1429
  return None
1765
1430
 
1766
- def search_for_sequences(
1767
- self,
1768
- q_name: str | None = None,
1769
- page: str | None = None,
1770
- per_page: str | None = None,
1771
- ) -> dict[str, Any]:
1431
+ async def search_for_sequences(self, q_name: str | None = None, page: str | None = None, per_page: str | None = None) -> dict[str, Any]:
1772
1432
  """
1773
1433
  Search for Sequences by name
1774
1434
 
@@ -1786,23 +1446,10 @@ class ApolloApp(APIApplication):
1786
1446
  """
1787
1447
  request_body_data = None
1788
1448
  url = f"{self.base_url}/emailer_campaigns/search"
1789
- query_params = {
1790
- k: v
1791
- for k, v in [("q_name", q_name), ("page", page), ("per_page", per_page)]
1792
- if v is not None
1793
- }
1794
- response = self._post(
1795
- url,
1796
- data=request_body_data,
1797
- params=query_params,
1798
- content_type="application/json",
1799
- )
1449
+ query_params = {k: v for k, v in [("q_name", q_name), ("page", page), ("per_page", per_page)] if v is not None}
1450
+ response = self._post(url, data=request_body_data, params=query_params, content_type="application/json")
1800
1451
  response.raise_for_status()
1801
- if (
1802
- response.status_code == 204
1803
- or not response.content
1804
- or not response.text.strip()
1805
- ):
1452
+ if response.status_code == 204 or not response.content or (not response.text.strip()):
1806
1453
  return None
1807
1454
  try:
1808
1455
  return response.json()