blitz-api-py 0.1.0__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.
- blitz_api/__init__.py +65 -0
- blitz_api/_base_client.py +191 -0
- blitz_api/_client.py +13 -0
- blitz_api/_client_async.py +143 -0
- blitz_api/_client_sync.py +145 -0
- blitz_api/_compat.py +26 -0
- blitz_api/_constants.py +36 -0
- blitz_api/_exceptions.py +113 -0
- blitz_api/_pagination_async.py +128 -0
- blitz_api/_pagination_base.py +52 -0
- blitz_api/_pagination_sync.py +130 -0
- blitz_api/_rate_limit.py +14 -0
- blitz_api/_rate_limit_async.py +67 -0
- blitz_api/_rate_limit_sync.py +69 -0
- blitz_api/_version.py +1 -0
- blitz_api/py.typed +0 -0
- blitz_api/resources/__init__.py +27 -0
- blitz_api/resources/_async/__init__.py +1 -0
- blitz_api/resources/_async/account.py +27 -0
- blitz_api/resources/_async/enrichment.py +116 -0
- blitz_api/resources/_async/search.py +153 -0
- blitz_api/resources/_async/utils.py +43 -0
- blitz_api/resources/_sync/__init__.py +3 -0
- blitz_api/resources/_sync/account.py +29 -0
- blitz_api/resources/_sync/enrichment.py +118 -0
- blitz_api/resources/_sync/search.py +155 -0
- blitz_api/resources/_sync/utils.py +45 -0
- blitz_api/types/__init__.py +108 -0
- blitz_api/types/_models.py +23 -0
- blitz_api/types/account.py +27 -0
- blitz_api/types/enrichment.py +76 -0
- blitz_api/types/enums.py +633 -0
- blitz_api/types/filters.py +130 -0
- blitz_api/types/search.py +36 -0
- blitz_api/types/shared.py +119 -0
- blitz_api/types/utils.py +35 -0
- blitz_api_py-0.1.0.dist-info/METADATA +220 -0
- blitz_api_py-0.1.0.dist-info/RECORD +40 -0
- blitz_api_py-0.1.0.dist-info/WHEEL +4 -0
- blitz_api_py-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""The Enrichment resource: ``client.enrichment``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from ..._compat import TimeoutParam
|
|
8
|
+
from ...types.enrichment import (
|
|
9
|
+
CompanyEnrichmentResponse,
|
|
10
|
+
DomainToLinkedinResponse,
|
|
11
|
+
EmailEnrichmentResponse,
|
|
12
|
+
EmailToPersonResponse,
|
|
13
|
+
LinkedinToDomainResponse,
|
|
14
|
+
PhoneEnrichmentResponse,
|
|
15
|
+
PhoneToPersonResponse,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from ..._client import AsyncBlitzAPI
|
|
20
|
+
|
|
21
|
+
_EMAIL = "/v2/enrichment/email"
|
|
22
|
+
_PHONE = "/v2/enrichment/phone"
|
|
23
|
+
_EMAIL_TO_PERSON = "/v2/enrichment/email-to-person"
|
|
24
|
+
_PHONE_TO_PERSON = "/v2/enrichment/phone-to-person"
|
|
25
|
+
_COMPANY = "/v2/enrichment/company"
|
|
26
|
+
_DOMAIN_TO_LINKEDIN = "/v2/enrichment/domain-to-linkedin"
|
|
27
|
+
_LINKEDIN_TO_DOMAIN = "/v2/enrichment/linkedin-to-domain"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AsyncEnrichmentResource:
|
|
31
|
+
def __init__(self, client: AsyncBlitzAPI) -> None:
|
|
32
|
+
self._client = client
|
|
33
|
+
|
|
34
|
+
async def email(
|
|
35
|
+
self, *, person_linkedin_url: str, timeout: TimeoutParam = None
|
|
36
|
+
) -> EmailEnrichmentResponse:
|
|
37
|
+
"""Find a verified work email from a LinkedIn profile URL."""
|
|
38
|
+
return await self._client._request(
|
|
39
|
+
"POST",
|
|
40
|
+
_EMAIL,
|
|
41
|
+
body={"person_linkedin_url": person_linkedin_url},
|
|
42
|
+
cast_to=EmailEnrichmentResponse,
|
|
43
|
+
timeout=timeout,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
async def phone(
|
|
47
|
+
self, *, person_linkedin_url: str, timeout: TimeoutParam = None
|
|
48
|
+
) -> PhoneEnrichmentResponse:
|
|
49
|
+
"""Find a phone number from a LinkedIn profile URL (US only)."""
|
|
50
|
+
return await self._client._request(
|
|
51
|
+
"POST",
|
|
52
|
+
_PHONE,
|
|
53
|
+
body={"person_linkedin_url": person_linkedin_url},
|
|
54
|
+
cast_to=PhoneEnrichmentResponse,
|
|
55
|
+
timeout=timeout,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
async def email_to_person(
|
|
59
|
+
self, *, email: str, timeout: TimeoutParam = None
|
|
60
|
+
) -> EmailToPersonResponse:
|
|
61
|
+
"""Resolve a work email to a full person profile."""
|
|
62
|
+
return await self._client._request(
|
|
63
|
+
"POST",
|
|
64
|
+
_EMAIL_TO_PERSON,
|
|
65
|
+
body={"email": email},
|
|
66
|
+
cast_to=EmailToPersonResponse,
|
|
67
|
+
timeout=timeout,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async def phone_to_person(
|
|
71
|
+
self, *, phone: str, timeout: TimeoutParam = None
|
|
72
|
+
) -> PhoneToPersonResponse:
|
|
73
|
+
"""Resolve a phone number to a full person profile."""
|
|
74
|
+
return await self._client._request(
|
|
75
|
+
"POST",
|
|
76
|
+
_PHONE_TO_PERSON,
|
|
77
|
+
body={"phone": phone},
|
|
78
|
+
cast_to=PhoneToPersonResponse,
|
|
79
|
+
timeout=timeout,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
async def company(
|
|
83
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
84
|
+
) -> CompanyEnrichmentResponse:
|
|
85
|
+
"""Resolve a company LinkedIn URL to a full company profile."""
|
|
86
|
+
return await self._client._request(
|
|
87
|
+
"POST",
|
|
88
|
+
_COMPANY,
|
|
89
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
90
|
+
cast_to=CompanyEnrichmentResponse,
|
|
91
|
+
timeout=timeout,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
async def domain_to_linkedin(
|
|
95
|
+
self, *, domain: str, timeout: TimeoutParam = None
|
|
96
|
+
) -> DomainToLinkedinResponse:
|
|
97
|
+
"""Resolve a website domain to a company LinkedIn URL."""
|
|
98
|
+
return await self._client._request(
|
|
99
|
+
"POST",
|
|
100
|
+
_DOMAIN_TO_LINKEDIN,
|
|
101
|
+
body={"domain": domain},
|
|
102
|
+
cast_to=DomainToLinkedinResponse,
|
|
103
|
+
timeout=timeout,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
async def linkedin_to_domain(
|
|
107
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
108
|
+
) -> LinkedinToDomainResponse:
|
|
109
|
+
"""Resolve a company LinkedIn URL to its email domain."""
|
|
110
|
+
return await self._client._request(
|
|
111
|
+
"POST",
|
|
112
|
+
_LINKEDIN_TO_DOMAIN,
|
|
113
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
114
|
+
cast_to=LinkedinToDomainResponse,
|
|
115
|
+
timeout=timeout,
|
|
116
|
+
)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""The Search resource: ``client.search``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from ..._compat import TimeoutParam
|
|
8
|
+
from ..._pagination_async import AsyncCursorPage, AsyncPageNumberPage
|
|
9
|
+
from ...types.filters import (
|
|
10
|
+
CascadeTier,
|
|
11
|
+
CompanyFilter,
|
|
12
|
+
ContinentValue,
|
|
13
|
+
JobFunctionValue,
|
|
14
|
+
JobLevelValue,
|
|
15
|
+
PeopleFilter,
|
|
16
|
+
SalesRegionValue,
|
|
17
|
+
)
|
|
18
|
+
from ...types.search import WaterfallIcpResponse
|
|
19
|
+
from ...types.shared import Company, Person
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from ..._client import AsyncBlitzAPI
|
|
23
|
+
|
|
24
|
+
_PEOPLE = "/v2/search/people"
|
|
25
|
+
_COMPANIES = "/v2/search/companies"
|
|
26
|
+
_EMPLOYEE_FINDER = "/v2/search/employee-finder"
|
|
27
|
+
_WATERFALL = "/v2/search/waterfall-icp-keyword"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _drop_none(**kwargs: Any) -> dict[str, Any]:
|
|
31
|
+
"""Build a request body keeping only the arguments the caller provided."""
|
|
32
|
+
return {key: value for key, value in kwargs.items() if value is not None}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _employee_finder_body(
|
|
36
|
+
*,
|
|
37
|
+
company_linkedin_url: str,
|
|
38
|
+
country_code: list[str] | None,
|
|
39
|
+
continent: list[ContinentValue] | None,
|
|
40
|
+
sales_region: list[SalesRegionValue] | None,
|
|
41
|
+
job_level: list[JobLevelValue] | None,
|
|
42
|
+
job_function: list[JobFunctionValue] | None,
|
|
43
|
+
min_connections_count: int | None,
|
|
44
|
+
max_results: int | None,
|
|
45
|
+
page: int | None,
|
|
46
|
+
) -> dict[str, Any]:
|
|
47
|
+
return _drop_none(
|
|
48
|
+
company_linkedin_url=company_linkedin_url,
|
|
49
|
+
country_code=country_code,
|
|
50
|
+
continent=continent,
|
|
51
|
+
sales_region=sales_region,
|
|
52
|
+
job_level=job_level,
|
|
53
|
+
job_function=job_function,
|
|
54
|
+
min_connections_count=min_connections_count,
|
|
55
|
+
max_results=max_results,
|
|
56
|
+
page=page,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AsyncSearchResource:
|
|
61
|
+
def __init__(self, client: AsyncBlitzAPI) -> None:
|
|
62
|
+
self._client = client
|
|
63
|
+
|
|
64
|
+
async def people(
|
|
65
|
+
self,
|
|
66
|
+
*,
|
|
67
|
+
company: CompanyFilter | None = None,
|
|
68
|
+
people: PeopleFilter | None = None,
|
|
69
|
+
max_results: int | None = None,
|
|
70
|
+
cursor: str | None = None,
|
|
71
|
+
timeout: TimeoutParam = None,
|
|
72
|
+
) -> AsyncCursorPage[Person]:
|
|
73
|
+
"""Search people across many companies, combining company and persona filters.
|
|
74
|
+
|
|
75
|
+
Auto-paginates over every matching person when the result is iterated; use
|
|
76
|
+
``.iter_pages()`` or the ``cursor=`` arg for manual control.
|
|
77
|
+
"""
|
|
78
|
+
body = _drop_none(company=company, people=people, max_results=max_results, cursor=cursor)
|
|
79
|
+
return await self._client._request(
|
|
80
|
+
"POST", _PEOPLE, body=body, cast_to=AsyncCursorPage[Person], timeout=timeout
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
async def companies(
|
|
84
|
+
self,
|
|
85
|
+
*,
|
|
86
|
+
company: CompanyFilter | None = None,
|
|
87
|
+
max_results: int | None = None,
|
|
88
|
+
cursor: str | None = None,
|
|
89
|
+
timeout: TimeoutParam = None,
|
|
90
|
+
) -> AsyncCursorPage[Company]:
|
|
91
|
+
"""Find companies matching ICP filters (industry, size, HQ, revenue, ...).
|
|
92
|
+
|
|
93
|
+
Auto-paginates over every matching company; use ``.iter_pages()`` or ``cursor=``
|
|
94
|
+
for manual control.
|
|
95
|
+
"""
|
|
96
|
+
body = _drop_none(company=company, max_results=max_results, cursor=cursor)
|
|
97
|
+
return await self._client._request(
|
|
98
|
+
"POST", _COMPANIES, body=body, cast_to=AsyncCursorPage[Company], timeout=timeout
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
async def employee_finder(
|
|
102
|
+
self,
|
|
103
|
+
*,
|
|
104
|
+
company_linkedin_url: str,
|
|
105
|
+
country_code: list[str] | None = None,
|
|
106
|
+
continent: list[ContinentValue] | None = None,
|
|
107
|
+
sales_region: list[SalesRegionValue] | None = None,
|
|
108
|
+
job_level: list[JobLevelValue] | None = None,
|
|
109
|
+
job_function: list[JobFunctionValue] | None = None,
|
|
110
|
+
min_connections_count: int | None = None,
|
|
111
|
+
max_results: int | None = None,
|
|
112
|
+
page: int | None = None,
|
|
113
|
+
timeout: TimeoutParam = None,
|
|
114
|
+
) -> AsyncPageNumberPage[Person]:
|
|
115
|
+
"""Search employees at a single company, with page-based pagination.
|
|
116
|
+
|
|
117
|
+
Auto-paginates over every matching employee; use ``.iter_pages()`` or ``page=``
|
|
118
|
+
for manual control.
|
|
119
|
+
"""
|
|
120
|
+
body = _employee_finder_body(
|
|
121
|
+
company_linkedin_url=company_linkedin_url,
|
|
122
|
+
country_code=country_code,
|
|
123
|
+
continent=continent,
|
|
124
|
+
sales_region=sales_region,
|
|
125
|
+
job_level=job_level,
|
|
126
|
+
job_function=job_function,
|
|
127
|
+
min_connections_count=min_connections_count,
|
|
128
|
+
max_results=max_results,
|
|
129
|
+
page=page,
|
|
130
|
+
)
|
|
131
|
+
return await self._client._request(
|
|
132
|
+
"POST",
|
|
133
|
+
_EMPLOYEE_FINDER,
|
|
134
|
+
body=body,
|
|
135
|
+
cast_to=AsyncPageNumberPage[Person],
|
|
136
|
+
timeout=timeout,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
async def waterfall_icp(
|
|
140
|
+
self,
|
|
141
|
+
*,
|
|
142
|
+
company_linkedin_url: str,
|
|
143
|
+
cascade: list[CascadeTier],
|
|
144
|
+
max_results: int | None = None,
|
|
145
|
+
timeout: TimeoutParam = None,
|
|
146
|
+
) -> WaterfallIcpResponse:
|
|
147
|
+
"""Find the best decision-maker at a company via a prioritized cascade."""
|
|
148
|
+
body = _drop_none(
|
|
149
|
+
company_linkedin_url=company_linkedin_url, cascade=cascade, max_results=max_results
|
|
150
|
+
)
|
|
151
|
+
return await self._client._request(
|
|
152
|
+
"POST", _WATERFALL, body=body, cast_to=WaterfallIcpResponse, timeout=timeout
|
|
153
|
+
)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""The Utilities resource: ``client.utils``."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from ..._compat import TimeoutParam
|
|
8
|
+
from ...types.utils import CompanyEmploymentDistributionResponse, CurrentDateResponse
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ..._client import AsyncBlitzAPI
|
|
12
|
+
|
|
13
|
+
_CURRENT_DATE = "/v2/utils/current-date"
|
|
14
|
+
_EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AsyncUtilsResource:
|
|
18
|
+
def __init__(self, client: AsyncBlitzAPI) -> None:
|
|
19
|
+
self._client = client
|
|
20
|
+
|
|
21
|
+
async def current_date(
|
|
22
|
+
self, *, region: str, timeout: TimeoutParam = None
|
|
23
|
+
) -> CurrentDateResponse:
|
|
24
|
+
"""Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
|
|
25
|
+
return await self._client._request(
|
|
26
|
+
"POST",
|
|
27
|
+
_CURRENT_DATE,
|
|
28
|
+
body={"region": region},
|
|
29
|
+
cast_to=CurrentDateResponse,
|
|
30
|
+
timeout=timeout,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
async def company_employment_distribution(
|
|
34
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
35
|
+
) -> CompanyEmploymentDistributionResponse:
|
|
36
|
+
"""Get a company's employee count broken down by country."""
|
|
37
|
+
return await self._client._request(
|
|
38
|
+
"POST",
|
|
39
|
+
_EMPLOYMENT_DISTRIBUTION,
|
|
40
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
41
|
+
cast_to=CompanyEmploymentDistributionResponse,
|
|
42
|
+
timeout=timeout,
|
|
43
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# This file is @generated by scripts/gen_sync.py from src/blitz_api/resources/_async/account.py.
|
|
2
|
+
# Do not edit by hand — edit the async source and run `python scripts/gen_sync.py`.
|
|
3
|
+
"""The Account resource: ``client.account``."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from ..._compat import TimeoutParam
|
|
10
|
+
from ...types.account import KeyInfo
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..._client import BlitzAPI
|
|
14
|
+
|
|
15
|
+
_KEY_INFO_PATH = "/v2/account/key-info"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AccountResource:
|
|
19
|
+
def __init__(self, client: BlitzAPI) -> None:
|
|
20
|
+
self._client = client
|
|
21
|
+
|
|
22
|
+
def key_info(self, *, timeout: TimeoutParam = None) -> KeyInfo:
|
|
23
|
+
"""Check the API key's validity, credit balance, and rate limit.
|
|
24
|
+
|
|
25
|
+
A cheap health check to run before a batch job.
|
|
26
|
+
"""
|
|
27
|
+
return self._client._request(
|
|
28
|
+
"GET", _KEY_INFO_PATH, body=None, cast_to=KeyInfo, timeout=timeout
|
|
29
|
+
)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# This file is @generated by scripts/gen_sync.py from src/blitz_api/resources/_async/enrichment.py.
|
|
2
|
+
# Do not edit by hand — edit the async source and run `python scripts/gen_sync.py`.
|
|
3
|
+
"""The Enrichment resource: ``client.enrichment``."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from ..._compat import TimeoutParam
|
|
10
|
+
from ...types.enrichment import (
|
|
11
|
+
CompanyEnrichmentResponse,
|
|
12
|
+
DomainToLinkedinResponse,
|
|
13
|
+
EmailEnrichmentResponse,
|
|
14
|
+
EmailToPersonResponse,
|
|
15
|
+
LinkedinToDomainResponse,
|
|
16
|
+
PhoneEnrichmentResponse,
|
|
17
|
+
PhoneToPersonResponse,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from ..._client import BlitzAPI
|
|
22
|
+
|
|
23
|
+
_EMAIL = "/v2/enrichment/email"
|
|
24
|
+
_PHONE = "/v2/enrichment/phone"
|
|
25
|
+
_EMAIL_TO_PERSON = "/v2/enrichment/email-to-person"
|
|
26
|
+
_PHONE_TO_PERSON = "/v2/enrichment/phone-to-person"
|
|
27
|
+
_COMPANY = "/v2/enrichment/company"
|
|
28
|
+
_DOMAIN_TO_LINKEDIN = "/v2/enrichment/domain-to-linkedin"
|
|
29
|
+
_LINKEDIN_TO_DOMAIN = "/v2/enrichment/linkedin-to-domain"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class EnrichmentResource:
|
|
33
|
+
def __init__(self, client: BlitzAPI) -> None:
|
|
34
|
+
self._client = client
|
|
35
|
+
|
|
36
|
+
def email(
|
|
37
|
+
self, *, person_linkedin_url: str, timeout: TimeoutParam = None
|
|
38
|
+
) -> EmailEnrichmentResponse:
|
|
39
|
+
"""Find a verified work email from a LinkedIn profile URL."""
|
|
40
|
+
return self._client._request(
|
|
41
|
+
"POST",
|
|
42
|
+
_EMAIL,
|
|
43
|
+
body={"person_linkedin_url": person_linkedin_url},
|
|
44
|
+
cast_to=EmailEnrichmentResponse,
|
|
45
|
+
timeout=timeout,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def phone(
|
|
49
|
+
self, *, person_linkedin_url: str, timeout: TimeoutParam = None
|
|
50
|
+
) -> PhoneEnrichmentResponse:
|
|
51
|
+
"""Find a phone number from a LinkedIn profile URL (US only)."""
|
|
52
|
+
return self._client._request(
|
|
53
|
+
"POST",
|
|
54
|
+
_PHONE,
|
|
55
|
+
body={"person_linkedin_url": person_linkedin_url},
|
|
56
|
+
cast_to=PhoneEnrichmentResponse,
|
|
57
|
+
timeout=timeout,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def email_to_person(
|
|
61
|
+
self, *, email: str, timeout: TimeoutParam = None
|
|
62
|
+
) -> EmailToPersonResponse:
|
|
63
|
+
"""Resolve a work email to a full person profile."""
|
|
64
|
+
return self._client._request(
|
|
65
|
+
"POST",
|
|
66
|
+
_EMAIL_TO_PERSON,
|
|
67
|
+
body={"email": email},
|
|
68
|
+
cast_to=EmailToPersonResponse,
|
|
69
|
+
timeout=timeout,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def phone_to_person(
|
|
73
|
+
self, *, phone: str, timeout: TimeoutParam = None
|
|
74
|
+
) -> PhoneToPersonResponse:
|
|
75
|
+
"""Resolve a phone number to a full person profile."""
|
|
76
|
+
return self._client._request(
|
|
77
|
+
"POST",
|
|
78
|
+
_PHONE_TO_PERSON,
|
|
79
|
+
body={"phone": phone},
|
|
80
|
+
cast_to=PhoneToPersonResponse,
|
|
81
|
+
timeout=timeout,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def company(
|
|
85
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
86
|
+
) -> CompanyEnrichmentResponse:
|
|
87
|
+
"""Resolve a company LinkedIn URL to a full company profile."""
|
|
88
|
+
return self._client._request(
|
|
89
|
+
"POST",
|
|
90
|
+
_COMPANY,
|
|
91
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
92
|
+
cast_to=CompanyEnrichmentResponse,
|
|
93
|
+
timeout=timeout,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def domain_to_linkedin(
|
|
97
|
+
self, *, domain: str, timeout: TimeoutParam = None
|
|
98
|
+
) -> DomainToLinkedinResponse:
|
|
99
|
+
"""Resolve a website domain to a company LinkedIn URL."""
|
|
100
|
+
return self._client._request(
|
|
101
|
+
"POST",
|
|
102
|
+
_DOMAIN_TO_LINKEDIN,
|
|
103
|
+
body={"domain": domain},
|
|
104
|
+
cast_to=DomainToLinkedinResponse,
|
|
105
|
+
timeout=timeout,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def linkedin_to_domain(
|
|
109
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
110
|
+
) -> LinkedinToDomainResponse:
|
|
111
|
+
"""Resolve a company LinkedIn URL to its email domain."""
|
|
112
|
+
return self._client._request(
|
|
113
|
+
"POST",
|
|
114
|
+
_LINKEDIN_TO_DOMAIN,
|
|
115
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
116
|
+
cast_to=LinkedinToDomainResponse,
|
|
117
|
+
timeout=timeout,
|
|
118
|
+
)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# This file is @generated by scripts/gen_sync.py from src/blitz_api/resources/_async/search.py.
|
|
2
|
+
# Do not edit by hand — edit the async source and run `python scripts/gen_sync.py`.
|
|
3
|
+
"""The Search resource: ``client.search``."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from ..._compat import TimeoutParam
|
|
10
|
+
from ..._pagination_sync import CursorPage, PageNumberPage
|
|
11
|
+
from ...types.filters import (
|
|
12
|
+
CascadeTier,
|
|
13
|
+
CompanyFilter,
|
|
14
|
+
ContinentValue,
|
|
15
|
+
JobFunctionValue,
|
|
16
|
+
JobLevelValue,
|
|
17
|
+
PeopleFilter,
|
|
18
|
+
SalesRegionValue,
|
|
19
|
+
)
|
|
20
|
+
from ...types.search import WaterfallIcpResponse
|
|
21
|
+
from ...types.shared import Company, Person
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from ..._client import BlitzAPI
|
|
25
|
+
|
|
26
|
+
_PEOPLE = "/v2/search/people"
|
|
27
|
+
_COMPANIES = "/v2/search/companies"
|
|
28
|
+
_EMPLOYEE_FINDER = "/v2/search/employee-finder"
|
|
29
|
+
_WATERFALL = "/v2/search/waterfall-icp-keyword"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _drop_none(**kwargs: Any) -> dict[str, Any]:
|
|
33
|
+
"""Build a request body keeping only the arguments the caller provided."""
|
|
34
|
+
return {key: value for key, value in kwargs.items() if value is not None}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _employee_finder_body(
|
|
38
|
+
*,
|
|
39
|
+
company_linkedin_url: str,
|
|
40
|
+
country_code: list[str] | None,
|
|
41
|
+
continent: list[ContinentValue] | None,
|
|
42
|
+
sales_region: list[SalesRegionValue] | None,
|
|
43
|
+
job_level: list[JobLevelValue] | None,
|
|
44
|
+
job_function: list[JobFunctionValue] | None,
|
|
45
|
+
min_connections_count: int | None,
|
|
46
|
+
max_results: int | None,
|
|
47
|
+
page: int | None,
|
|
48
|
+
) -> dict[str, Any]:
|
|
49
|
+
return _drop_none(
|
|
50
|
+
company_linkedin_url=company_linkedin_url,
|
|
51
|
+
country_code=country_code,
|
|
52
|
+
continent=continent,
|
|
53
|
+
sales_region=sales_region,
|
|
54
|
+
job_level=job_level,
|
|
55
|
+
job_function=job_function,
|
|
56
|
+
min_connections_count=min_connections_count,
|
|
57
|
+
max_results=max_results,
|
|
58
|
+
page=page,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SearchResource:
|
|
63
|
+
def __init__(self, client: BlitzAPI) -> None:
|
|
64
|
+
self._client = client
|
|
65
|
+
|
|
66
|
+
def people(
|
|
67
|
+
self,
|
|
68
|
+
*,
|
|
69
|
+
company: CompanyFilter | None = None,
|
|
70
|
+
people: PeopleFilter | None = None,
|
|
71
|
+
max_results: int | None = None,
|
|
72
|
+
cursor: str | None = None,
|
|
73
|
+
timeout: TimeoutParam = None,
|
|
74
|
+
) -> CursorPage[Person]:
|
|
75
|
+
"""Search people across many companies, combining company and persona filters.
|
|
76
|
+
|
|
77
|
+
Auto-paginates over every matching person when the result is iterated; use
|
|
78
|
+
``.iter_pages()`` or the ``cursor=`` arg for manual control.
|
|
79
|
+
"""
|
|
80
|
+
body = _drop_none(company=company, people=people, max_results=max_results, cursor=cursor)
|
|
81
|
+
return self._client._request(
|
|
82
|
+
"POST", _PEOPLE, body=body, cast_to=CursorPage[Person], timeout=timeout
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def companies(
|
|
86
|
+
self,
|
|
87
|
+
*,
|
|
88
|
+
company: CompanyFilter | None = None,
|
|
89
|
+
max_results: int | None = None,
|
|
90
|
+
cursor: str | None = None,
|
|
91
|
+
timeout: TimeoutParam = None,
|
|
92
|
+
) -> CursorPage[Company]:
|
|
93
|
+
"""Find companies matching ICP filters (industry, size, HQ, revenue, ...).
|
|
94
|
+
|
|
95
|
+
Auto-paginates over every matching company; use ``.iter_pages()`` or ``cursor=``
|
|
96
|
+
for manual control.
|
|
97
|
+
"""
|
|
98
|
+
body = _drop_none(company=company, max_results=max_results, cursor=cursor)
|
|
99
|
+
return self._client._request(
|
|
100
|
+
"POST", _COMPANIES, body=body, cast_to=CursorPage[Company], timeout=timeout
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def employee_finder(
|
|
104
|
+
self,
|
|
105
|
+
*,
|
|
106
|
+
company_linkedin_url: str,
|
|
107
|
+
country_code: list[str] | None = None,
|
|
108
|
+
continent: list[ContinentValue] | None = None,
|
|
109
|
+
sales_region: list[SalesRegionValue] | None = None,
|
|
110
|
+
job_level: list[JobLevelValue] | None = None,
|
|
111
|
+
job_function: list[JobFunctionValue] | None = None,
|
|
112
|
+
min_connections_count: int | None = None,
|
|
113
|
+
max_results: int | None = None,
|
|
114
|
+
page: int | None = None,
|
|
115
|
+
timeout: TimeoutParam = None,
|
|
116
|
+
) -> PageNumberPage[Person]:
|
|
117
|
+
"""Search employees at a single company, with page-based pagination.
|
|
118
|
+
|
|
119
|
+
Auto-paginates over every matching employee; use ``.iter_pages()`` or ``page=``
|
|
120
|
+
for manual control.
|
|
121
|
+
"""
|
|
122
|
+
body = _employee_finder_body(
|
|
123
|
+
company_linkedin_url=company_linkedin_url,
|
|
124
|
+
country_code=country_code,
|
|
125
|
+
continent=continent,
|
|
126
|
+
sales_region=sales_region,
|
|
127
|
+
job_level=job_level,
|
|
128
|
+
job_function=job_function,
|
|
129
|
+
min_connections_count=min_connections_count,
|
|
130
|
+
max_results=max_results,
|
|
131
|
+
page=page,
|
|
132
|
+
)
|
|
133
|
+
return self._client._request(
|
|
134
|
+
"POST",
|
|
135
|
+
_EMPLOYEE_FINDER,
|
|
136
|
+
body=body,
|
|
137
|
+
cast_to=PageNumberPage[Person],
|
|
138
|
+
timeout=timeout,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
def waterfall_icp(
|
|
142
|
+
self,
|
|
143
|
+
*,
|
|
144
|
+
company_linkedin_url: str,
|
|
145
|
+
cascade: list[CascadeTier],
|
|
146
|
+
max_results: int | None = None,
|
|
147
|
+
timeout: TimeoutParam = None,
|
|
148
|
+
) -> WaterfallIcpResponse:
|
|
149
|
+
"""Find the best decision-maker at a company via a prioritized cascade."""
|
|
150
|
+
body = _drop_none(
|
|
151
|
+
company_linkedin_url=company_linkedin_url, cascade=cascade, max_results=max_results
|
|
152
|
+
)
|
|
153
|
+
return self._client._request(
|
|
154
|
+
"POST", _WATERFALL, body=body, cast_to=WaterfallIcpResponse, timeout=timeout
|
|
155
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# This file is @generated by scripts/gen_sync.py from src/blitz_api/resources/_async/utils.py.
|
|
2
|
+
# Do not edit by hand — edit the async source and run `python scripts/gen_sync.py`.
|
|
3
|
+
"""The Utilities resource: ``client.utils``."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
from ..._compat import TimeoutParam
|
|
10
|
+
from ...types.utils import CompanyEmploymentDistributionResponse, CurrentDateResponse
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ..._client import BlitzAPI
|
|
14
|
+
|
|
15
|
+
_CURRENT_DATE = "/v2/utils/current-date"
|
|
16
|
+
_EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class UtilsResource:
|
|
20
|
+
def __init__(self, client: BlitzAPI) -> None:
|
|
21
|
+
self._client = client
|
|
22
|
+
|
|
23
|
+
def current_date(
|
|
24
|
+
self, *, region: str, timeout: TimeoutParam = None
|
|
25
|
+
) -> CurrentDateResponse:
|
|
26
|
+
"""Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
|
|
27
|
+
return self._client._request(
|
|
28
|
+
"POST",
|
|
29
|
+
_CURRENT_DATE,
|
|
30
|
+
body={"region": region},
|
|
31
|
+
cast_to=CurrentDateResponse,
|
|
32
|
+
timeout=timeout,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def company_employment_distribution(
|
|
36
|
+
self, *, company_linkedin_url: str, timeout: TimeoutParam = None
|
|
37
|
+
) -> CompanyEmploymentDistributionResponse:
|
|
38
|
+
"""Get a company's employee count broken down by country."""
|
|
39
|
+
return self._client._request(
|
|
40
|
+
"POST",
|
|
41
|
+
_EMPLOYMENT_DISTRIBUTION,
|
|
42
|
+
body={"company_linkedin_url": company_linkedin_url},
|
|
43
|
+
cast_to=CompanyEmploymentDistributionResponse,
|
|
44
|
+
timeout=timeout,
|
|
45
|
+
)
|