Skip to content

Commit e7fcbfb

Browse files
Add search_jobs and fetch_job operations
1 parent c0345cb commit e7fcbfb

11 files changed

Lines changed: 226 additions & 3 deletions

File tree

linkedapi/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
CustomWorkflow,
3535
FetchCompany,
3636
FetchCompanyMapper,
37+
FetchJob,
38+
FetchJobMapper,
3739
FetchPerson,
3840
FetchPersonMapper,
3941
FetchPost,
@@ -53,6 +55,7 @@
5355
RetrievePerformance,
5456
RetrieveSSI,
5557
SearchCompanies,
58+
SearchJobs,
5659
SearchPeople,
5760
SendConnectionRequest,
5861
SendMessage,
@@ -62,7 +65,7 @@
6265
from linkedapi.types import * # noqa: F403
6366
from linkedapi.types import __all__ as _types_all
6467

65-
__version__ = "1.0.0"
68+
__version__ = "1.0.2"
6669
PredefinedOperation = Operation
6770

6871
__all__ = [
@@ -80,6 +83,8 @@
8083
"CustomWorkflow",
8184
"FetchCompany",
8285
"FetchCompanyMapper",
86+
"FetchJob",
87+
"FetchJobMapper",
8388
"FetchPerson",
8489
"FetchPersonMapper",
8590
"FetchPost",
@@ -114,6 +119,7 @@
114119
"RetrievePerformance",
115120
"RetrieveSSI",
116121
"SearchCompanies",
122+
"SearchJobs",
117123
"SearchPeople",
118124
"SendConnectionRequest",
119125
"SendMessage",

linkedapi/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
CreatePost,
1414
CustomWorkflow,
1515
FetchCompany,
16+
FetchJob,
1617
FetchPerson,
1718
FetchPost,
1819
NvFetchCompany,
@@ -28,6 +29,7 @@
2829
RetrievePerformance,
2930
RetrieveSSI,
3031
SearchCompanies,
32+
SearchJobs,
3133
SearchPeople,
3234
SendConnectionRequest,
3335
SendMessage,
@@ -60,9 +62,11 @@ def __init__(self, config: LinkedApiConfig | HttpClient[Any]) -> None:
6062
self.remove_connection = RemoveConnection(self.http_client)
6163
self.search_companies = SearchCompanies(self.http_client)
6264
self.search_people = SearchPeople(self.http_client)
65+
self.search_jobs = SearchJobs(self.http_client)
6366
self.fetch_company = FetchCompany(self.http_client)
6467
self.fetch_person = FetchPerson(self.http_client)
6568
self.fetch_post = FetchPost(self.http_client)
69+
self.fetch_job = FetchJob(self.http_client)
6670
self.react_to_post = ReactToPost(self.http_client)
6771
self.comment_on_post = CommentOnPost(self.http_client)
6872
self.create_post = CreatePost(self.http_client)
@@ -87,9 +91,11 @@ def __init__(self, config: LinkedApiConfig | HttpClient[Any]) -> None:
8791
self.remove_connection,
8892
self.search_companies,
8993
self.search_people,
94+
self.search_jobs,
9095
self.fetch_company,
9196
self.fetch_person,
9297
self.fetch_post,
98+
self.fetch_job,
9399
self.react_to_post,
94100
self.comment_on_post,
95101
self.create_post,

linkedapi/errors.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"searchingNotAllowed",
1717
"companyNotFound",
1818
"postNotFound",
19+
"jobNotFound",
1920
"commentingNotAllowed",
2021
"noPostingPermission",
2122
"noSalesNavigator",
@@ -35,6 +36,7 @@
3536
"searchingNotAllowed",
3637
"companyNotFound",
3738
"postNotFound",
39+
"jobNotFound",
3840
"commentingNotAllowed",
3941
"noPostingPermission",
4042
"noSalesNavigator",

linkedapi/operations/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from linkedapi.operations.create_post import CreatePost
44
from linkedapi.operations.custom_workflow import CustomWorkflow
55
from linkedapi.operations.fetch_company import FetchCompany, FetchCompanyMapper
6+
from linkedapi.operations.fetch_job import FetchJob, FetchJobMapper
67
from linkedapi.operations.fetch_person import FetchPerson, FetchPersonMapper
78
from linkedapi.operations.fetch_post import FetchPost, FetchPostMapper
89
from linkedapi.operations.nv_fetch_company import NvFetchCompany, NvFetchCompanyMapper
@@ -18,6 +19,7 @@
1819
from linkedapi.operations.retrieve_performance import RetrievePerformance
1920
from linkedapi.operations.retrieve_ssi import RetrieveSSI
2021
from linkedapi.operations.search_companies import SearchCompanies
22+
from linkedapi.operations.search_jobs import SearchJobs
2123
from linkedapi.operations.search_people import SearchPeople
2224
from linkedapi.operations.send_connection_request import SendConnectionRequest
2325
from linkedapi.operations.send_message import SendMessage
@@ -31,6 +33,8 @@
3133
"CustomWorkflow",
3234
"FetchCompany",
3335
"FetchCompanyMapper",
36+
"FetchJob",
37+
"FetchJobMapper",
3438
"FetchPerson",
3539
"FetchPersonMapper",
3640
"FetchPost",
@@ -50,6 +54,7 @@
5054
"RetrievePerformance",
5155
"RetrieveSSI",
5256
"SearchCompanies",
57+
"SearchJobs",
5358
"SearchPeople",
5459
"SendConnectionRequest",
5560
"SendMessage",

linkedapi/operations/fetch_job.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from __future__ import annotations
2+
3+
from linkedapi.core import Operation
4+
from linkedapi.mappers import ThenWorkflowMapper
5+
from linkedapi.types import FetchJobParams, Job
6+
7+
8+
class FetchJobMapper(ThenWorkflowMapper[FetchJobParams, Job]):
9+
def __init__(self) -> None:
10+
super().__init__(
11+
action_configs=[],
12+
response_mappings=[],
13+
base_action_type="st.openJob",
14+
default_params={"basicInfo": True},
15+
result_model=Job,
16+
)
17+
18+
19+
class FetchJob(Operation[FetchJobParams, Job]):
20+
"""Fetch a LinkedIn job."""
21+
22+
operation_name = "fetchJob"
23+
mapper = FetchJobMapper()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 SearchJobResult, SearchJobsParams
6+
7+
8+
class SearchJobs(Operation[SearchJobsParams, list[SearchJobResult]]):
9+
"""Search jobs on standard LinkedIn."""
10+
11+
operation_name = "searchJobs"
12+
mapper = ArrayWorkflowMapper[SearchJobsParams, SearchJobResult](
13+
"st.searchJobs",
14+
SearchJobResult,
15+
)

linkedapi/types/__init__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@
8383
SendConnectionRequestParams,
8484
WithdrawConnectionRequestParams,
8585
)
86+
from linkedapi.types.jobs import (
87+
FetchJobParams,
88+
FetchJobResult,
89+
Job,
90+
JobCurrency,
91+
JobDatePosted,
92+
JobEmploymentType,
93+
JobExperienceLevel,
94+
JobSalary,
95+
JobWorkplaceType,
96+
SalaryPeriod,
97+
SearchJobResult,
98+
SearchJobsFilter,
99+
SearchJobsParams,
100+
)
86101
from linkedapi.types.message import (
87102
ConversationPollRequest,
88103
ConversationPollResult,
@@ -223,13 +238,22 @@
223238
"EmploymentType",
224239
"FetchCompanyParams",
225240
"FetchCompanyResult",
241+
"FetchJobParams",
242+
"FetchJobResult",
226243
"FetchPersonParams",
227244
"FetchPersonResult",
228245
"FetchPostParams",
229246
"FetchPostResult",
230247
"GetConnectionSessionParams",
231248
"GetLimitsParams",
232249
"GetLimitsUsageParams",
250+
"Job",
251+
"JobCurrency",
252+
"JobDatePosted",
253+
"JobEmploymentType",
254+
"JobExperienceLevel",
255+
"JobSalary",
256+
"JobWorkplaceType",
233257
"LanguageProficiency",
234258
"Limit",
235259
"LimitCategory",
@@ -298,10 +322,14 @@
298322
"RetrievePendingRequestsResult",
299323
"RetrievePerformanceResult",
300324
"RetrieveSSIResult",
325+
"SalaryPeriod",
301326
"SearchCompaniesFilter",
302327
"SearchCompaniesParams",
303328
"SearchCompanyResult",
304329
"SearchCompanySize",
330+
"SearchJobResult",
331+
"SearchJobsFilter",
332+
"SearchJobsParams",
305333
"SearchPeopleFilter",
306334
"SearchPeopleParams",
307335
"SearchPeopleResult",

linkedapi/types/jobs.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from __future__ import annotations
2+
3+
from typing import Literal, TypeAlias
4+
5+
from linkedapi.types.base import LinkedApiModel
6+
from linkedapi.types.params import BaseActionParams, LimitParams
7+
8+
JobDatePosted = Literal["anyTime", "past24Hours", "pastWeek", "pastMonth"]
9+
JobExperienceLevel = Literal[
10+
"internship",
11+
"entryLevel",
12+
"associate",
13+
"midSeniorLevel",
14+
"director",
15+
"executive",
16+
]
17+
JobEmploymentType = Literal[
18+
"fullTime",
19+
"partTime",
20+
"contract",
21+
"temporary",
22+
"volunteer",
23+
"internship",
24+
"other",
25+
]
26+
JobWorkplaceType = Literal["onSite", "remote", "hybrid"]
27+
SalaryPeriod = Literal["yearly", "monthly", "hourly"]
28+
JobCurrency = Literal[
29+
"usd",
30+
"eur",
31+
"gbp",
32+
"inr",
33+
"cad",
34+
"aud",
35+
"nzd",
36+
"hkd",
37+
"sgd",
38+
"jpy",
39+
"cny",
40+
"chf",
41+
"sek",
42+
"nok",
43+
"dkk",
44+
"pln",
45+
"czk",
46+
"huf",
47+
"ron",
48+
"brl",
49+
"mxn",
50+
"ars",
51+
"zar",
52+
"aed",
53+
"sar",
54+
"ils",
55+
"try",
56+
"rub",
57+
"uah",
58+
"krw",
59+
"thb",
60+
"idr",
61+
"myr",
62+
"php",
63+
"vnd",
64+
"ngn",
65+
"twd",
66+
]
67+
68+
69+
class JobSalary(LinkedApiModel):
70+
currency: JobCurrency | None = None
71+
min_amount: float | None = None
72+
max_amount: float | None = None
73+
period: SalaryPeriod | None = None
74+
75+
76+
class SearchJobsFilter(LinkedApiModel):
77+
location: str | None = None
78+
date_posted: JobDatePosted | None = None
79+
experience_levels: list[JobExperienceLevel] | None = None
80+
employment_types: list[JobEmploymentType] | None = None
81+
workplace_types: list[JobWorkplaceType] | None = None
82+
companies: list[str] | None = None
83+
industries: list[str] | None = None
84+
job_functions: list[str] | None = None
85+
easy_apply: bool | None = None
86+
has_verifications: bool | None = None
87+
under_10_applicants: bool | None = None
88+
in_your_network: bool | None = None
89+
fair_chance_employer: bool | None = None
90+
91+
92+
class SearchJobsParams(BaseActionParams, LimitParams):
93+
term: str | None = None
94+
filter: SearchJobsFilter | None = None
95+
custom_search_url: str | None = None
96+
97+
98+
class SearchJobResult(LinkedApiModel):
99+
job_id: str | None = None
100+
job_url: str | None = None
101+
title: str | None = None
102+
company_name: str | None = None
103+
location: str | None = None
104+
workplace_type: str | None = None
105+
salary: JobSalary | None = None
106+
easy_apply: bool | None = None
107+
is_promoted: bool | None = None
108+
109+
110+
class FetchJobParams(BaseActionParams):
111+
job_url: str
112+
113+
114+
class Job(LinkedApiModel):
115+
job_id: str | None = None
116+
job_url: str | None = None
117+
title: str | None = None
118+
company_name: str | None = None
119+
company_url: str | None = None
120+
location: str | None = None
121+
posted_date: str | None = None
122+
applicants_count: int | None = None
123+
workplace_type: str | None = None
124+
employment_type: str | None = None
125+
salary: JobSalary | None = None
126+
description: str | None = None
127+
apply_url: str | None = None
128+
easy_apply: bool | None = None
129+
130+
131+
FetchJobResult: TypeAlias = Job

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "linkedapi"
7-
version = "1.0.1"
7+
version = "1.0.2"
88
description = "Official synchronous Python SDK for Linked API."
99
readme = "README.md"
1010
requires-python = ">=3.10"

tests/test_errors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def test_error_type_sets_match_node_contract() -> None:
4242
"searchingNotAllowed",
4343
"companyNotFound",
4444
"postNotFound",
45+
"jobNotFound",
4546
"commentingNotAllowed",
4647
"noPostingPermission",
4748
"noSalesNavigator",

0 commit comments

Comments
 (0)