universal-mcp-applications 0.1.17__py3-none-any.whl → 0.1.33__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.
- universal_mcp/applications/BEST_PRACTICES.md +166 -0
- universal_mcp/applications/ahrefs/README.md +3 -3
- universal_mcp/applications/airtable/README.md +3 -3
- universal_mcp/applications/airtable/app.py +0 -1
- universal_mcp/applications/apollo/app.py +0 -1
- universal_mcp/applications/asana/README.md +3 -3
- universal_mcp/applications/aws_s3/README.md +29 -0
- universal_mcp/applications/aws_s3/app.py +40 -39
- universal_mcp/applications/bill/README.md +249 -0
- universal_mcp/applications/browser_use/README.md +1 -0
- universal_mcp/applications/browser_use/__init__.py +0 -0
- universal_mcp/applications/browser_use/app.py +71 -0
- universal_mcp/applications/calendly/README.md +45 -45
- universal_mcp/applications/calendly/app.py +125 -125
- universal_mcp/applications/canva/README.md +35 -35
- universal_mcp/applications/canva/app.py +95 -99
- universal_mcp/applications/clickup/README.md +4 -4
- universal_mcp/applications/confluence/app.py +0 -1
- universal_mcp/applications/contentful/README.md +1 -2
- universal_mcp/applications/contentful/app.py +4 -5
- universal_mcp/applications/crustdata/README.md +3 -3
- universal_mcp/applications/domain_checker/README.md +2 -2
- universal_mcp/applications/domain_checker/app.py +11 -15
- universal_mcp/applications/e2b/README.md +4 -4
- universal_mcp/applications/e2b/app.py +4 -4
- universal_mcp/applications/elevenlabs/README.md +3 -77
- universal_mcp/applications/elevenlabs/app.py +18 -15
- universal_mcp/applications/exa/README.md +7 -7
- universal_mcp/applications/exa/app.py +17 -17
- universal_mcp/applications/falai/README.md +13 -12
- universal_mcp/applications/falai/app.py +34 -35
- universal_mcp/applications/figma/README.md +3 -3
- universal_mcp/applications/file_system/README.md +13 -0
- universal_mcp/applications/file_system/app.py +9 -9
- universal_mcp/applications/firecrawl/README.md +9 -9
- universal_mcp/applications/firecrawl/app.py +46 -46
- universal_mcp/applications/fireflies/README.md +14 -14
- universal_mcp/applications/fireflies/app.py +164 -57
- universal_mcp/applications/fpl/README.md +12 -12
- universal_mcp/applications/fpl/app.py +54 -55
- universal_mcp/applications/ghost_content/app.py +0 -1
- universal_mcp/applications/github/README.md +10 -10
- universal_mcp/applications/github/app.py +50 -52
- universal_mcp/applications/google_calendar/README.md +10 -10
- universal_mcp/applications/google_calendar/app.py +50 -49
- universal_mcp/applications/google_docs/README.md +14 -14
- universal_mcp/applications/google_docs/app.py +307 -233
- universal_mcp/applications/google_drive/README.md +54 -57
- universal_mcp/applications/google_drive/app.py +270 -261
- universal_mcp/applications/google_gemini/README.md +3 -14
- universal_mcp/applications/google_gemini/app.py +15 -18
- universal_mcp/applications/google_mail/README.md +20 -20
- universal_mcp/applications/google_mail/app.py +110 -109
- universal_mcp/applications/google_searchconsole/README.md +10 -10
- universal_mcp/applications/google_searchconsole/app.py +37 -37
- universal_mcp/applications/google_sheet/README.md +25 -25
- universal_mcp/applications/google_sheet/app.py +270 -266
- universal_mcp/applications/hashnode/README.md +6 -3
- universal_mcp/applications/hashnode/app.py +174 -25
- universal_mcp/applications/http_tools/README.md +5 -5
- universal_mcp/applications/http_tools/app.py +10 -11
- universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
- universal_mcp/applications/hubspot/api_segments/api_segment_base.py +54 -0
- universal_mcp/applications/hubspot/api_segments/crm_api.py +7337 -0
- universal_mcp/applications/hubspot/api_segments/marketing_api.py +1467 -0
- universal_mcp/applications/hubspot/app.py +2 -15
- universal_mcp/applications/jira/app.py +0 -1
- universal_mcp/applications/klaviyo/README.md +0 -36
- universal_mcp/applications/linkedin/README.md +18 -4
- universal_mcp/applications/linkedin/app.py +763 -162
- universal_mcp/applications/mailchimp/README.md +3 -3
- universal_mcp/applications/markitdown/app.py +10 -5
- universal_mcp/applications/ms_teams/README.md +31 -31
- universal_mcp/applications/ms_teams/app.py +151 -151
- universal_mcp/applications/neon/README.md +3 -3
- universal_mcp/applications/onedrive/README.md +24 -0
- universal_mcp/applications/onedrive/__init__.py +1 -0
- universal_mcp/applications/onedrive/app.py +338 -0
- universal_mcp/applications/openai/README.md +18 -17
- universal_mcp/applications/openai/app.py +40 -39
- universal_mcp/applications/outlook/README.md +9 -9
- universal_mcp/applications/outlook/app.py +307 -225
- universal_mcp/applications/perplexity/README.md +4 -4
- universal_mcp/applications/perplexity/app.py +4 -4
- universal_mcp/applications/posthog/README.md +128 -127
- universal_mcp/applications/reddit/README.md +21 -124
- universal_mcp/applications/reddit/app.py +51 -68
- universal_mcp/applications/resend/README.md +29 -29
- universal_mcp/applications/resend/app.py +116 -117
- universal_mcp/applications/rocketlane/app.py +0 -1
- universal_mcp/applications/scraper/README.md +7 -4
- universal_mcp/applications/scraper/__init__.py +1 -1
- universal_mcp/applications/scraper/app.py +341 -103
- universal_mcp/applications/semrush/README.md +3 -0
- universal_mcp/applications/serpapi/README.md +3 -3
- universal_mcp/applications/serpapi/app.py +14 -14
- universal_mcp/applications/sharepoint/README.md +19 -0
- universal_mcp/applications/sharepoint/app.py +285 -173
- universal_mcp/applications/shopify/app.py +0 -1
- universal_mcp/applications/shortcut/README.md +3 -3
- universal_mcp/applications/slack/README.md +23 -0
- universal_mcp/applications/slack/app.py +79 -48
- universal_mcp/applications/spotify/README.md +3 -3
- universal_mcp/applications/supabase/README.md +3 -3
- universal_mcp/applications/tavily/README.md +4 -4
- universal_mcp/applications/tavily/app.py +4 -4
- universal_mcp/applications/twilio/README.md +15 -0
- universal_mcp/applications/twitter/README.md +92 -89
- universal_mcp/applications/twitter/api_segments/compliance_api.py +13 -15
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +20 -20
- universal_mcp/applications/twitter/api_segments/dm_events_api.py +12 -12
- universal_mcp/applications/twitter/api_segments/likes_api.py +12 -12
- universal_mcp/applications/twitter/api_segments/lists_api.py +37 -39
- universal_mcp/applications/twitter/api_segments/spaces_api.py +24 -24
- universal_mcp/applications/twitter/api_segments/trends_api.py +4 -4
- universal_mcp/applications/twitter/api_segments/tweets_api.py +105 -105
- universal_mcp/applications/twitter/api_segments/usage_api.py +4 -4
- universal_mcp/applications/twitter/api_segments/users_api.py +136 -136
- universal_mcp/applications/twitter/app.py +15 -11
- universal_mcp/applications/whatsapp/README.md +12 -12
- universal_mcp/applications/whatsapp/app.py +66 -67
- universal_mcp/applications/whatsapp/audio.py +39 -35
- universal_mcp/applications/whatsapp/whatsapp.py +176 -154
- universal_mcp/applications/whatsapp_business/README.md +23 -23
- universal_mcp/applications/whatsapp_business/app.py +92 -92
- universal_mcp/applications/yahoo_finance/README.md +17 -0
- universal_mcp/applications/yahoo_finance/__init__.py +1 -0
- universal_mcp/applications/yahoo_finance/app.py +300 -0
- universal_mcp/applications/youtube/README.md +46 -46
- universal_mcp/applications/youtube/app.py +208 -195
- universal_mcp/applications/zenquotes/README.md +1 -1
- universal_mcp/applications/zenquotes/__init__.py +2 -0
- universal_mcp/applications/zenquotes/app.py +5 -5
- {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/METADATA +5 -90
- {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/RECORD +137 -128
- universal_mcp/applications/replicate/README.md +0 -18
- universal_mcp/applications/replicate/__init__.py +0 -1
- universal_mcp/applications/replicate/app.py +0 -493
- universal_mcp/applications/unipile/README.md +0 -28
- universal_mcp/applications/unipile/__init__.py +0 -1
- universal_mcp/applications/unipile/app.py +0 -827
- {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/WHEEL +0 -0
- {universal_mcp_applications-0.1.17.dist-info → universal_mcp_applications-0.1.33.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,827 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from collections.abc import Callable
|
|
3
|
-
from typing import Any, Literal
|
|
4
|
-
|
|
5
|
-
from loguru import logger
|
|
6
|
-
|
|
7
|
-
from universal_mcp.applications.application import APIApplication
|
|
8
|
-
from universal_mcp.integrations import Integration
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class UnipileApp(APIApplication):
|
|
12
|
-
"""
|
|
13
|
-
Application for interacting with the LinkedIn API via Unipile.
|
|
14
|
-
Handles operations related to chats, messages, accounts, posts, and user profiles.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
def __init__(self, integration: Integration) -> None:
|
|
18
|
-
"""
|
|
19
|
-
Initialize the LinkedinApp.
|
|
20
|
-
|
|
21
|
-
Args:
|
|
22
|
-
integration: The integration configuration containing credentials and other settings.
|
|
23
|
-
It is expected that the integration provides the 'x-api-key'
|
|
24
|
-
via headers in `integration.get_credentials()`, e.g.,
|
|
25
|
-
`{"headers": {"x-api-key": "YOUR_API_KEY"}}`.
|
|
26
|
-
"""
|
|
27
|
-
super().__init__(name="unipile", integration=integration)
|
|
28
|
-
|
|
29
|
-
self._base_url = None
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def base_url(self) -> str:
|
|
33
|
-
"""
|
|
34
|
-
A property that lazily constructs and caches the Unipile API base URL using 'subdomain' and 'port' from integration credentials. The URL is built on first access and used by all API methods, raising a ValueError if the required credentials are missing.
|
|
35
|
-
"""
|
|
36
|
-
if not self._base_url:
|
|
37
|
-
credentials = self.integration.get_credentials()
|
|
38
|
-
subdomain = credentials.get("subdomain")
|
|
39
|
-
port = credentials.get("port")
|
|
40
|
-
if not subdomain or not port:
|
|
41
|
-
logger.error(
|
|
42
|
-
"UnipileApp: Missing 'subdomain' or 'port' in integration credentials."
|
|
43
|
-
)
|
|
44
|
-
raise ValueError(
|
|
45
|
-
"Integration credentials must include 'subdomain' and 'port'."
|
|
46
|
-
)
|
|
47
|
-
self._base_url = f"https://{subdomain}.unipile.com:{port}"
|
|
48
|
-
return self._base_url
|
|
49
|
-
|
|
50
|
-
@base_url.setter
|
|
51
|
-
def base_url(self, base_url: str) -> None:
|
|
52
|
-
"""
|
|
53
|
-
Sets or overrides the base URL for Unipile API requests. This setter allows manually changing the endpoint, bypassing the default URL that is dynamically constructed from integration credentials. It is primarily intended for testing against different environments or for custom deployments.
|
|
54
|
-
|
|
55
|
-
Args:
|
|
56
|
-
base_url: The new base URL to set.
|
|
57
|
-
"""
|
|
58
|
-
self._base_url = base_url
|
|
59
|
-
logger.info(f"UnipileApp: Base URL set to {self._base_url}")
|
|
60
|
-
|
|
61
|
-
def _get_headers(self) -> dict[str, str]:
|
|
62
|
-
"""
|
|
63
|
-
Get the headers for Unipile API requests.
|
|
64
|
-
Overrides the base class method to use X-Api-Key.
|
|
65
|
-
"""
|
|
66
|
-
if not self.integration:
|
|
67
|
-
logger.warning(
|
|
68
|
-
"UnipileApp: No integration configured, returning empty headers."
|
|
69
|
-
)
|
|
70
|
-
return {}
|
|
71
|
-
|
|
72
|
-
credentials = self.integration.get_credentials()
|
|
73
|
-
|
|
74
|
-
api_key = (
|
|
75
|
-
credentials.get("api_key")
|
|
76
|
-
or credentials.get("API_KEY")
|
|
77
|
-
or credentials.get("apiKey")
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
if not api_key:
|
|
81
|
-
logger.error(
|
|
82
|
-
"UnipileApp: API key not found in integration credentials for Unipile."
|
|
83
|
-
)
|
|
84
|
-
return { # Or return minimal headers if some calls might not need auth (unlikely for Unipile)
|
|
85
|
-
"Content-Type": "application/json",
|
|
86
|
-
"Cache-Control": "no-cache",
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
logger.debug("UnipileApp: Using X-Api-Key for authentication.")
|
|
90
|
-
return {
|
|
91
|
-
"x-api-key": api_key,
|
|
92
|
-
"Content-Type": "application/json",
|
|
93
|
-
"Cache-Control": "no-cache", # Often good practice for APIs
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
def list_all_chats(
|
|
97
|
-
self,
|
|
98
|
-
unread: bool | None = None,
|
|
99
|
-
cursor: str | None = None,
|
|
100
|
-
before: str | None = None, # ISO 8601 UTC datetime
|
|
101
|
-
after: str | None = None, # ISO 8601 UTC datetime
|
|
102
|
-
limit: int | None = None, # 1-250
|
|
103
|
-
account_type: str | None = None,
|
|
104
|
-
account_id: str | None = None, # Comma-separated list of ids
|
|
105
|
-
) -> dict[str, Any]:
|
|
106
|
-
"""
|
|
107
|
-
Retrieves a paginated list of all chat conversations across linked accounts. Supports filtering by unread status, date range, account provider, and specific account IDs, distinguishing it from functions listing messages within a single chat.
|
|
108
|
-
|
|
109
|
-
Args:
|
|
110
|
-
unread: Filter for unread chats only or read chats only.
|
|
111
|
-
cursor: Pagination cursor for the next page of entries.
|
|
112
|
-
before: Filter for items created before this ISO 8601 UTC datetime (exclusive).
|
|
113
|
-
after: Filter for items created after this ISO 8601 UTC datetime (exclusive).
|
|
114
|
-
limit: Number of items to return (1-250).
|
|
115
|
-
account_type: Filter by provider (e.g., "linkedin").
|
|
116
|
-
account_id: Filter by specific account IDs (comma-separated).
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
A dictionary containing a list of chat objects and a pagination cursor.
|
|
120
|
-
|
|
121
|
-
Raises:
|
|
122
|
-
httpx.HTTPError: If the API request fails.
|
|
123
|
-
|
|
124
|
-
Tags:
|
|
125
|
-
linkedin, chat, list, messaging, api
|
|
126
|
-
"""
|
|
127
|
-
url = f"{self.base_url}/api/v1/chats"
|
|
128
|
-
params: dict[str, Any] = {}
|
|
129
|
-
if unread is not None:
|
|
130
|
-
params["unread"] = unread
|
|
131
|
-
if cursor:
|
|
132
|
-
params["cursor"] = cursor
|
|
133
|
-
if before:
|
|
134
|
-
params["before"] = before
|
|
135
|
-
if after:
|
|
136
|
-
params["after"] = after
|
|
137
|
-
if limit:
|
|
138
|
-
params["limit"] = limit
|
|
139
|
-
if account_type:
|
|
140
|
-
params["account_type"] = account_type
|
|
141
|
-
if account_id:
|
|
142
|
-
params["account_id"] = account_id
|
|
143
|
-
|
|
144
|
-
response = self._get(url, params=params)
|
|
145
|
-
return response.json()
|
|
146
|
-
|
|
147
|
-
def list_chat_messages(
|
|
148
|
-
self,
|
|
149
|
-
chat_id: str,
|
|
150
|
-
cursor: str | None = None,
|
|
151
|
-
before: str | None = None, # ISO 8601 UTC datetime
|
|
152
|
-
after: str | None = None, # ISO 8601 UTC datetime
|
|
153
|
-
limit: int | None = None, # 1-250
|
|
154
|
-
sender_id: str | None = None,
|
|
155
|
-
) -> dict[str, Any]:
|
|
156
|
-
"""
|
|
157
|
-
Retrieves messages from a specific chat identified by `chat_id`. It supports pagination and filtering by date or sender. This function is distinct from `list_all_messages`, which fetches messages across all chats, whereas this method targets the contents of a single conversation.
|
|
158
|
-
|
|
159
|
-
Args:
|
|
160
|
-
chat_id: The ID of the chat to retrieve messages from.
|
|
161
|
-
cursor: Pagination cursor for the next page of entries.
|
|
162
|
-
before: Filter for items created before this ISO 8601 UTC datetime (exclusive).
|
|
163
|
-
after: Filter for items created after this ISO 8601 UTC datetime (exclusive).
|
|
164
|
-
limit: Number of items to return (1-250).
|
|
165
|
-
sender_id: Filter messages from a specific sender ID.
|
|
166
|
-
|
|
167
|
-
Returns:
|
|
168
|
-
A dictionary containing a list of message objects and a pagination cursor.
|
|
169
|
-
|
|
170
|
-
Raises:
|
|
171
|
-
httpx.HTTPError: If the API request fails.
|
|
172
|
-
|
|
173
|
-
Tags:
|
|
174
|
-
linkedin, chat, message, list, messaging, api
|
|
175
|
-
"""
|
|
176
|
-
url = f"{self.base_url}/api/v1/chats/{chat_id}/messages"
|
|
177
|
-
params: dict[str, Any] = {}
|
|
178
|
-
if cursor:
|
|
179
|
-
params["cursor"] = cursor
|
|
180
|
-
if before:
|
|
181
|
-
params["before"] = before
|
|
182
|
-
if after:
|
|
183
|
-
params["after"] = after
|
|
184
|
-
if limit:
|
|
185
|
-
params["limit"] = limit
|
|
186
|
-
if sender_id:
|
|
187
|
-
params["sender_id"] = sender_id
|
|
188
|
-
|
|
189
|
-
response = self._get(url, params=params)
|
|
190
|
-
return response.json()
|
|
191
|
-
|
|
192
|
-
def send_chat_message(
|
|
193
|
-
self,
|
|
194
|
-
chat_id: str,
|
|
195
|
-
text: str,
|
|
196
|
-
) -> dict[str, Any]:
|
|
197
|
-
"""
|
|
198
|
-
Sends a text message to a specific chat via a POST request to the Unipile API. Given a chat ID and text content, it creates a new message within that conversation and returns the API's response, typically containing the new message's ID.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
chat_id: The ID of the chat where the message will be sent.
|
|
202
|
-
text: The text content of the message.
|
|
203
|
-
attachments: Optional list of attachment objects to include with the message.
|
|
204
|
-
|
|
205
|
-
Returns:
|
|
206
|
-
A dictionary containing the ID of the sent message.
|
|
207
|
-
|
|
208
|
-
Raises:
|
|
209
|
-
httpx.HTTPError: If the API request fails.
|
|
210
|
-
|
|
211
|
-
Tags:
|
|
212
|
-
linkedin, chat, message, send, create, messaging, api
|
|
213
|
-
"""
|
|
214
|
-
url = f"{self.base_url}/api/v1/chats/{chat_id}/messages"
|
|
215
|
-
payload: dict[str, Any] = {"text": text}
|
|
216
|
-
|
|
217
|
-
response = self._post(url, data=payload)
|
|
218
|
-
return response.json()
|
|
219
|
-
|
|
220
|
-
def retrieve_chat(
|
|
221
|
-
self, chat_id: str, account_id: str | None = None
|
|
222
|
-
) -> dict[str, Any]:
|
|
223
|
-
"""
|
|
224
|
-
Retrieves a single chat by its unique Unipile or provider-specific ID. The `account_id` is required when using a provider ID to specify the correct context. This function fetches one specific chat, unlike `list_all_chats` which retrieves a collection of chats.
|
|
225
|
-
|
|
226
|
-
Args:
|
|
227
|
-
chat_id: The Unipile or provider ID of the chat.
|
|
228
|
-
account_id: Mandatory if the chat_id is a provider ID. Specifies the account context.
|
|
229
|
-
|
|
230
|
-
Returns:
|
|
231
|
-
A dictionary containing the chat object details.
|
|
232
|
-
|
|
233
|
-
Raises:
|
|
234
|
-
httpx.HTTPError: If the API request fails.
|
|
235
|
-
|
|
236
|
-
Tags:
|
|
237
|
-
linkedin, chat, retrieve, get, messaging, api
|
|
238
|
-
"""
|
|
239
|
-
url = f"{self.base_url}/api/v1/chats/{chat_id}"
|
|
240
|
-
params: dict[str, Any] = {}
|
|
241
|
-
if account_id:
|
|
242
|
-
params["account_id"] = account_id
|
|
243
|
-
|
|
244
|
-
response = self._get(url, params=params)
|
|
245
|
-
return response.json()
|
|
246
|
-
|
|
247
|
-
def list_all_messages(
|
|
248
|
-
self,
|
|
249
|
-
cursor: str | None = None,
|
|
250
|
-
before: str | None = None, # ISO 8601 UTC datetime
|
|
251
|
-
after: str | None = None, # ISO 8601 UTC datetime
|
|
252
|
-
limit: int | None = None, # 1-250
|
|
253
|
-
sender_id: str | None = None,
|
|
254
|
-
account_id: str | None = None,
|
|
255
|
-
) -> dict[str, Any]:
|
|
256
|
-
"""
|
|
257
|
-
Retrieves a paginated list of messages from all chats associated with the account(s). Unlike `list_chat_messages` which targets a specific conversation, this function provides a global message view, filterable by sender, account, and date range.
|
|
258
|
-
|
|
259
|
-
Args:
|
|
260
|
-
cursor: Pagination cursor.
|
|
261
|
-
before: Filter for items created before this ISO 8601 UTC datetime.
|
|
262
|
-
after: Filter for items created after this ISO 8601 UTC datetime.
|
|
263
|
-
limit: Number of items to return (1-250).
|
|
264
|
-
sender_id: Filter messages from a specific sender.
|
|
265
|
-
account_id: Filter messages from a specific linked account.
|
|
266
|
-
|
|
267
|
-
Returns:
|
|
268
|
-
A dictionary containing a list of message objects and a pagination cursor.
|
|
269
|
-
|
|
270
|
-
Raises:
|
|
271
|
-
httpx.HTTPError: If the API request fails.
|
|
272
|
-
|
|
273
|
-
Tags:
|
|
274
|
-
linkedin, message, list, all_messages, messaging, api
|
|
275
|
-
"""
|
|
276
|
-
url = f"{self.base_url}/api/v1/messages"
|
|
277
|
-
params: dict[str, Any] = {}
|
|
278
|
-
if cursor:
|
|
279
|
-
params["cursor"] = cursor
|
|
280
|
-
if before:
|
|
281
|
-
params["before"] = before
|
|
282
|
-
if after:
|
|
283
|
-
params["after"] = after
|
|
284
|
-
if limit:
|
|
285
|
-
params["limit"] = limit
|
|
286
|
-
if sender_id:
|
|
287
|
-
params["sender_id"] = sender_id
|
|
288
|
-
if account_id:
|
|
289
|
-
params["account_id"] = account_id
|
|
290
|
-
|
|
291
|
-
response = self._get(url, params=params)
|
|
292
|
-
return response.json()
|
|
293
|
-
|
|
294
|
-
def list_all_accounts(
|
|
295
|
-
self,
|
|
296
|
-
cursor: str | None = None,
|
|
297
|
-
limit: int | None = None, # 1-259 according to spec
|
|
298
|
-
) -> dict[str, Any]:
|
|
299
|
-
"""
|
|
300
|
-
Retrieves a paginated list of all social media accounts linked to the Unipile service. This is crucial for obtaining the `account_id` required by other methods to specify which user account should perform an action, like sending a message or retrieving user-specific posts.
|
|
301
|
-
|
|
302
|
-
Args:
|
|
303
|
-
cursor: Pagination cursor.
|
|
304
|
-
limit: Number of items to return (1-259).
|
|
305
|
-
|
|
306
|
-
Returns:
|
|
307
|
-
A dictionary containing a list of account objects and a pagination cursor.
|
|
308
|
-
|
|
309
|
-
Raises:
|
|
310
|
-
httpx.HTTPError: If the API request fails.
|
|
311
|
-
|
|
312
|
-
Tags:
|
|
313
|
-
linkedin, account, list, unipile, api, important
|
|
314
|
-
"""
|
|
315
|
-
url = f"{self.base_url}/api/v1/accounts"
|
|
316
|
-
params: dict[str, Any] = {}
|
|
317
|
-
if cursor:
|
|
318
|
-
params["cursor"] = cursor
|
|
319
|
-
if limit:
|
|
320
|
-
params["limit"] = limit
|
|
321
|
-
|
|
322
|
-
response = self._get(url, params=params)
|
|
323
|
-
return response.json()
|
|
324
|
-
|
|
325
|
-
def retrieve_linked_account(
|
|
326
|
-
self,
|
|
327
|
-
account_id: str,
|
|
328
|
-
) -> dict[str, Any]:
|
|
329
|
-
"""
|
|
330
|
-
Retrieves the details of a specific account linked to the Unipile service by its unique ID. This function fetches metadata about the connection itself (e.g., a linked LinkedIn account), distinguishing it from functions that fetch end-user profiles from the external platform.
|
|
331
|
-
|
|
332
|
-
Args:
|
|
333
|
-
account_id: The ID of the account to retrieve.
|
|
334
|
-
|
|
335
|
-
Returns:
|
|
336
|
-
A dictionary containing the account object details.
|
|
337
|
-
|
|
338
|
-
Raises:
|
|
339
|
-
httpx.HTTPError: If the API request fails.
|
|
340
|
-
|
|
341
|
-
Tags:
|
|
342
|
-
linkedin, account, retrieve, get, unipile, api, important
|
|
343
|
-
"""
|
|
344
|
-
url = f"{self.base_url}/api/v1/accounts/{account_id}"
|
|
345
|
-
response = self._get(url)
|
|
346
|
-
return response.json()
|
|
347
|
-
|
|
348
|
-
def list_profile_posts(
|
|
349
|
-
self,
|
|
350
|
-
identifier: str, # User or Company provider internal ID
|
|
351
|
-
account_id: str, # Account to perform the request from (REQUIRED)
|
|
352
|
-
cursor: str | None = None,
|
|
353
|
-
limit: int | None = None, # 1-100 (spec says max 250)
|
|
354
|
-
is_company: bool | None = None,
|
|
355
|
-
) -> dict[str, Any]:
|
|
356
|
-
"""
|
|
357
|
-
Retrieves a paginated list of posts from a specific user or company profile using their provider ID. A Unipile account is required for authorization, and the `is_company` flag must be used to differentiate between entity types.
|
|
358
|
-
|
|
359
|
-
Args:
|
|
360
|
-
identifier: The entity's provider internal ID (LinkedIn ID).
|
|
361
|
-
account_id: The ID of the Unipile account to perform the request from (REQUIRED).
|
|
362
|
-
cursor: Pagination cursor.
|
|
363
|
-
limit: Number of items to return (1-100, as per Unipile example, though spec allows up to 250).
|
|
364
|
-
is_company: Boolean indicating if the identifier is for a company.
|
|
365
|
-
|
|
366
|
-
Returns:
|
|
367
|
-
A dictionary containing a list of post objects and pagination details.
|
|
368
|
-
|
|
369
|
-
Raises:
|
|
370
|
-
httpx.HTTPError: If the API request fails.
|
|
371
|
-
|
|
372
|
-
Tags:
|
|
373
|
-
linkedin, post, list, user_posts, company_posts, content, api, important
|
|
374
|
-
"""
|
|
375
|
-
url = f"{self.base_url}/api/v1/users/{identifier}/posts"
|
|
376
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
377
|
-
if cursor:
|
|
378
|
-
params["cursor"] = cursor
|
|
379
|
-
if limit:
|
|
380
|
-
params["limit"] = limit
|
|
381
|
-
if is_company is not None:
|
|
382
|
-
params["is_company"] = is_company
|
|
383
|
-
|
|
384
|
-
response = self._get(url, params=params)
|
|
385
|
-
return response.json()
|
|
386
|
-
|
|
387
|
-
def retrieve_own_profile(
|
|
388
|
-
self,
|
|
389
|
-
account_id: str,
|
|
390
|
-
) -> dict[str, Any]:
|
|
391
|
-
"""
|
|
392
|
-
Retrieves the profile details for the user associated with the specified Unipile account ID. This function targets the API's 'me' endpoint to fetch the current authenticated user's profile, distinct from fetching profiles of other users via the `retrieve_profile` function.
|
|
393
|
-
|
|
394
|
-
Args:
|
|
395
|
-
account_id: The ID of the Unipile account to use for retrieving the profile (REQUIRED).
|
|
396
|
-
|
|
397
|
-
Returns:
|
|
398
|
-
A dictionary containing the user's profile details.
|
|
399
|
-
|
|
400
|
-
Raises:
|
|
401
|
-
httpx.HTTPError: If the API request fails.
|
|
402
|
-
|
|
403
|
-
Tags:
|
|
404
|
-
linkedin, user, profile, me, retrieve, get, api
|
|
405
|
-
"""
|
|
406
|
-
url = f"{self.base_url}/api/v1/users/me"
|
|
407
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
408
|
-
response = self._get(url, params=params)
|
|
409
|
-
return response.json()
|
|
410
|
-
|
|
411
|
-
def retrieve_post(
|
|
412
|
-
self,
|
|
413
|
-
post_id: str,
|
|
414
|
-
account_id: str,
|
|
415
|
-
) -> dict[str, Any]:
|
|
416
|
-
"""
|
|
417
|
-
Fetches the details of a specific post by its unique ID. The request is performed using the provided `account_id` for authorization, returning the full post object. This differs from `list_user_posts` which retrieves multiple posts for a specific user or company.
|
|
418
|
-
|
|
419
|
-
Args:
|
|
420
|
-
post_id: The ID of the post to retrieve.
|
|
421
|
-
account_id: The ID of the Unipile account to perform the request from (REQUIRED).
|
|
422
|
-
|
|
423
|
-
Returns:
|
|
424
|
-
A dictionary containing the post details.
|
|
425
|
-
|
|
426
|
-
Raises:
|
|
427
|
-
httpx.HTTPError: If the API request fails.
|
|
428
|
-
|
|
429
|
-
Tags:
|
|
430
|
-
linkedin, post, retrieve, get, content, api, important
|
|
431
|
-
"""
|
|
432
|
-
url = f"{self.base_url}/api/v1/posts/{post_id}"
|
|
433
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
434
|
-
response = self._get(url, params=params)
|
|
435
|
-
return response.json()
|
|
436
|
-
|
|
437
|
-
def list_post_comments(
|
|
438
|
-
self,
|
|
439
|
-
post_id: str,
|
|
440
|
-
account_id: str,
|
|
441
|
-
comment_id: str | None = None,
|
|
442
|
-
cursor: str | None = None,
|
|
443
|
-
limit: int | None = None,
|
|
444
|
-
) -> dict[str, Any]:
|
|
445
|
-
"""
|
|
446
|
-
Fetches comments for a specific post. By providing an optional `comment_id`, the function retrieves replies to that comment instead of top-level comments. This read-only operation contrasts with `create_post_comment`, which adds new comments, and `list_post_reactions`, which retrieves likes.
|
|
447
|
-
|
|
448
|
-
Args:
|
|
449
|
-
post_id: The social ID of the post.
|
|
450
|
-
account_id: The ID of the Unipile account to perform the request from (REQUIRED).
|
|
451
|
-
comment_id: If provided, retrieves replies to this comment ID instead of top-level comments.
|
|
452
|
-
cursor: Pagination cursor.
|
|
453
|
-
limit: Number of comments to return. (OpenAPI spec shows type string, passed as string if provided).
|
|
454
|
-
|
|
455
|
-
Returns:
|
|
456
|
-
A dictionary containing a list of comment objects and pagination details.
|
|
457
|
-
|
|
458
|
-
Raises:
|
|
459
|
-
httpx.HTTPError: If the API request fails.
|
|
460
|
-
|
|
461
|
-
Tags:
|
|
462
|
-
linkedin, post, comment, list, content, api, important
|
|
463
|
-
"""
|
|
464
|
-
url = f"{self.base_url}/api/v1/posts/{post_id}/comments"
|
|
465
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
466
|
-
if cursor:
|
|
467
|
-
params["cursor"] = cursor
|
|
468
|
-
if limit is not None:
|
|
469
|
-
params["limit"] = str(limit)
|
|
470
|
-
if comment_id:
|
|
471
|
-
params["comment_id"] = comment_id
|
|
472
|
-
|
|
473
|
-
response = self._get(url, params=params)
|
|
474
|
-
return response.json()
|
|
475
|
-
|
|
476
|
-
def create_post(
|
|
477
|
-
self,
|
|
478
|
-
account_id: str,
|
|
479
|
-
text: str,
|
|
480
|
-
mentions: list[dict[str, Any]] | None = None,
|
|
481
|
-
external_link: str | None = None,
|
|
482
|
-
) -> dict[str, Any]:
|
|
483
|
-
"""
|
|
484
|
-
Publishes a new post to LinkedIn via the Unipile API from a specified account. The post's content can include text, user mentions, and an external link displayed as a card. This function is for creating top-level posts, distinct from `create_post_comment` which replies to existing posts.
|
|
485
|
-
|
|
486
|
-
Args:
|
|
487
|
-
account_id: The ID of the Unipile account that will author the post (added as query parameter).
|
|
488
|
-
text: The main text content of the post.
|
|
489
|
-
mentions: Optional list of dictionaries, each representing a mention.
|
|
490
|
-
Example: `[{"entity_urn": "urn:li:person:...", "start_index": 0, "end_index": 5}]`
|
|
491
|
-
external_link: Optional string, an external URL that should be displayed within a card.
|
|
492
|
-
|
|
493
|
-
Returns:
|
|
494
|
-
A dictionary containing the ID of the created post.
|
|
495
|
-
|
|
496
|
-
Raises:
|
|
497
|
-
httpx.HTTPError: If the API request fails.
|
|
498
|
-
|
|
499
|
-
Tags:
|
|
500
|
-
linkedin, post, create, share, content, api, important
|
|
501
|
-
"""
|
|
502
|
-
url = f"{self.base_url}/api/v1/posts"
|
|
503
|
-
|
|
504
|
-
params: dict[str, str] = {
|
|
505
|
-
"account_id": account_id,
|
|
506
|
-
"text": text,
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
if mentions:
|
|
510
|
-
params["mentions"] = mentions
|
|
511
|
-
if external_link:
|
|
512
|
-
params["external_link"] = external_link
|
|
513
|
-
|
|
514
|
-
response = self._post(url, data=params)
|
|
515
|
-
return response.json()
|
|
516
|
-
|
|
517
|
-
def list_content_reactions(
|
|
518
|
-
self,
|
|
519
|
-
post_id: str,
|
|
520
|
-
account_id: str,
|
|
521
|
-
comment_id: str | None = None,
|
|
522
|
-
cursor: str | None = None,
|
|
523
|
-
limit: int | None = None,
|
|
524
|
-
) -> dict[str, Any]:
|
|
525
|
-
"""
|
|
526
|
-
Retrieves a paginated list of reactions for a given post or, optionally, a specific comment. This read-only operation uses the provided `account_id` for the request, distinguishing it from `add_reaction_to_post` which creates new reactions.
|
|
527
|
-
|
|
528
|
-
Args:
|
|
529
|
-
post_id: The social ID of the post.
|
|
530
|
-
account_id: The ID of the Unipile account to perform the request from .
|
|
531
|
-
comment_id: If provided, retrieves reactions for this comment ID.
|
|
532
|
-
cursor: Pagination cursor.
|
|
533
|
-
limit: Number of reactions to return (1-100, spec max 250).
|
|
534
|
-
|
|
535
|
-
Returns:
|
|
536
|
-
A dictionary containing a list of reaction objects and pagination details.
|
|
537
|
-
|
|
538
|
-
Raises:
|
|
539
|
-
httpx.HTTPError: If the API request fails.
|
|
540
|
-
|
|
541
|
-
Tags:
|
|
542
|
-
linkedin, post, reaction, list, like, content, api
|
|
543
|
-
"""
|
|
544
|
-
url = f"{self.base_url}/api/v1/posts/{post_id}/reactions"
|
|
545
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
546
|
-
if cursor:
|
|
547
|
-
params["cursor"] = cursor
|
|
548
|
-
if limit:
|
|
549
|
-
params["limit"] = limit
|
|
550
|
-
if comment_id:
|
|
551
|
-
params["comment_id"] = comment_id
|
|
552
|
-
|
|
553
|
-
response = self._get(url, params=params)
|
|
554
|
-
return response.json()
|
|
555
|
-
|
|
556
|
-
def create_post_comment(
|
|
557
|
-
self,
|
|
558
|
-
post_social_id: str,
|
|
559
|
-
account_id: str,
|
|
560
|
-
text: str,
|
|
561
|
-
comment_id: str | None = None, # If provided, replies to a specific comment
|
|
562
|
-
mentions_body: list[dict[str, Any]] | None = None,
|
|
563
|
-
) -> dict[str, Any]:
|
|
564
|
-
"""
|
|
565
|
-
Publishes a comment on a specified post. By providing an optional `comment_id`, it creates a threaded reply to an existing comment instead of a new top-level one. This function's dual capability distinguishes it from `list_post_comments`, which only retrieves comments and their replies.
|
|
566
|
-
|
|
567
|
-
Args:
|
|
568
|
-
post_social_id: The social ID of the post to comment on.
|
|
569
|
-
account_id: The ID of the Unipile account performing the comment.
|
|
570
|
-
text: The text content of the comment (passed as a query parameter).
|
|
571
|
-
Supports Unipile's mention syntax like "Hey {{0}}".
|
|
572
|
-
comment_id: Optional ID of a specific comment to reply to instead of commenting on the post.
|
|
573
|
-
mentions_body: Optional list of mention objects for the request body if needed.
|
|
574
|
-
|
|
575
|
-
Returns:
|
|
576
|
-
A dictionary, likely confirming comment creation. (Structure depends on actual API response)
|
|
577
|
-
|
|
578
|
-
Raises:
|
|
579
|
-
httpx.HTTPError: If the API request fails.
|
|
580
|
-
|
|
581
|
-
Tags:
|
|
582
|
-
linkedin, post, comment, create, content, api, important
|
|
583
|
-
"""
|
|
584
|
-
url = f"{self.base_url}/api/v1/posts/{post_social_id}/comments"
|
|
585
|
-
params: dict[str, Any] = {
|
|
586
|
-
"account_id": account_id,
|
|
587
|
-
"text": text,
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
if comment_id:
|
|
591
|
-
params["comment_id"] = comment_id
|
|
592
|
-
|
|
593
|
-
if mentions_body:
|
|
594
|
-
params = {"mentions": mentions_body}
|
|
595
|
-
|
|
596
|
-
response = self._post(url, data=params)
|
|
597
|
-
|
|
598
|
-
try:
|
|
599
|
-
return response.json()
|
|
600
|
-
except json.JSONDecodeError:
|
|
601
|
-
return {
|
|
602
|
-
"status": response.status_code,
|
|
603
|
-
"message": "Comment action processed.",
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
def create_reaction(
|
|
607
|
-
self,
|
|
608
|
-
post_social_id: str,
|
|
609
|
-
reaction_type: Literal[
|
|
610
|
-
"like", "celebrate", "love", "insightful", "funny", "support"
|
|
611
|
-
],
|
|
612
|
-
account_id: str,
|
|
613
|
-
comment_id: str | None = None,
|
|
614
|
-
) -> dict[str, Any]:
|
|
615
|
-
"""
|
|
616
|
-
Adds a specified reaction (e.g., 'like', 'love') to a LinkedIn post or, optionally, to a specific comment. This function performs a POST request to create the reaction, differentiating it from `list_post_reactions` which only retrieves existing ones.
|
|
617
|
-
|
|
618
|
-
Args:
|
|
619
|
-
post_social_id: The social ID of the post or comment to react to.
|
|
620
|
-
reaction_type: The type of reaction .
|
|
621
|
-
account_id: Account ID of the Unipile account performing the reaction.
|
|
622
|
-
comment_id: Optional ID of a specific comment to react to instead of the post.
|
|
623
|
-
|
|
624
|
-
Returns:
|
|
625
|
-
A dictionary, likely confirming the reaction. (Structure depends on actual API response)
|
|
626
|
-
|
|
627
|
-
Raises:
|
|
628
|
-
httpx.HTTPError: If the API request fails.
|
|
629
|
-
|
|
630
|
-
Tags:
|
|
631
|
-
linkedin, post, reaction, create, like, content, api, important
|
|
632
|
-
"""
|
|
633
|
-
url = f"{self.base_url}/api/v1/posts/reaction"
|
|
634
|
-
|
|
635
|
-
params: dict[str, str] = {
|
|
636
|
-
"account_id": account_id,
|
|
637
|
-
"post_id": post_social_id,
|
|
638
|
-
"reaction_type": reaction_type,
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
if comment_id:
|
|
642
|
-
params["comment_id"] = comment_id
|
|
643
|
-
|
|
644
|
-
response = self._post(url, data=params)
|
|
645
|
-
|
|
646
|
-
try:
|
|
647
|
-
return response.json()
|
|
648
|
-
except json.JSONDecodeError:
|
|
649
|
-
return {
|
|
650
|
-
"status": response.status_code,
|
|
651
|
-
"message": "Reaction action processed.",
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
def search(
|
|
655
|
-
self,
|
|
656
|
-
account_id: str,
|
|
657
|
-
category: Literal["people", "companies", "posts", "jobs"] = "posts",
|
|
658
|
-
api: Literal["classic", "sales_navigator"] = "classic",
|
|
659
|
-
cursor: str | None = None,
|
|
660
|
-
limit: int | None = None,
|
|
661
|
-
keywords: str | None = None,
|
|
662
|
-
sort_by: Literal["relevance", "date"] | None = None,
|
|
663
|
-
date_posted: Literal["past_day", "past_week", "past_month"] | None = None,
|
|
664
|
-
content_type: Literal[
|
|
665
|
-
"videos", "images", "live_videos", "collaborative_articles", "documents"
|
|
666
|
-
]
|
|
667
|
-
| None = None,
|
|
668
|
-
posted_by: dict[str, Any] | None = None,
|
|
669
|
-
mentioning: dict[str, Any] | None = None,
|
|
670
|
-
author: dict[str, Any] | None = None,
|
|
671
|
-
# People search specific parameters
|
|
672
|
-
location: list[str] | None = None,
|
|
673
|
-
industry: list[str] | None = None,
|
|
674
|
-
company: list[str] | None = None,
|
|
675
|
-
past_company: list[str] | None = None,
|
|
676
|
-
school: list[str] | None = None,
|
|
677
|
-
# Company search specific parameters
|
|
678
|
-
headcount: list[dict[str, int]] | None = None,
|
|
679
|
-
# Job search specific parameters
|
|
680
|
-
job_type: list[str] | None = None,
|
|
681
|
-
minimum_salary: dict[str, Any] | None = None,
|
|
682
|
-
# URL search
|
|
683
|
-
search_url: str | None = None,
|
|
684
|
-
) -> dict[str, Any]:
|
|
685
|
-
"""
|
|
686
|
-
Performs a comprehensive LinkedIn search for people, companies, posts, or jobs using granular filters like keywords and location. Alternatively, it can execute a search from a direct LinkedIn URL. Supports pagination and targets either the classic or Sales Navigator API.
|
|
687
|
-
|
|
688
|
-
Args:
|
|
689
|
-
account_id: The ID of the Unipile account to perform the search from (REQUIRED).
|
|
690
|
-
category: Type of search to perform - "people", "companies", "posts", or "jobs".
|
|
691
|
-
api: Which LinkedIn API to use - "classic" or "sales_navigator".
|
|
692
|
-
cursor: Pagination cursor for the next page of entries.
|
|
693
|
-
limit: Number of items to return (up to 50 for Classic search).
|
|
694
|
-
keywords: Keywords to search for.
|
|
695
|
-
sort_by: How to sort the results, e.g., "relevance" or "date".
|
|
696
|
-
date_posted: Filter posts by when they were posted (posts only).
|
|
697
|
-
content_type: Filter by the type of content in the post (posts only).
|
|
698
|
-
posted_by: Dictionary to filter by who posted (posts only).
|
|
699
|
-
location: Location filter for people/company search (array of strings).
|
|
700
|
-
industry: Industry filter for people/company search (array of strings).
|
|
701
|
-
company: Company filter for people search (array of strings).
|
|
702
|
-
past_company: Past company filter for people search (array of strings).
|
|
703
|
-
school: School filter for people search (array of strings).
|
|
704
|
-
headcount: Company size filter for company search (array of objects with min/max numbers).
|
|
705
|
-
job_type: Job type filter for job search (array of strings).
|
|
706
|
-
minimum_salary: Minimum salary filter for job search (object with currency and value). Example:
|
|
707
|
-
minimum_salary = {
|
|
708
|
-
"currency": "USD",
|
|
709
|
-
"value": 80
|
|
710
|
-
}
|
|
711
|
-
search_url: Direct LinkedIn search URL to use instead of building parameters.
|
|
712
|
-
|
|
713
|
-
Returns:
|
|
714
|
-
A dictionary containing search results and pagination details.
|
|
715
|
-
|
|
716
|
-
Raises:
|
|
717
|
-
httpx.HTTPError: If the API request fails.
|
|
718
|
-
|
|
719
|
-
Tags:
|
|
720
|
-
linkedin, search, people, companies, posts, jobs, api, important
|
|
721
|
-
"""
|
|
722
|
-
url = f"{self.base_url}/api/v1/linkedin/search"
|
|
723
|
-
|
|
724
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
725
|
-
if cursor:
|
|
726
|
-
params["cursor"] = cursor
|
|
727
|
-
if limit is not None:
|
|
728
|
-
params["limit"] = limit
|
|
729
|
-
|
|
730
|
-
payload: dict[str, Any] = {"api": api, "category": category}
|
|
731
|
-
|
|
732
|
-
# Add search URL if provided (takes precedence over other parameters)
|
|
733
|
-
if search_url:
|
|
734
|
-
payload["search_url"] = search_url
|
|
735
|
-
else:
|
|
736
|
-
# Add common parameters
|
|
737
|
-
common_params = {
|
|
738
|
-
"keywords": keywords,
|
|
739
|
-
"sort_by": sort_by,
|
|
740
|
-
}
|
|
741
|
-
payload.update({k: v for k, v in common_params.items() if v is not None})
|
|
742
|
-
|
|
743
|
-
# Category-specific parameters
|
|
744
|
-
category_params = {
|
|
745
|
-
"posts": {
|
|
746
|
-
"date_posted": date_posted,
|
|
747
|
-
"content_type": content_type,
|
|
748
|
-
"posted_by": posted_by,
|
|
749
|
-
},
|
|
750
|
-
"people": {
|
|
751
|
-
"location": location,
|
|
752
|
-
"industry": industry,
|
|
753
|
-
"company": company,
|
|
754
|
-
"past_company": past_company,
|
|
755
|
-
"school": school,
|
|
756
|
-
},
|
|
757
|
-
"companies": {
|
|
758
|
-
"location": location,
|
|
759
|
-
"industry": industry,
|
|
760
|
-
"headcount": headcount,
|
|
761
|
-
},
|
|
762
|
-
"jobs": {
|
|
763
|
-
"location": location,
|
|
764
|
-
"job_type": job_type,
|
|
765
|
-
"minimum_salary": minimum_salary,
|
|
766
|
-
},
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if category in category_params:
|
|
770
|
-
payload.update(
|
|
771
|
-
{
|
|
772
|
-
k: v
|
|
773
|
-
for k, v in category_params[category].items()
|
|
774
|
-
if v is not None
|
|
775
|
-
}
|
|
776
|
-
)
|
|
777
|
-
|
|
778
|
-
response = self._post(url, params=params, data=payload)
|
|
779
|
-
return self._handle_response(response)
|
|
780
|
-
|
|
781
|
-
def retrieve_user_profile(
|
|
782
|
-
self,
|
|
783
|
-
identifier: str,
|
|
784
|
-
account_id: str,
|
|
785
|
-
) -> dict[str, Any]:
|
|
786
|
-
"""
|
|
787
|
-
Retrieves a specific LinkedIn user's profile using their public or internal ID. This is distinct from `retrieve_own_profile`, which retrieves the profile associated with the Unipile account performing the request.
|
|
788
|
-
|
|
789
|
-
Args:
|
|
790
|
-
identifier: Can be the provider's internal id OR the provider's public id of the requested user.For example, for https://www.linkedin.com/in/manojbajaj95/, the identifier is "manojbajaj95".
|
|
791
|
-
|
|
792
|
-
account_id: The ID of the Unipile account to perform the request from (REQUIRED).
|
|
793
|
-
|
|
794
|
-
Returns:
|
|
795
|
-
A dictionary containing the user's profile details.
|
|
796
|
-
|
|
797
|
-
Raises:
|
|
798
|
-
httpx.HTTPError: If the API request fails.
|
|
799
|
-
|
|
800
|
-
Tags:
|
|
801
|
-
linkedin, user, profile, retrieve, get, api, important
|
|
802
|
-
"""
|
|
803
|
-
url = f"{self.base_url}/api/v1/users/{identifier}"
|
|
804
|
-
params: dict[str, Any] = {"account_id": account_id}
|
|
805
|
-
response = self._get(url, params=params)
|
|
806
|
-
return self._handle_response(response)
|
|
807
|
-
|
|
808
|
-
def list_tools(self) -> list[Callable]:
|
|
809
|
-
return [
|
|
810
|
-
self.list_all_chats,
|
|
811
|
-
self.list_chat_messages,
|
|
812
|
-
self.send_chat_message,
|
|
813
|
-
self.retrieve_chat,
|
|
814
|
-
self.list_all_messages,
|
|
815
|
-
self.list_all_accounts,
|
|
816
|
-
self.retrieve_linked_account,
|
|
817
|
-
self.list_profile_posts,
|
|
818
|
-
self.retrieve_own_profile,
|
|
819
|
-
self.retrieve_user_profile,
|
|
820
|
-
self.retrieve_post,
|
|
821
|
-
self.list_post_comments,
|
|
822
|
-
self.create_post,
|
|
823
|
-
self.list_content_reactions,
|
|
824
|
-
self.create_post_comment,
|
|
825
|
-
self.create_reaction,
|
|
826
|
-
self.search,
|
|
827
|
-
]
|