linkedapi 1.3.8__tar.gz → 1.3.10__tar.gz

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 (108) hide show
  1. {linkedapi-1.3.8 → linkedapi-1.3.10}/PKG-INFO +1 -1
  2. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/__init__.py +3 -1
  3. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/client.py +3 -0
  4. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/errors.py +2 -0
  5. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/__init__.py +2 -0
  6. linkedapi-1.3.10/linkedapi/operations/retrieve_profile_viewers.py +15 -0
  7. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/__init__.py +14 -0
  8. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/jobs.py +48 -1
  9. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/message.py +3 -0
  10. linkedapi-1.3.10/linkedapi/types/profile_viewers.py +82 -0
  11. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/webhooks.py +3 -0
  12. {linkedapi-1.3.8 → linkedapi-1.3.10}/pyproject.toml +1 -1
  13. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_errors.py +1 -0
  14. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_operations.py +2 -1
  15. {linkedapi-1.3.8 → linkedapi-1.3.10}/.github/workflows/publish.yaml +0 -0
  16. {linkedapi-1.3.8 → linkedapi-1.3.10}/.gitignore +0 -0
  17. {linkedapi-1.3.8 → linkedapi-1.3.10}/LICENSE +0 -0
  18. {linkedapi-1.3.8 → linkedapi-1.3.10}/README.md +0 -0
  19. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/__init__.py +0 -0
  20. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/accounts.py +0 -0
  21. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/admin.py +0 -0
  22. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/http_client.py +0 -0
  23. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/limits.py +0 -0
  24. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/subscription.py +0 -0
  25. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/admin/webhooks.py +0 -0
  26. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/config.py +0 -0
  27. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/core/__init__.py +0 -0
  28. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/core/operation.py +0 -0
  29. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/core/polling.py +0 -0
  30. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/http/__init__.py +0 -0
  31. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/http/base.py +0 -0
  32. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/http/linked_api_http_client.py +0 -0
  33. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/__init__.py +0 -0
  34. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/array.py +0 -0
  35. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/base.py +0 -0
  36. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/send_message.py +0 -0
  37. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/simple.py +0 -0
  38. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/then.py +0 -0
  39. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/mappers/void.py +0 -0
  40. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/accept_invitation.py +0 -0
  41. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/check_connection_status.py +0 -0
  42. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/comment_on_post.py +0 -0
  43. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/create_post.py +0 -0
  44. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/custom_workflow.py +0 -0
  45. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/fetch_company.py +0 -0
  46. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/fetch_job.py +0 -0
  47. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/fetch_person.py +0 -0
  48. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/fetch_post.py +0 -0
  49. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/ignore_invitation.py +0 -0
  50. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/manage_conversation.py +0 -0
  51. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_fetch_company.py +0 -0
  52. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_fetch_person.py +0 -0
  53. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_manage_conversation.py +0 -0
  54. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_search_companies.py +0 -0
  55. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_search_people.py +0 -0
  56. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_send_message.py +0 -0
  57. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_sync_conversation.py +0 -0
  58. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/nv_sync_inbox.py +0 -0
  59. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/react_to_comment.py +0 -0
  60. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/react_to_post.py +0 -0
  61. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/remove_connection.py +0 -0
  62. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/reply_to_comment.py +0 -0
  63. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_connections.py +0 -0
  64. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_feed.py +0 -0
  65. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_invitations.py +0 -0
  66. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_pending_requests.py +0 -0
  67. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_performance.py +0 -0
  68. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/retrieve_ssi.py +0 -0
  69. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/search_companies.py +0 -0
  70. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/search_jobs.py +0 -0
  71. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/search_people.py +0 -0
  72. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/send_connection_request.py +0 -0
  73. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/send_message.py +0 -0
  74. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/sync_conversation.py +0 -0
  75. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/sync_inbox.py +0 -0
  76. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/sync_network.py +0 -0
  77. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/operations/withdraw_connection_request.py +0 -0
  78. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/py.typed +0 -0
  79. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/account.py +0 -0
  80. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/admin/__init__.py +0 -0
  81. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/admin/accounts.py +0 -0
  82. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/admin/config.py +0 -0
  83. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/admin/limits.py +0 -0
  84. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/admin/subscription.py +0 -0
  85. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/base.py +0 -0
  86. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/company.py +0 -0
  87. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/connection.py +0 -0
  88. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/feed.py +0 -0
  89. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/network.py +0 -0
  90. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/params.py +0 -0
  91. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/person.py +0 -0
  92. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/post.py +0 -0
  93. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/responses.py +0 -0
  94. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/search_companies.py +0 -0
  95. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/search_people.py +0 -0
  96. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/statistics.py +0 -0
  97. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/types/workflow.py +0 -0
  98. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/webhooks/__init__.py +0 -0
  99. {linkedapi-1.3.8 → linkedapi-1.3.10}/linkedapi/webhooks/parse.py +0 -0
  100. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/conftest.py +0 -0
  101. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_admin.py +0 -0
  102. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_direct_methods.py +0 -0
  103. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_http_client.py +0 -0
  104. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_mappers.py +0 -0
  105. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_models.py +0 -0
  106. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_polling.py +0 -0
  107. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_webhooks.py +0 -0
  108. {linkedapi-1.3.8 → linkedapi-1.3.10}/tests/test_working_hours_contract.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: linkedapi
