blitz-api-py 0.4.0__tar.gz → 1.0.0__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 (46) hide show
  1. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/CHANGELOG.md +18 -0
  2. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/PKG-INFO +10 -7
  3. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/README.md +9 -6
  4. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_client_async.py +23 -2
  5. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_client_sync.py +23 -2
  6. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_rate_limit_async.py +6 -4
  7. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_rate_limit_sync.py +6 -4
  8. blitz_api_py-1.0.0/src/blitz_api/_version.py +1 -0
  9. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_async/enrichment.py +35 -0
  10. blitz_api_py-1.0.0/src/blitz_api/resources/_async/utils.py +30 -0
  11. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_sync/enrichment.py +35 -0
  12. blitz_api_py-1.0.0/src/blitz_api/resources/_sync/utils.py +32 -0
  13. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/__init__.py +12 -8
  14. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/enrichment.py +53 -0
  15. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/enums.py +27 -0
  16. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/filters.py +15 -0
  17. blitz_api_py-1.0.0/src/blitz_api/types/utils.py +18 -0
  18. blitz_api_py-0.4.0/src/blitz_api/_version.py +0 -1
  19. blitz_api_py-0.4.0/src/blitz_api/resources/_async/utils.py +0 -63
  20. blitz_api_py-0.4.0/src/blitz_api/resources/_sync/utils.py +0 -65
  21. blitz_api_py-0.4.0/src/blitz_api/types/utils.py +0 -55
  22. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/.gitignore +0 -0
  23. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/LICENSE +0 -0
  24. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/pyproject.toml +0 -0
  25. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/__init__.py +0 -0
  26. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_base_client.py +0 -0
  27. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_client.py +0 -0
  28. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_compat.py +0 -0
  29. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_constants.py +0 -0
  30. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_exceptions.py +0 -0
  31. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_pagination_async.py +0 -0
  32. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_pagination_base.py +0 -0
  33. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_pagination_sync.py +0 -0
  34. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/_rate_limit.py +0 -0
  35. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/py.typed +0 -0
  36. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/__init__.py +0 -0
  37. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_async/__init__.py +0 -0
  38. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_async/account.py +0 -0
  39. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_async/search.py +0 -0
  40. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_sync/__init__.py +0 -0
  41. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_sync/account.py +0 -0
  42. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/resources/_sync/search.py +0 -0
  43. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/_models.py +0 -0
  44. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/account.py +0 -0
  45. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/search.py +0 -0
  46. {blitz_api_py-0.4.0 → blitz_api_py-1.0.0}/src/blitz_api/types/shared.py +0 -0
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.0](https://github.com/api-blitz/blitz-api-py/compare/v0.5.0...v1.0.0) (2026-06-19)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * funding/HQ-state search filters + relocate distribution endpoints ([#15](https://github.com/api-blitz/blitz-api-py/issues/15))
9
+
10
+ ### Features
11
+
12
+ * funding/HQ-state search filters + relocate distribution endpoints ([#15](https://github.com/api-blitz/blitz-api-py/issues/15)) ([f711ee8](https://github.com/api-blitz/blitz-api-py/commit/f711ee81a9e046bd7e354b593eda9e8d978768e3))
13
+
14
+ ## [0.5.0](https://github.com/api-blitz/blitz-api-py/compare/v0.4.0...v0.5.0) (2026-06-18)
15
+
16
+
17
+ ### Features
18
+
19
+ * scope client-side rate limiting per endpoint ([#13](https://github.com/api-blitz/blitz-api-py/issues/13)) ([de5308b](https://github.com/api-blitz/blitz-api-py/commit/de5308b6995edc68dd1e43a8554296b7de095df2))
20
+
3
21
  ## [0.4.0](https://github.com/api-blitz/blitz-api-py/compare/v0.3.0...v0.4.0) (2026-06-17)
4
22
 
5
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blitz-api-py
3
- Version: 0.4.0
3
+ Version: 1.0.0
4
4
  Summary: Typed Python SDK for the Blitz API — B2B data, search, and enrichment.
5
5
  Project-URL: Homepage, https://blitz-api.ai
6
6
  Project-URL: Documentation, https://docs.blitz-api.ai
@@ -199,8 +199,8 @@ All methods are grouped into four namespaces:
199
199
  | --- | --- |
200
200
  | `client.account` | `key_info()` |
201
201
  | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
202
- | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()` |
203
- | `client.utils` | `current_date()`, `company_employment_distribution()`, `company_department_distribution()` |
202
+ | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()`, `company_distribution_by_country()`, `company_distribution_by_department()` |
203
+ | `client.utils` | `current_date()` |
204
204
 
205
205
  Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
206
206
  filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
@@ -258,10 +258,13 @@ client = BlitzAPI(
258
258
  ```
259
259
 
260
260
  The client-side rate limiter is a sliding window — at most `rate_limit_rps` requests
261
- in any rolling second — so a single client instance stays under the API's limit (5 req/s
262
- by default; check your key's limit via
263
- `client.account.key_info().max_requests_per_seconds`). Across multiple processes you may
264
- still hit `429` the retry path handles that.
261
+ in any rolling second — applied **per endpoint**: each endpoint (e.g. `.email` vs
262
+ `.phone`) is throttled independently, mirroring the API's own limit, which is also per
263
+ endpoint (5 req/s by default; check yours via
264
+ `client.account.key_info().max_requests_per_seconds`). A single client instance therefore
265
+ stays under the limit on every endpoint, so a burst on one never blocks another. Across
266
+ multiple processes — which share an endpoint's budget — you may still hit `429`; the retry
267
+ path handles that.
265
268
 
266
269
  Every method also accepts a per-call `timeout` (seconds or an `httpx.Timeout`) when one
267
270
  endpoint needs longer than the client default:
@@ -168,8 +168,8 @@ All methods are grouped into four namespaces:
168
168
  | --- | --- |
169
169
  | `client.account` | `key_info()` |
170
170
  | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
171
- | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()` |
172
- | `client.utils` | `current_date()`, `company_employment_distribution()`, `company_department_distribution()` |
171
+ | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()`, `company_distribution_by_country()`, `company_distribution_by_department()` |
172
+ | `client.utils` | `current_date()` |
173
173
 
174
174
  Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
175
175
  filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
@@ -227,10 +227,13 @@ client = BlitzAPI(
227
227
  ```
228
228
 
229
229
  The client-side rate limiter is a sliding window — at most `rate_limit_rps` requests
230
- in any rolling second — so a single client instance stays under the API's limit (5 req/s
231
- by default; check your key's limit via
232
- `client.account.key_info().max_requests_per_seconds`). Across multiple processes you may
233
- still hit `429` the retry path handles that.
230
+ in any rolling second — applied **per endpoint**: each endpoint (e.g. `.email` vs
231
+ `.phone`) is throttled independently, mirroring the API's own limit, which is also per
232
+ endpoint (5 req/s by default; check yours via
233
+ `client.account.key_info().max_requests_per_seconds`). A single client instance therefore
234
+ stays under the limit on every endpoint, so a burst on one never blocks another. Across
235
+ multiple processes — which share an endpoint's budget — you may still hit `429`; the retry
236
+ path handles that.
234
237
 
235
238
  Every method also accepts a per-call `timeout` (seconds or an `httpx.Timeout`) when one
236
239
  endpoint needs longer than the client default:
@@ -50,13 +50,34 @@ class AsyncBlitzAPI(BaseClient):
50
50
  )
51
51
  self._http_client = http_client or httpx.AsyncClient(timeout=timeout)
52
52
  self._owns_http_client = http_client is None
53
- self._rate_limiter = AsyncRateLimiter(rate_limit_rps)
53
+ self._rate_limit_rps = rate_limit_rps
54
+ # One limiter per endpoint path so each endpoint's rate limit is tracked
55
+ # independently (e.g. ``.email`` and ``.phone`` do not share a budget). Built
56
+ # lazily in ``_limiter_for`` on first use of each path.
57
+ self._rate_limiters: dict[str, AsyncRateLimiter] = {}
54
58
  if sleep is None:
55
59
  import asyncio
56
60
 
57
61
  sleep = asyncio.sleep
58
62
  self._sleep = sleep
59
63
 
64
+ def _limiter_for(self, path: str) -> AsyncRateLimiter:
65
+ """Return the per-endpoint limiter for ``path``, creating it on first use.
66
+
67
+ Each endpoint path gets its own sliding window so its rate limit is tracked
68
+ independently of every other endpoint.
69
+ """
70
+ limiter = self._rate_limiters.get(path)
71
+ if limiter is None:
72
+ # ``setdefault`` keeps concurrent first-callers on the same instance; any
73
+ # extra limiter built in a race is harmlessly discarded. Thread the client's
74
+ # ``sleep`` through so a custom/fake sleep injected for tests also drives the
75
+ # limiter's throttle wait, not just the retry backoff.
76
+ limiter = self._rate_limiters.setdefault(
77
+ path, AsyncRateLimiter(self._rate_limit_rps, sleep=self._sleep)
78
+ )
79
+ return limiter
80
+
60
81
  async def _request(
61
82
  self,
62
83
  method: str,
@@ -72,7 +93,7 @@ class AsyncBlitzAPI(BaseClient):
72
93
 
73
94
  attempt = 0
74
95
  while True:
75
- await self._rate_limiter.acquire()
96
+ await self._limiter_for(path).acquire()
76
97
  try:
77
98
  if timeout is None:
78
99
  response = await self._http_client.request(
@@ -52,13 +52,34 @@ class BlitzAPI(BaseClient):
52
52
  )
53
53
  self._http_client = http_client or httpx.Client(timeout=timeout)
54
54
  self._owns_http_client = http_client is None
55
- self._rate_limiter = RateLimiter(rate_limit_rps)
55
+ self._rate_limit_rps = rate_limit_rps
56
+ # One limiter per endpoint path so each endpoint's rate limit is tracked
57
+ # independently (e.g. ``.email`` and ``.phone`` do not share a budget). Built
58
+ # lazily in ``_limiter_for`` on first use of each path.
59
+ self._rate_limiters: dict[str, RateLimiter] = {}
56
60
  if sleep is None:
57
61
  import time
58
62
 
59
63
  sleep = time.sleep
60
64
  self._sleep = sleep
61
65
 
66
+ def _limiter_for(self, path: str) -> RateLimiter:
67
+ """Return the per-endpoint limiter for ``path``, creating it on first use.
68
+
69
+ Each endpoint path gets its own sliding window so its rate limit is tracked
70
+ independently of every other endpoint.
71
+ """
72
+ limiter = self._rate_limiters.get(path)
73
+ if limiter is None:
74
+ # ``setdefault`` keeps concurrent first-callers on the same instance; any
75
+ # extra limiter built in a race is harmlessly discarded. Thread the client's
76
+ # ``sleep`` through so a custom/fake sleep injected for tests also drives the
77
+ # limiter's throttle wait, not just the retry backoff.
78
+ limiter = self._rate_limiters.setdefault(
79
+ path, RateLimiter(self._rate_limit_rps, sleep=self._sleep)
80
+ )
81
+ return limiter
82
+
62
83
  def _request(
63
84
  self,
64
85
  method: str,
@@ -74,7 +95,7 @@ class BlitzAPI(BaseClient):
74
95
 
75
96
  attempt = 0
76
97
  while True:
77
- self._rate_limiter.acquire()
98
+ self._limiter_for(path).acquire()
78
99
  try:
79
100
  if timeout is None:
80
101
  response = self._http_client.request(
@@ -1,9 +1,11 @@
1
1
  """Client-side sliding-window rate limiter (async source; sync twin generated).
2
2
 
3
- The API enforces a per-key request rate (5 req/s by default). This limiter throttles
4
- outgoing requests *before* they are sent so a single client instance stays under the
5
- limit proactively; the server-side 429 retry path is the backstop for bursts across
6
- processes.
3
+ The API enforces a per-endpoint request rate (5 req/s by default). This limiter throttles
4
+ outgoing requests *before* they are sent. The client holds one limiter **per endpoint
5
+ path** (see ``_client_async.py``), so each endpoint is throttled to ``rps`` independently,
6
+ mirroring the server's per-endpoint budget; a single client instance therefore stays under
7
+ the limit on every endpoint on its own. The server-side 429 retry path is the backstop for
8
+ bursts across processes, which share the same per-endpoint budget.
7
9
 
8
10
  The algorithm is a sliding window: at most ``rps`` requests may begin in any rolling
9
11
  one-second window. This matches the Blitz docs ("max 5 requests per 1000 ms") and the
@@ -2,10 +2,12 @@
2
2
  # Do not edit by hand — edit the async source and run `python scripts/gen_sync.py`.
3
3
  """Client-side sliding-window rate limiter (async source; sync twin generated).
4
4
 
5
- The API enforces a per-key request rate (5 req/s by default). This limiter throttles
6
- outgoing requests *before* they are sent so a single client instance stays under the
7
- limit proactively; the server-side 429 retry path is the backstop for bursts across
8
- processes.
5
+ The API enforces a per-endpoint request rate (5 req/s by default). This limiter throttles
6
+ outgoing requests *before* they are sent. The client holds one limiter **per endpoint
7
+ path** (see ``_client_async.py``), so each endpoint is throttled to ``rps`` independently,
8
+ mirroring the server's per-endpoint budget; a single client instance therefore stays under
9
+ the limit on every endpoint on its own. The server-side 429 retry path is the backstop for
10
+ bursts across processes, which share the same per-endpoint budget.
9
11
 
10
12
  The algorithm is a sliding window: at most ``rps`` requests may begin in any rolling
11
13
  one-second window. This matches the Blitz docs ("max 5 requests per 1000 ms") and the
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0" # x-release-please-version
@@ -6,6 +6,8 @@ from typing import TYPE_CHECKING
6
6
 
7
7
  from ..._compat import TimeoutParam
8
8
  from ...types.enrichment import (
9
+ CompanyCountryDistributionResponse,
10
+ CompanyDepartmentDistributionResponse,
9
11
  CompanyEnrichmentResponse,
10
12
  DomainToLinkedinResponse,
11
13
  EmailEnrichmentResponse,
@@ -25,6 +27,8 @@ _PHONE_TO_PERSON = "/v2/enrichment/phone-to-person"
25
27
  _COMPANY = "/v2/enrichment/company"
26
28
  _DOMAIN_TO_LINKEDIN = "/v2/enrichment/domain-to-linkedin"
27
29
  _LINKEDIN_TO_DOMAIN = "/v2/enrichment/linkedin-to-domain"
30
+ _DISTRIBUTION_BY_COUNTRY = "/v2/enrichment/company-distribution-by-country"
31
+ _DISTRIBUTION_BY_DEPARTMENT = "/v2/enrichment/company-distribution-by-department"
28
32
 
29
33
 
30
34
  class AsyncEnrichmentResource:
@@ -114,3 +118,34 @@ class AsyncEnrichmentResource:
114
118
  cast_to=LinkedinToDomainResponse,
115
119
  timeout=timeout,
116
120
  )
121
+
122
+ async def company_distribution_by_country(
123
+ self, *, company_linkedin_url: str, timeout: TimeoutParam = None
124
+ ) -> CompanyCountryDistributionResponse:
125
+ """Get a company's employee count broken down by country.
126
+
127
+ Countries are reported as ISO 3166-1 alpha-2 codes (e.g. ``US``, ``GB``);
128
+ employees whose country can't be determined are bucketed under ``"unknown"``.
129
+ """
130
+ return await self._client._request(
131
+ "POST",
132
+ _DISTRIBUTION_BY_COUNTRY,
133
+ body={"company_linkedin_url": company_linkedin_url},
134
+ cast_to=CompanyCountryDistributionResponse,
135
+ timeout=timeout,
136
+ )
137
+
138
+ async def company_distribution_by_department(
139
+ self, *, company_linkedin_url: str, timeout: TimeoutParam = None
140
+ ) -> CompanyDepartmentDistributionResponse:
141
+ """Get a company's employee count broken down by department.
142
+
143
+ Employees with no classified department are counted under ``"Other"``.
144
+ """
145
+ return await self._client._request(
146
+ "POST",
147
+ _DISTRIBUTION_BY_DEPARTMENT,
148
+ body={"company_linkedin_url": company_linkedin_url},
149
+ cast_to=CompanyDepartmentDistributionResponse,
150
+ timeout=timeout,
151
+ )
@@ -0,0 +1,30 @@
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 CurrentDateResponse
9
+
10
+ if TYPE_CHECKING:
11
+ from ..._client import AsyncBlitzAPI
12
+
13
+ _CURRENT_DATE = "/v2/utils/current-date"
14
+
15
+
16
+ class AsyncUtilsResource:
17
+ def __init__(self, client: AsyncBlitzAPI) -> None:
18
+ self._client = client
19
+
20
+ async def current_date(
21
+ self, *, region: str, timeout: TimeoutParam = None
22
+ ) -> CurrentDateResponse:
23
+ """Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
24
+ return await self._client._request(
25
+ "POST",
26
+ _CURRENT_DATE,
27
+ body={"region": region},
28
+ cast_to=CurrentDateResponse,
29
+ timeout=timeout,
30
+ )
@@ -8,6 +8,8 @@ from typing import TYPE_CHECKING
8
8
 
9
9
  from ..._compat import TimeoutParam
10
10
  from ...types.enrichment import (
11
+ CompanyCountryDistributionResponse,
12
+ CompanyDepartmentDistributionResponse,
11
13
  CompanyEnrichmentResponse,
12
14
  DomainToLinkedinResponse,
13
15
  EmailEnrichmentResponse,
@@ -27,6 +29,8 @@ _PHONE_TO_PERSON = "/v2/enrichment/phone-to-person"
27
29
  _COMPANY = "/v2/enrichment/company"
28
30
  _DOMAIN_TO_LINKEDIN = "/v2/enrichment/domain-to-linkedin"
29
31
  _LINKEDIN_TO_DOMAIN = "/v2/enrichment/linkedin-to-domain"
32
+ _DISTRIBUTION_BY_COUNTRY = "/v2/enrichment/company-distribution-by-country"
33
+ _DISTRIBUTION_BY_DEPARTMENT = "/v2/enrichment/company-distribution-by-department"
30
34
 
31
35
 
32
36
  class EnrichmentResource:
@@ -116,3 +120,34 @@ class EnrichmentResource:
116
120
  cast_to=LinkedinToDomainResponse,
117
121
  timeout=timeout,
118
122
  )
123
+
124
+ def company_distribution_by_country(
125
+ self, *, company_linkedin_url: str, timeout: TimeoutParam = None
126
+ ) -> CompanyCountryDistributionResponse:
127
+ """Get a company's employee count broken down by country.
128
+
129
+ Countries are reported as ISO 3166-1 alpha-2 codes (e.g. ``US``, ``GB``);
130
+ employees whose country can't be determined are bucketed under ``"unknown"``.
131
+ """
132
+ return self._client._request(
133
+ "POST",
134
+ _DISTRIBUTION_BY_COUNTRY,
135
+ body={"company_linkedin_url": company_linkedin_url},
136
+ cast_to=CompanyCountryDistributionResponse,
137
+ timeout=timeout,
138
+ )
139
+
140
+ def company_distribution_by_department(
141
+ self, *, company_linkedin_url: str, timeout: TimeoutParam = None
142
+ ) -> CompanyDepartmentDistributionResponse:
143
+ """Get a company's employee count broken down by department.
144
+
145
+ Employees with no classified department are counted under ``"Other"``.
146
+ """
147
+ return self._client._request(
148
+ "POST",
149
+ _DISTRIBUTION_BY_DEPARTMENT,
150
+ body={"company_linkedin_url": company_linkedin_url},
151
+ cast_to=CompanyDepartmentDistributionResponse,
152
+ timeout=timeout,
153
+ )
@@ -0,0 +1,32 @@
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 CurrentDateResponse
11
+
12
+ if TYPE_CHECKING:
13
+ from ..._client import BlitzAPI
14
+
15
+ _CURRENT_DATE = "/v2/utils/current-date"
16
+
17
+
18
+ class UtilsResource:
19
+ def __init__(self, client: BlitzAPI) -> None:
20
+ self._client = client
21
+
22
+ def current_date(
23
+ self, *, region: str, timeout: TimeoutParam = None
24
+ ) -> CurrentDateResponse:
25
+ """Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
26
+ return self._client._request(
27
+ "POST",
28
+ _CURRENT_DATE,
29
+ body={"region": region},
30
+ cast_to=CurrentDateResponse,
31
+ timeout=timeout,
32
+ )
@@ -9,7 +9,11 @@ from __future__ import annotations
9
9
 
10
10
  from .account import ActivePlan, KeyInfo
11
11
  from .enrichment import (
12
+ CompanyCountryDistributionResponse,
13
+ CompanyDepartmentDistributionResponse,
12
14
  CompanyEnrichmentResponse,
15
+ CountryDistributionItem,
16
+ DepartmentDistributionItem,
13
17
  DomainToLinkedinResponse,
14
18
  EmailEnrichmentResponse,
15
19
  EmailMatch,
@@ -22,6 +26,7 @@ from .enums import (
22
26
  CompanyType,
23
27
  Continent,
24
28
  EmployeeRange,
29
+ FundingType,
25
30
  Industry,
26
31
  JobFunction,
27
32
  JobLevel,
@@ -32,6 +37,7 @@ from .filters import (
32
37
  CompanyFilter,
33
38
  CompanyHQFilter,
34
39
  CompanyTypeFilter,
40
+ FundingTypeFilter,
35
41
  IndustryFilter,
36
42
  KeywordFilter,
37
43
  PeopleFilter,
@@ -53,11 +59,7 @@ from .shared import (
53
59
  Person,
54
60
  )
55
61
  from .utils import (
56
- CompanyDepartmentDistributionResponse,
57
- CompanyEmploymentDistributionResponse,
58
62
  CurrentDateResponse,
59
- DepartmentDistributionItem,
60
- EmploymentDistributionItem,
61
63
  )
62
64
 
63
65
  __all__ = [
@@ -73,6 +75,7 @@ __all__ = [
73
75
  "Industry",
74
76
  "CompanyType",
75
77
  "EmployeeRange",
78
+ "FundingType",
76
79
  "Continent",
77
80
  "SalesRegion",
78
81
  "JobFunction",
@@ -81,6 +84,7 @@ __all__ = [
81
84
  "KeywordFilter",
82
85
  "IndustryFilter",
83
86
  "CompanyTypeFilter",
87
+ "FundingTypeFilter",
84
88
  "RangeFilter",
85
89
  "CompanyHQFilter",
86
90
  "CompanyFilter",
@@ -103,10 +107,10 @@ __all__ = [
103
107
  "CompanyEnrichmentResponse",
104
108
  "DomainToLinkedinResponse",
105
109
  "LinkedinToDomainResponse",
106
- # utils
107
- "CurrentDateResponse",
108
- "EmploymentDistributionItem",
109
- "CompanyEmploymentDistributionResponse",
110
+ "CountryDistributionItem",
111
+ "CompanyCountryDistributionResponse",
110
112
  "DepartmentDistributionItem",
111
113
  "CompanyDepartmentDistributionResponse",
114
+ # utils
115
+ "CurrentDateResponse",
112
116
  ]
@@ -14,6 +14,10 @@ __all__ = [
14
14
  "CompanyEnrichmentResponse",
15
15
  "DomainToLinkedinResponse",
16
16
  "LinkedinToDomainResponse",
17
+ "CountryDistributionItem",
18
+ "CompanyCountryDistributionResponse",
19
+ "DepartmentDistributionItem",
20
+ "CompanyDepartmentDistributionResponse",
17
21
  ]
18
22
 
19
23
 
@@ -74,3 +78,52 @@ class LinkedinToDomainResponse(BlitzModel):
74
78
 
75
79
  found: bool | None = None
76
80
  email_domain: str | None = None
81
+
82
+
83
+ class CountryDistributionItem(BlitzModel):
84
+ """Employee count for a single country.
85
+
86
+ ``country`` is an ISO 3166-1 alpha-2 code (e.g. ``"US"``, ``"GB"``), or the
87
+ literal ``"unknown"`` bucket for employees whose country couldn't be determined.
88
+ ``percentage_ratio`` is the bucket's share of ``total_employees`` (0-100, to 2
89
+ decimals).
90
+ """
91
+
92
+ country: str | None = None
93
+ count: int | None = None
94
+ percentage_ratio: float | None = None
95
+
96
+
97
+ class CompanyCountryDistributionResponse(BlitzModel):
98
+ """Result of ``enrichment.company_distribution_by_country``.
99
+
100
+ Served by ``POST /v2/enrichment/company-distribution-by-country``.
101
+ """
102
+
103
+ company_linkedin_url: str | None = None
104
+ total_employees: int | None = None
105
+ distribution: list[CountryDistributionItem] = []
106
+
107
+
108
+ class DepartmentDistributionItem(BlitzModel):
109
+ """Employee count for a single department (Blitz job function).
110
+
111
+ Employees with no classified department are counted under ``"Other"``.
112
+ ``percentage_ratio`` is the bucket's share of ``total_employees`` (0-100, to 2
113
+ decimals).
114
+ """
115
+
116
+ department: str | None = None
117
+ count: int | None = None
118
+ percentage_ratio: float | None = None
119
+
120
+
121
+ class CompanyDepartmentDistributionResponse(BlitzModel):
122
+ """Result of ``enrichment.company_distribution_by_department``.
123
+
124
+ Served by ``POST /v2/enrichment/company-distribution-by-department``.
125
+ """
126
+
127
+ company_linkedin_url: str | None = None
128
+ total_employees: int | None = None
129
+ distribution: list[DepartmentDistributionItem] = []
@@ -18,6 +18,7 @@ __all__ = [
18
18
  "SalesRegion",
19
19
  "JobFunction",
20
20
  "JobLevel",
21
+ "FundingType",
21
22
  ]
22
23
 
23
24
 
@@ -631,3 +632,29 @@ class JobLevel(str, Enum):
631
632
  OTHER = 'Other'
632
633
  STAFF = 'Staff'
633
634
  VP = 'VP'
635
+
636
+
637
+ class FundingType(str, Enum):
638
+ SERIES_UNKNOWN = 'Series unknown'
639
+ PRE_SEED = 'Pre seed'
640
+ SEED = 'Seed'
641
+ SERIES_A = 'Series A'
642
+ SERIES_B = 'Series B'
643
+ SERIES_C = 'Series C'
644
+ SERIES_D = 'Series D'
645
+ SERIES_E_J = 'Series E-J'
646
+ GRANT = 'Grant'
647
+ ANGEL = 'Angel'
648
+ PRIVATE_EQUITY = 'Private equity'
649
+ DEBT_FINANCING = 'Debt financing'
650
+ NON_EQUITY_ASSISTANCE = 'Non equity assistance'
651
+ POST_IPO_EQUITY = 'Post IPO equity'
652
+ UNDISCLOSED = 'Undisclosed'
653
+ POST_IPO_DEBT = 'Post IPO debt'
654
+ PRODUCT_CROWDFUNDING = 'Product crowdfunding'
655
+ EQUITY_CROWDFUNDING = 'Equity crowdfunding'
656
+ CORPORATE_ROUND = 'Corporate round'
657
+ CONVERTIBLE_NOTE = 'Convertible note'
658
+ SECONDARY_MARKET = 'Secondary market'
659
+ INITIAL_COIN_OFFERING = 'Initial coin offering'
660
+ POST_IPO_SECONDARY = 'Post IPO secondary'
@@ -16,6 +16,7 @@ from .enums import (
16
16
  CompanyType,
17
17
  Continent,
18
18
  EmployeeRange,
19
+ FundingType,
19
20
  Industry,
20
21
  JobFunction,
21
22
  JobLevel,
@@ -30,6 +31,7 @@ from .enums import (
30
31
  IndustryValue = Industry | str
31
32
  CompanyTypeValue = CompanyType | str
32
33
  EmployeeRangeValue = EmployeeRange | str
34
+ FundingTypeValue = FundingType | str
33
35
  ContinentValue = Continent | str
34
36
  SalesRegionValue = SalesRegion | str
35
37
  JobFunctionValue = JobFunction | str
@@ -57,6 +59,13 @@ class CompanyTypeFilter(TypedDict, total=False):
57
59
  exclude: list[CompanyTypeValue]
58
60
 
59
61
 
62
+ class FundingTypeFilter(TypedDict, total=False):
63
+ """Include/exclude filter over the last funding round type."""
64
+
65
+ include: list[FundingTypeValue]
66
+ exclude: list[FundingTypeValue]
67
+
68
+
60
69
  class RangeFilter(TypedDict, total=False):
61
70
  """Numeric range filter. ``0`` means unset for most fields."""
62
71
 
@@ -68,6 +77,7 @@ class CompanyHQFilter(TypedDict, total=False):
68
77
  """Headquarters-location filter for company search."""
69
78
 
70
79
  city: KeywordFilter
80
+ state: KeywordFilter
71
81
  country_code: list[str]
72
82
  continent: list[ContinentValue]
73
83
  sales_region: list[SalesRegionValue]
@@ -88,6 +98,11 @@ class CompanyFilter(TypedDict, total=False):
88
98
  sic_code: KeywordFilter
89
99
  web_traffic: RangeFilter
90
100
  ad_spend: RangeFilter
101
+ total_funding: RangeFilter
102
+ last_funding_amount: RangeFilter
103
+ last_funding_year: RangeFilter
104
+ last_funding_type: FundingTypeFilter
105
+ lead_investors: KeywordFilter
91
106
  keywords: KeywordFilter
92
107
  founded_year: RangeFilter
93
108
  hq: CompanyHQFilter
@@ -0,0 +1,18 @@
1
+ """Response models for the Utilities resource."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ._models import BlitzModel
6
+
7
+ __all__ = [
8
+ "CurrentDateResponse",
9
+ ]
10
+
11
+
12
+ class CurrentDateResponse(BlitzModel):
13
+ """Result of ``utils.current_date``."""
14
+
15
+ datetime: str | None = None
16
+ timestamp: int | None = None
17
+ timezone: str | None = None
18
+ timezone_name: str | None = None
@@ -1 +0,0 @@
1
- __version__ = "0.4.0" # x-release-please-version
@@ -1,63 +0,0 @@
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 (
9
- CompanyDepartmentDistributionResponse,
10
- CompanyEmploymentDistributionResponse,
11
- CurrentDateResponse,
12
- )
13
-
14
- if TYPE_CHECKING:
15
- from ..._client import AsyncBlitzAPI
16
-
17
- _CURRENT_DATE = "/v2/utils/current-date"
18
- _EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
19
- _DEPARTMENT_DISTRIBUTION = "/v2/utils/company-department-distribution"
20
-
21
-
22
- class AsyncUtilsResource:
23
- def __init__(self, client: AsyncBlitzAPI) -> None:
24
- self._client = client
25
-
26
- async def current_date(
27
- self, *, region: str, timeout: TimeoutParam = None
28
- ) -> CurrentDateResponse:
29
- """Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
30
- return await self._client._request(
31
- "POST",
32
- _CURRENT_DATE,
33
- body={"region": region},
34
- cast_to=CurrentDateResponse,
35
- timeout=timeout,
36
- )
37
-
38
- async def company_employment_distribution(
39
- self, *, company_linkedin_url: str, timeout: TimeoutParam = None
40
- ) -> CompanyEmploymentDistributionResponse:
41
- """Get a company's employee count broken down by country."""
42
- return await self._client._request(
43
- "POST",
44
- _EMPLOYMENT_DISTRIBUTION,
45
- body={"company_linkedin_url": company_linkedin_url},
46
- cast_to=CompanyEmploymentDistributionResponse,
47
- timeout=timeout,
48
- )
49
-
50
- async def company_department_distribution(
51
- self, *, company_linkedin_url: str, timeout: TimeoutParam = None
52
- ) -> CompanyDepartmentDistributionResponse:
53
- """Get a company's employee count broken down by department.
54
-
55
- Employees with no classified department are counted under ``"Other"``.
56
- """
57
- return await self._client._request(
58
- "POST",
59
- _DEPARTMENT_DISTRIBUTION,
60
- body={"company_linkedin_url": company_linkedin_url},
61
- cast_to=CompanyDepartmentDistributionResponse,
62
- timeout=timeout,
63
- )
@@ -1,65 +0,0 @@
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 (
11
- CompanyDepartmentDistributionResponse,
12
- CompanyEmploymentDistributionResponse,
13
- CurrentDateResponse,
14
- )
15
-
16
- if TYPE_CHECKING:
17
- from ..._client import BlitzAPI
18
-
19
- _CURRENT_DATE = "/v2/utils/current-date"
20
- _EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
21
- _DEPARTMENT_DISTRIBUTION = "/v2/utils/company-department-distribution"
22
-
23
-
24
- class UtilsResource:
25
- def __init__(self, client: BlitzAPI) -> None:
26
- self._client = client
27
-
28
- def current_date(
29
- self, *, region: str, timeout: TimeoutParam = None
30
- ) -> CurrentDateResponse:
31
- """Get the current server date/time for an IANA timezone (e.g. ``America/New_York``)."""
32
- return self._client._request(
33
- "POST",
34
- _CURRENT_DATE,
35
- body={"region": region},
36
- cast_to=CurrentDateResponse,
37
- timeout=timeout,
38
- )
39
-
40
- def company_employment_distribution(
41
- self, *, company_linkedin_url: str, timeout: TimeoutParam = None
42
- ) -> CompanyEmploymentDistributionResponse:
43
- """Get a company's employee count broken down by country."""
44
- return self._client._request(
45
- "POST",
46
- _EMPLOYMENT_DISTRIBUTION,
47
- body={"company_linkedin_url": company_linkedin_url},
48
- cast_to=CompanyEmploymentDistributionResponse,
49
- timeout=timeout,
50
- )
51
-
52
- def company_department_distribution(
53
- self, *, company_linkedin_url: str, timeout: TimeoutParam = None
54
- ) -> CompanyDepartmentDistributionResponse:
55
- """Get a company's employee count broken down by department.
56
-
57
- Employees with no classified department are counted under ``"Other"``.
58
- """
59
- return self._client._request(
60
- "POST",
61
- _DEPARTMENT_DISTRIBUTION,
62
- body={"company_linkedin_url": company_linkedin_url},
63
- cast_to=CompanyDepartmentDistributionResponse,
64
- timeout=timeout,
65
- )
@@ -1,55 +0,0 @@
1
- """Response models for the Utilities resource."""
2
-
3
- from __future__ import annotations
4
-
5
- from ._models import BlitzModel
6
-
7
- __all__ = [
8
- "CurrentDateResponse",
9
- "EmploymentDistributionItem",
10
- "CompanyEmploymentDistributionResponse",
11
- "DepartmentDistributionItem",
12
- "CompanyDepartmentDistributionResponse",
13
- ]
14
-
15
-
16
- class CurrentDateResponse(BlitzModel):
17
- """Result of ``utils.current_date``."""
18
-
19
- datetime: str | None = None
20
- timestamp: int | None = None
21
- timezone: str | None = None
22
- timezone_name: str | None = None
23
-
24
-
25
- class EmploymentDistributionItem(BlitzModel):
26
- """Employee count for a single country."""
27
-
28
- country: str | None = None
29
- count: int | None = None
30
-
31
-
32
- class CompanyEmploymentDistributionResponse(BlitzModel):
33
- """Result of ``utils.company_employment_distribution``."""
34
-
35
- company_linkedin_url: str | None = None
36
- total_employees: int | None = None
37
- distribution: list[EmploymentDistributionItem] = []
38
-
39
-
40
- class DepartmentDistributionItem(BlitzModel):
41
- """Employee count for a single department (Blitz job function).
42
-
43
- Employees with no classified department are counted under ``"Other"``.
44
- """
45
-
46
- department: str | None = None
47
- count: int | None = None
48
-
49
-
50
- class CompanyDepartmentDistributionResponse(BlitzModel):
51
- """Result of ``utils.company_department_distribution``."""
52
-
53
- company_linkedin_url: str | None = None
54
- total_employees: int | None = None
55
- distribution: list[DepartmentDistributionItem] = []
File without changes
File without changes