3
- Version: 1.3.8
3
+ Version: 1.3.10
4
4
  Summary: Official synchronous Python SDK for Linked API.
5
5
  Project-URL: Homepage, https://linkedapi.io
6
6
  Project-URL: Repository, https://github.com/Linked-API/linkedapi-python
@@ -63,6 +63,7 @@ from linkedapi.operations import (
63
63
  RetrieveInvitations,
64
64
  RetrievePendingRequests,
65
65
  RetrievePerformance,
66
+ RetrieveProfileViewers,
66
67
  RetrieveSSI,
67
68
  SearchCompanies,
68
69
  SearchJobs,
@@ -78,7 +79,7 @@ from linkedapi.types import * # noqa: F403
78
79
  from linkedapi.types import __all__ as _types_all
79
80
  from linkedapi.webhooks import parse_webhook_event
80
81
 
81
- __version__ = "1.3.8"
82
+ __version__ = "1.3.9"
82
83
  PredefinedOperation = Operation
83
84
 
84
85
  __all__ = [
@@ -140,6 +141,7 @@ __all__ = [
140
141
  "RetrieveFeed",
141
142
  "RetrievePendingRequests",
142
143
  "RetrievePerformance",
144
+ "RetrieveProfileViewers",
143
145
  "RetrieveSSI",
144
146
  "SearchCompanies",
145
147
  "SearchJobs",
@@ -36,6 +36,7 @@ from linkedapi.operations import (
36
36
  RetrieveInvitations,
37
37
  RetrievePendingRequests,
38
38
  RetrievePerformance,
39
+ RetrieveProfileViewers,
39
40
  RetrieveSSI,
40
41
  SearchCompanies,
41
42
  SearchJobs,
@@ -98,6 +99,7 @@ class LinkedApi:
98
99
  self.retrieve_feed = RetrieveFeed(self.http_client)
99
100
  self.retrieve_ssi = RetrieveSSI(self.http_client)
100
101
  self.retrieve_performance = RetrievePerformance(self.http_client)
102
+ self.retrieve_profile_viewers = RetrieveProfileViewers(self.http_client)
101
103
  self.nv_send_message = NvSendMessage(self.http_client)
102
104
  self.nv_sync_conversation = NvSyncConversation(self.http_client)
103
105
  self.nv_sync_inbox = NvSyncInbox(self.http_client)
@@ -138,6 +140,7 @@ class LinkedApi:
138
140
  self.retrieve_feed,
139
141
  self.retrieve_ssi,
140
142
  self.retrieve_performance,
143
+ self.retrieve_profile_viewers,
141
144
  self.nv_send_message,
142
145
  self.nv_sync_conversation,
143
146
  self.nv_sync_inbox,
@@ -16,6 +16,7 @@ LinkedApiActionErrorType = Literal[
16
16
  "retrievingNotAllowed",
17
17
  "connectionNotFound",
18
18
  "searchingNotAllowed",
19
+ "searchInterfaceMismatch",
19
20
  "companyNotFound",
20
21
  "postNotFound",
21
22
  "jobNotFound",
@@ -41,6 +42,7 @@ LINKED_API_ACTION_ERROR_TYPES: tuple[str, ...] = (
41
42
  "retrievingNotAllowed",
42
43
  "connectionNotFound",
43
44
  "searchingNotAllowed",
45
+ "searchInterfaceMismatch",
44
46
  "companyNotFound",
45
47
  "postNotFound",
46
48
  "jobNotFound",
@@ -26,6 +26,7 @@ from linkedapi.operations.retrieve_feed import RetrieveFeed
26
26
  from linkedapi.operations.retrieve_invitations import RetrieveInvitations
27
27
  from linkedapi.operations.retrieve_pending_requests import RetrievePendingRequests
28
28
  from linkedapi.operations.retrieve_performance import RetrievePerformance
29
+ from linkedapi.operations.retrieve_profile_viewers import RetrieveProfileViewers
29
30
  from linkedapi.operations.retrieve_ssi import RetrieveSSI
30
31
  from linkedapi.operations.search_companies import SearchCompanies
31
32
  from linkedapi.operations.search_jobs import SearchJobs
@@ -72,6 +73,7 @@ __all__ = [
72
73
  "RetrieveInvitations",
73
74
  "RetrievePendingRequests",
74
75
  "RetrievePerformance",
76
+ "RetrieveProfileViewers",
75
77
  "RetrieveSSI",
76
78
  "SearchCompanies",
77
79
  "SearchJobs",
@@ -0,0 +1,15 @@
1
+ from __future__ import annotations
2
+
3
+ from linkedapi.core import Operation
4
+ from linkedapi.mappers import ArrayWorkflowMapper
5
+ from linkedapi.types import ProfileViewer, RetrieveProfileViewersParams
6
+
7
+
8
+ class RetrieveProfileViewers(Operation[RetrieveProfileViewersParams, list[ProfileViewer]]):
9
+ """Retrieve the viewers visible on the current account's LinkedIn profile."""
10
+
11
+ operation_name = "retrieveProfileViewers"
12
+ mapper = ArrayWorkflowMapper[RetrieveProfileViewersParams, ProfileViewer](
13
+ "st.retrieveProfileViewers",
14
+ ProfileViewer,
15
+ )
@@ -96,12 +96,15 @@ from linkedapi.types.jobs import (
96
96
  JobDatePosted,
97
97
  JobEmploymentType,
98
98
  JobExperienceLevel,
99
+ JobPreferenceEmploymentType,
100
+ JobPreferenceExperienceLevel,
99
101
  JobSalary,
100
102
  JobWorkplaceType,
101
103
  SalaryPeriod,
102
104
  SearchJobResult,
103
105
  SearchJobsFilter,
104
106
  SearchJobsParams,
107
+ SearchJobsPreferences,
105
108
  )
106
109
  from linkedapi.types.message import (
107
110
  ConversationPollRequest,
@@ -177,6 +180,11 @@ from linkedapi.types.post import (
177
180
  ReplyToCommentParams,
178
181
  ReplyToCommentResult,
179
182
  )
183
+ from linkedapi.types.profile_viewers import (
184
+ ProfileViewer,
185
+ ProfileViewerType,
186
+ RetrieveProfileViewersParams,
187
+ )
180
188
  from linkedapi.types.responses import LinkedApiRequestError, LinkedApiResponse
181
189
  from linkedapi.types.search_companies import (
182
190
  AnnualRevenueFilter,
@@ -315,6 +323,8 @@ __all__ = [
315
323
  "JobDatePosted",
316
324
  "JobEmploymentType",
317
325
  "JobExperienceLevel",
326
+ "JobPreferenceEmploymentType",
327
+ "JobPreferenceExperienceLevel",
318
328
  "JobSalary",
319
329
  "JobWorkplaceType",
320
330
  "LanguageProficiency",
@@ -383,6 +393,8 @@ __all__ = [
383
393
  "PostReactionsRetrievalConfig",
384
394
  "PostReposter",
385
395
  "PostType",
396
+ "ProfileViewer",
397
+ "ProfileViewerType",
386
398
  "ReactToCommentParams",
387
399
  "ReactToPostParams",
388
400
  "Reaction",
@@ -402,6 +414,7 @@ __all__ = [
402
414
  "RetrieveFeedParams",
403
415
  "RetrievePendingRequestsResult",
404
416
  "RetrievePerformanceResult",
417
+ "RetrieveProfileViewersParams",
405
418
  "RetrieveSSIResult",
406
419
  "SalaryPeriod",
407
420
  "SearchCompaniesFilter",
@@ -411,6 +424,7 @@ __all__ = [
411
424
  "SearchJobResult",
412
425
  "SearchJobsFilter",
413
426
  "SearchJobsParams",
427
+ "SearchJobsPreferences",
414
428
  "SearchPeopleFilter",
415
429
  "SearchPeopleParams",
416
430
  "SearchPeopleResult",
@@ -24,6 +24,24 @@ JobEmploymentType = Literal[
24
24
  "other",
25
25
  ]
26
26
  JobWorkplaceType = Literal["onSite", "remote", "hybrid"]
27
+ # Experience levels of LinkedIn's AI-powered jobs search. Not a subset of JobExperienceLevel:
28
+ # "senior" corresponds to "midSeniorLevel", "manager" has no classic equivalent, and "internship"
29
+ # and "associate" are absent here.
30
+ JobPreferenceExperienceLevel = Literal[
31
+ "entryLevel",
32
+ "senior",
33
+ "manager",
34
+ "director",
35
+ "executive",
36
+ ]
37
+ # Same names as JobEmploymentType, minus "temporary" and "other".
38
+ JobPreferenceEmploymentType = Literal[
39
+ "fullTime",
40
+ "partTime",
41
+ "contract",
42
+ "internship",
43
+ "volunteer",
44
+ ]
27
45
  SalaryPeriod = Literal["yearly", "monthly", "hourly"]
28
46
  JobCurrency = Literal[
29
47
  "usd",
@@ -74,6 +92,12 @@ class JobSalary(LinkedApiModel):
74
92
 
75
93
 
76
94
  class SearchJobsFilter(LinkedApiModel):
95
+ """Filtering criteria for the classic LinkedIn jobs search.
96
+
97
+ Every specified field is applied, or the action fails.
98
+ """
99
+
100
+ # Deprecated: use the top-level "location" of SearchJobsParams instead.
77
101
  location: str | None = None
78
102
  date_posted: JobDatePosted | None = None
79
103
  experience_levels: list[JobExperienceLevel] | None = None
@@ -89,9 +113,32 @@ class SearchJobsFilter(LinkedApiModel):
89
113
  fair_chance_employer: bool | None = None
90
114
 
91
115
 
116
+ class SearchJobsPreferences(LinkedApiModel):
117
+ """Filtering criteria for LinkedIn's AI-powered jobs search.
118
+
119
+ LinkedIn decides which of them it offers for a given search, and the ones it does not offer are
120
+ skipped instead of failing the action.
121
+ """
122
+
123
+ date_posted: JobDatePosted | None = None
124
+ experience_levels: list[JobPreferenceExperienceLevel] | None = None
125
+ employment_types: list[JobPreferenceEmploymentType] | None = None
126
+ companies: list[str] | None = None
127
+ remote: bool | None = None
128
+ easy_apply: bool | None = None
129
+ under_10_applicants: bool | None = None
130
+ in_your_network: bool | None = None
131
+ keywords: list[str] | None = None
132
+
133
+
92
134
  class SearchJobsParams(BaseActionParams, LimitParams):
93
135
  term: str | None = None
136
+ location: str | None = None
137
+ allow_similar_results: bool | None = None
138
+ # "filter" and "preferences" are mutually exclusive: "filter" targets the classic LinkedIn jobs
139
+ # search, "preferences" the AI-powered one.
94
140
  filter: SearchJobsFilter | None = None
141
+ preferences: SearchJobsPreferences | None = None
95
142
  custom_search_url: str | None = None
96
143
 
97
144
 
@@ -106,6 +153,7 @@ class SearchJobResult(LinkedApiModel):
106
153
  salary: JobSalary | None = None
107
154
  easy_apply: bool | None = None
108
155
  is_promoted: bool | None = None
156
+ is_similar_match: bool | None = None
109
157
 
110
158
 
111
159
  class FetchJobParams(BaseActionParams):
@@ -118,7 +166,6 @@ class Job(LinkedApiModel):
118
166
  job_url: str | None = None
119
167
  title: str | None = None
120
168
  company_name: str | None = None
121
- company_urn: str | None = None
122
169
  company_url: str | None = None
123
170
  location: str | None = None
124
171
  posted_date: str | None = None
@@ -97,6 +97,9 @@ class InboxMessage(LinkedApiModel):
97
97
  type: ConversationType | None = None
98
98
  thread_id: str | None = None
99
99
  person_urn: str | None = None
100
+ person_hashed_url: str | None = None
101
+ person_public_url: str | None = None
102
+ # Deprecated: use person_hashed_url. Still returned by the API for compatibility.
100
103
  person_url: str | None = None
101
104
  sender: MessageSender | None = None
102
105
  text: str | None = None
@@ -0,0 +1,82 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field, model_validator
6
+
7
+ from linkedapi.types.base import LinkedApiModel
8
+ from linkedapi.types.params import BaseActionParams
9
+
10
+ ProfileViewerType = Literal["identified", "anonymous"]
11
+
12
+
13
+ class RetrieveProfileViewersParams(BaseActionParams):
14
+ limit: int | None = Field(default=None, ge=1, le=300)
15
+ since: str | None = None
16
+
17
+
18
+ class ProfileViewer(LinkedApiModel):
19
+ viewer_type: ProfileViewerType
20
+ viewed_at: str | None
21
+ viewed_ago: str | None
22
+ name: str | None = None
23
+ public_url: str | None = None
24
+ urn: str | None = None
25
+ headline: str | None = None
26
+ connection_degree: Literal[1, 2, 3] | None = None
27
+ avatar_url: str | None = None
28
+ description: str | None = None
29
+ search_url: str | None = None
30
+
31
+ @model_validator(mode="after")
32
+ def validate_type_fields(self) -> ProfileViewer:
33
+ type_fields = {
34
+ "name",
35
+ "public_url",
36
+ "urn",
37
+ "headline",
38
+ "connection_degree",
39
+ "avatar_url",
40
+ "description",
41
+ "search_url",
42
+ }
43
+ required_fields = {
44
+ "identified": {
45
+ "name",
46
+ "public_url",
47
+ "urn",
48
+ "headline",
49
+ "connection_degree",
50
+ "avatar_url",
51
+ },
52
+ "anonymous": {"description", "search_url"},
53
+ }[self.viewer_type]
54
+ missing_fields = required_fields - self.model_fields_set
55
+ if missing_fields:
56
+ msg = (
57
+ f"{self.viewer_type} profile viewer is missing required fields: "
58
+ f"{', '.join(sorted(missing_fields))}"
59
+ )
60
+ raise ValueError(msg)
61
+
62
+ unexpected_fields = (self.model_fields_set & type_fields) - required_fields
63
+ if unexpected_fields:
64
+ msg = (
65
+ f"{self.viewer_type} profile viewer contains fields for another type: "
66
+ f"{', '.join(sorted(unexpected_fields))}"
67
+ )
68
+ raise ValueError(msg)
69
+
70
+ required_values = {
71
+ "identified": {"name": self.name, "public_url": self.public_url},
72
+ "anonymous": {"description": self.description, "search_url": self.search_url},
73
+ }[self.viewer_type]
74
+ null_fields = [name for name, value in required_values.items() if value is None]
75
+ if null_fields:
76
+ msg = (
77
+ f"{self.viewer_type} profile viewer requires non-null fields: "
78
+ f"{', '.join(sorted(null_fields))}"
79
+ )
80
+ raise ValueError(msg)
81
+
82
+ return self
@@ -102,6 +102,9 @@ class MessageWebhookEventData(LinkedApiModel):
102
102
  type: ConversationType | None = None
103
103
  thread_id: str | None = None
104
104
  person_urn: str | None = None
105
+ person_hashed_url: str | None = None
106
+ person_public_url: str | None = None
107
+ # Deprecated: use person_hashed_url. Still returned by the API for compatibility.
105
108
  person_url: str | None = None
106
109
  message_id: str | None = None
107
110
  sender: MessageSender | None = None
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "linkedapi"
7
- version = "1.3.8"
7
+ version = "1.3.10"
8
8
  description = "Official synchronous Python SDK for Linked API."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -45,6 +45,7 @@ def test_error_type_sets_match_node_contract() -> None:
45
45
  "retrievingNotAllowed",
46
46
  "connectionNotFound",
47
47
  "searchingNotAllowed",
48
+ "searchInterfaceMismatch",
48
49
  "companyNotFound",
49
50
  "postNotFound",
50
51
  "jobNotFound",
@@ -59,6 +59,7 @@ def test_linked_api_exposes_all_predefined_operations() -> None:
59
59
  "create_post",
60
60
  "retrieve_ssi",
61
61
  "retrieve_performance",
62
+ "retrieve_profile_viewers",
62
63
  ]
63
64
 
64
65
  for name in operation_names:
@@ -66,7 +67,7 @@ def test_linked_api_exposes_all_predefined_operations() -> None:
66
67
  assert hasattr(operation, "execute")
67
68
  assert hasattr(operation, "result")
68
69
  assert hasattr(operation, "cancel")
69
- assert len(linkedapi.operations) == 38
70
+ assert len(linkedapi.operations) == 39
70
71
 
71
72
 
72
73
  def test_operation_mappers_match_node_contract() -> None:
File without changes
File without changes
File without changes
File without changes
File without changes