blitz-api-py 0.2.0__tar.gz → 0.4.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 (43) hide show
  1. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/CHANGELOG.md +19 -0
  2. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/PKG-INFO +97 -3
  3. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/README.md +96 -2
  4. blitz_api_py-0.4.0/src/blitz_api/_version.py +1 -0
  5. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_async/utils.py +21 -1
  6. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_sync/utils.py +21 -1
  7. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/__init__.py +4 -0
  8. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/utils.py +20 -0
  9. blitz_api_py-0.2.0/src/blitz_api/_version.py +0 -1
  10. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/.gitignore +0 -0
  11. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/LICENSE +0 -0
  12. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/pyproject.toml +0 -0
  13. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/__init__.py +0 -0
  14. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_base_client.py +0 -0
  15. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_client.py +0 -0
  16. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_client_async.py +0 -0
  17. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_client_sync.py +0 -0
  18. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_compat.py +0 -0
  19. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_constants.py +0 -0
  20. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_exceptions.py +0 -0
  21. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_pagination_async.py +0 -0
  22. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_pagination_base.py +0 -0
  23. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_pagination_sync.py +0 -0
  24. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_rate_limit.py +0 -0
  25. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_rate_limit_async.py +0 -0
  26. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/_rate_limit_sync.py +0 -0
  27. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/py.typed +0 -0
  28. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/__init__.py +0 -0
  29. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_async/__init__.py +0 -0
  30. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_async/account.py +0 -0
  31. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_async/enrichment.py +0 -0
  32. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_async/search.py +0 -0
  33. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_sync/__init__.py +0 -0
  34. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_sync/account.py +0 -0
  35. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_sync/enrichment.py +0 -0
  36. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/resources/_sync/search.py +0 -0
  37. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/_models.py +0 -0
  38. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/account.py +0 -0
  39. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/enrichment.py +0 -0
  40. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/enums.py +0 -0
  41. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/filters.py +0 -0
  42. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/search.py +0 -0
  43. {blitz_api_py-0.2.0 → blitz_api_py-0.4.0}/src/blitz_api/types/shared.py +0 -0
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.0](https://github.com/api-blitz/blitz-api-py/compare/v0.3.0...v0.4.0) (2026-06-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * add company department distribution endpoint and response models ([b64a6d9](https://github.com/api-blitz/blitz-api-py/commit/b64a6d9bada069206c77ee11c9f86fae01ef6baa))
9
+
10
+
11
+ ### Documentation
12
+
13
+ * port JS SDK README upgrade (badges, billing note, TOC, example) ([#11](https://github.com/api-blitz/blitz-api-py/issues/11)) ([2276513](https://github.com/api-blitz/blitz-api-py/commit/2276513cdae4c23d4a1b50f59366e7156bf81019))
14
+
15
+ ## [0.3.0](https://github.com/api-blitz/blitz-api-py/compare/v0.2.0...v0.3.0) (2026-06-04)
16
+
17
+
18
+ ### Features
19
+
20
+ * generate enums from the live OpenAPI spec with offline drift guard ([#9](https://github.com/api-blitz/blitz-api-py/issues/9)) ([fee865c](https://github.com/api-blitz/blitz-api-py/commit/fee865c4d8f7c685330794fa79921dccd7556e37))
21
+
3
22
  ## [0.2.0](https://github.com/api-blitz/blitz-api-py/compare/v0.1.0...v0.2.0) (2026-06-02)
4
23
 
5
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blitz-api-py
3
- Version: 0.2.0
3
+ Version: 0.4.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
@@ -31,6 +31,11 @@ Description-Content-Type: text/markdown
31
31
 
32
32
  # blitz-api-py
33
33
 
34
+ [![PyPI version](https://img.shields.io/pypi/v/blitz-api-py.svg)](https://pypi.org/project/blitz-api-py/)
35
+ [![types: py.typed](https://img.shields.io/badge/types-py.typed-blue.svg)](https://pypi.org/project/blitz-api-py/)
36
+ [![CI](https://github.com/api-blitz/blitz-api-py/actions/workflows/ci.yml/badge.svg)](https://github.com/api-blitz/blitz-api-py/actions/workflows/ci.yml)
37
+ [![license: MIT](https://img.shields.io/pypi/l/blitz-api-py.svg)](./LICENSE)
38
+
34
39
  The typed Python SDK for the [Blitz API](https://blitz-api.ai) — B2B data, search,
35
40
  and enrichment.
36
41
 
@@ -41,14 +46,35 @@ and enrichment.
41
46
  - **Resilient** — built-in client-side rate limiting, retries with backoff on
42
47
  `429`/`5xx`, and a typed exception hierarchy.
43
48
  - **Forward-compatible** — new fields the API adds never break deserialization.
49
+ - **1:1 with the API** — request filters and response fields are snake_case,
50
+ matching [docs.blitz-api.ai](https://docs.blitz-api.ai).
44
51
 
45
52
  > Create and manage API keys at [app.blitz-api.ai](https://app.blitz-api.ai).
46
53
 
54
+ > **Billing.** Blitz bills **per result**. A bare `for person in client.search.people(...)`
55
+ > loop streams every match up to the server-side limit (people: 50k results), which can be
56
+ > a lot of credits. Bound spend with **`max_items`** (a client-side total cap on
57
+ > `.collect()` / `.auto_paging_iter()`, never sent on the wire) — details in
58
+ > [Pagination](#pagination).
59
+
60
+ ## Contents
61
+
62
+ - [Installation](#installation)
63
+ - [Quickstart](#quickstart)
64
+ - [Example: find, enrich, collect](#example-find-enrich-collect)
65
+ - [Authentication](#authentication)
66
+ - [Endpoints](#endpoints)
67
+ - [Pagination](#pagination)
68
+ - [Configuration](#configuration)
69
+ - [Error handling](#error-handling)
70
+ - [Forward compatibility](#forward-compatibility)
71
+ - [Development](#development)
72
+
47
73
  ## Installation
48
74
 
49
75
  ```bash
50
76
  pip install blitz-api-py
51
- # or: uv add blitz-api-py
77
+ # or: poetry add blitz-api-py / uv add blitz-api-py
52
78
  ```
53
79
 
54
80
  Requires Python 3.10+.
@@ -98,6 +124,61 @@ async def main() -> None:
98
124
  asyncio.run(main())
99
125
  ```
100
126
 
127
+ ## Example: find, enrich, collect
128
+
129
+ A complete flow — find people, enrich each one's verified work email, collect the
130
+ contacts. `max_items` caps the total fetched so the run can't surprise you with credits.
131
+
132
+ ```python
133
+ from blitz_api import BlitzAPI
134
+ from blitz_api.types import Industry, JobLevel
135
+
136
+ client = BlitzAPI() # reads BLITZ_API_KEY
137
+
138
+ # 1. Find up to 25 VPs at software companies (typed filters, 1:1 with the API).
139
+ leads = client.search.people(
140
+ company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
141
+ people={"job_level": [JobLevel.VP]},
142
+ max_results=25,
143
+ ).collect(max_items=25) # client-side total cap — bounds credit spend
144
+
145
+ # 2. Enrich each lead's verified work email from their LinkedIn profile URL.
146
+ contacts: list[dict[str, str | None]] = []
147
+ for person in leads:
148
+ if not person.linkedin_url:
149
+ continue
150
+ result = client.enrichment.email(person_linkedin_url=person.linkedin_url)
151
+ if result.found:
152
+ contacts.append({"name": person.full_name, "email": result.email})
153
+
154
+ print(f"Collected {len(contacts)} contacts")
155
+ ```
156
+
157
+ What comes back is typed and snake_case. A `Person` from the search above (fields are a
158
+ **superset** — only what the profile has is populated, and unknown fields the API adds
159
+ later are preserved):
160
+
161
+ ```python
162
+ Person(
163
+ full_name="Jordan Lee",
164
+ headline="VP of Engineering at Acme",
165
+ linkedin_url="https://www.linkedin.com/in/example-person",
166
+ location=Location(city="San Francisco", state_code="CA", country_code="US", continent="North America"),
167
+ experiences=[Experience(job_title="VP of Engineering", company_name="Acme", job_is_current=True)],
168
+ # first_name, last_name, skills, education, certifications, … also present
169
+ )
170
+ ```
171
+
172
+ And `enrichment.email(...)` returns:
173
+
174
+ ```python
175
+ EmailEnrichmentResponse(
176
+ found=True,
177
+ email="jordan@acme.com",
178
+ all_emails=[EmailMatch(email="jordan@acme.com", email_domain="acme.com")],
179
+ )
180
+ ```
181
+
101
182
  ## Authentication
102
183
 
103
184
  Pass the key explicitly or via the `BLITZ_API_KEY` environment variable:
@@ -119,7 +200,7 @@ All methods are grouped into four namespaces:
119
200
  | `client.account` | `key_info()` |
120
201
  | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
121
202
  | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()` |
122
- | `client.utils` | `current_date()`, `company_employment_distribution()` |
203
+ | `client.utils` | `current_date()`, `company_employment_distribution()`, `company_department_distribution()` |
123
204
 
124
205
  Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
125
206
  filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
@@ -131,6 +212,13 @@ The search methods return an **auto-paginating page**: iterate it and the SDK fe
131
212
  each subsequent page for you. `search.people`/`search.companies` are cursor-based;
132
213
  `search.employee_finder` is page-based — both behave identically here.
133
214
 
215
+ > **`max_results` is the page size, not a total.** It's results per page, and the API
216
+ > **bills 1 credit per result returned**. A bare `for person in client.search.people(...)`
217
+ > loop streams *every* match up to the server-side limit (people: 50k results / 1k pages;
218
+ > employee finder: 10k), which can be a lot of credits. Bound it with **`max_items`** on
219
+ > `.collect()` / `.auto_paging_iter()` (a client-side total cap — never sent on the wire),
220
+ > `break` out of the loop, or drive pages manually.
221
+
134
222
  ```python
135
223
  # Iterate every matching person across all pages — no cursor handling needed.
136
224
  for person in client.search.people(people={"job_level": ["VP"]}):
@@ -210,6 +298,12 @@ except BlitzError:
210
298
  but a **read timeout is not** — the server may already have processed (and billed) the
211
299
  request, so it surfaces as `APITimeoutError` rather than risking a double charge.
212
300
 
301
+ ## Forward compatibility
302
+
303
+ Response models subclass a base configured with `extra="allow"`, so a field the API adds
304
+ before this SDK models it is still present on the parsed object (via attribute access or
305
+ `.model_extra`). Known fields stay precisely typed.
306
+
213
307
  ## Development
214
308
 
215
309
  See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, the test/type/lint
@@ -1,5 +1,10 @@
1
1
  # blitz-api-py
2
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/blitz-api-py.svg)](https://pypi.org/project/blitz-api-py/)
4
+ [![types: py.typed](https://img.shields.io/badge/types-py.typed-blue.svg)](https://pypi.org/project/blitz-api-py/)
5
+ [![CI](https://github.com/api-blitz/blitz-api-py/actions/workflows/ci.yml/badge.svg)](https://github.com/api-blitz/blitz-api-py/actions/workflows/ci.yml)
6
+ [![license: MIT](https://img.shields.io/pypi/l/blitz-api-py.svg)](./LICENSE)
7
+
3
8
  The typed Python SDK for the [Blitz API](https://blitz-api.ai) — B2B data, search,
4
9
  and enrichment.
5
10
 
@@ -10,14 +15,35 @@ and enrichment.
10
15
  - **Resilient** — built-in client-side rate limiting, retries with backoff on
11
16
  `429`/`5xx`, and a typed exception hierarchy.
12
17
  - **Forward-compatible** — new fields the API adds never break deserialization.
18
+ - **1:1 with the API** — request filters and response fields are snake_case,
19
+ matching [docs.blitz-api.ai](https://docs.blitz-api.ai).
13
20
 
14
21
  > Create and manage API keys at [app.blitz-api.ai](https://app.blitz-api.ai).
15
22
 
23
+ > **Billing.** Blitz bills **per result**. A bare `for person in client.search.people(...)`
24
+ > loop streams every match up to the server-side limit (people: 50k results), which can be
25
+ > a lot of credits. Bound spend with **`max_items`** (a client-side total cap on
26
+ > `.collect()` / `.auto_paging_iter()`, never sent on the wire) — details in
27
+ > [Pagination](#pagination).
28
+
29
+ ## Contents
30
+
31
+ - [Installation](#installation)
32
+ - [Quickstart](#quickstart)
33
+ - [Example: find, enrich, collect](#example-find-enrich-collect)
34
+ - [Authentication](#authentication)
35
+ - [Endpoints](#endpoints)
36
+ - [Pagination](#pagination)
37
+ - [Configuration](#configuration)
38
+ - [Error handling](#error-handling)
39
+ - [Forward compatibility](#forward-compatibility)
40
+ - [Development](#development)
41
+
16
42
  ## Installation
17
43
 
18
44
  ```bash
19
45
  pip install blitz-api-py
20
- # or: uv add blitz-api-py
46
+ # or: poetry add blitz-api-py / uv add blitz-api-py
21
47
  ```
22
48
 
23
49
  Requires Python 3.10+.
@@ -67,6 +93,61 @@ async def main() -> None:
67
93
  asyncio.run(main())
68
94
  ```
69
95
 
96
+ ## Example: find, enrich, collect
97
+
98
+ A complete flow — find people, enrich each one's verified work email, collect the
99
+ contacts. `max_items` caps the total fetched so the run can't surprise you with credits.
100
+
101
+ ```python
102
+ from blitz_api import BlitzAPI
103
+ from blitz_api.types import Industry, JobLevel
104
+
105
+ client = BlitzAPI() # reads BLITZ_API_KEY
106
+
107
+ # 1. Find up to 25 VPs at software companies (typed filters, 1:1 with the API).
108
+ leads = client.search.people(
109
+ company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
110
+ people={"job_level": [JobLevel.VP]},
111
+ max_results=25,
112
+ ).collect(max_items=25) # client-side total cap — bounds credit spend
113
+
114
+ # 2. Enrich each lead's verified work email from their LinkedIn profile URL.
115
+ contacts: list[dict[str, str | None]] = []
116
+ for person in leads:
117
+ if not person.linkedin_url:
118
+ continue
119
+ result = client.enrichment.email(person_linkedin_url=person.linkedin_url)
120
+ if result.found:
121
+ contacts.append({"name": person.full_name, "email": result.email})
122
+
123
+ print(f"Collected {len(contacts)} contacts")
124
+ ```
125
+
126
+ What comes back is typed and snake_case. A `Person` from the search above (fields are a
127
+ **superset** — only what the profile has is populated, and unknown fields the API adds
128
+ later are preserved):
129
+
130
+ ```python
131
+ Person(
132
+ full_name="Jordan Lee",
133
+ headline="VP of Engineering at Acme",
134
+ linkedin_url="https://www.linkedin.com/in/example-person",
135
+ location=Location(city="San Francisco", state_code="CA", country_code="US", continent="North America"),
136
+ experiences=[Experience(job_title="VP of Engineering", company_name="Acme", job_is_current=True)],
137
+ # first_name, last_name, skills, education, certifications, … also present
138
+ )
139
+ ```
140
+
141
+ And `enrichment.email(...)` returns:
142
+
143
+ ```python
144
+ EmailEnrichmentResponse(
145
+ found=True,
146
+ email="jordan@acme.com",
147
+ all_emails=[EmailMatch(email="jordan@acme.com", email_domain="acme.com")],
148
+ )
149
+ ```
150
+
70
151
  ## Authentication
71
152
 
72
153
  Pass the key explicitly or via the `BLITZ_API_KEY` environment variable:
@@ -88,7 +169,7 @@ All methods are grouped into four namespaces:
88
169
  | `client.account` | `key_info()` |
89
170
  | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
90
171
  | `client.enrichment` | `email()`, `phone()`, `email_to_person()`, `phone_to_person()`, `company()`, `domain_to_linkedin()`, `linkedin_to_domain()` |
91
- | `client.utils` | `current_date()`, `company_employment_distribution()` |
172
+ | `client.utils` | `current_date()`, `company_employment_distribution()`, `company_department_distribution()` |
92
173
 
93
174
  Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
94
175
  filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
@@ -100,6 +181,13 @@ The search methods return an **auto-paginating page**: iterate it and the SDK fe
100
181
  each subsequent page for you. `search.people`/`search.companies` are cursor-based;
101
182
  `search.employee_finder` is page-based — both behave identically here.
102
183
 
184
+ > **`max_results` is the page size, not a total.** It's results per page, and the API
185
+ > **bills 1 credit per result returned**. A bare `for person in client.search.people(...)`
186
+ > loop streams *every* match up to the server-side limit (people: 50k results / 1k pages;
187
+ > employee finder: 10k), which can be a lot of credits. Bound it with **`max_items`** on
188
+ > `.collect()` / `.auto_paging_iter()` (a client-side total cap — never sent on the wire),
189
+ > `break` out of the loop, or drive pages manually.
190
+
103
191
  ```python
104
192
  # Iterate every matching person across all pages — no cursor handling needed.
105
193
  for person in client.search.people(people={"job_level": ["VP"]}):
@@ -179,6 +267,12 @@ except BlitzError:
179
267
  but a **read timeout is not** — the server may already have processed (and billed) the
180
268
  request, so it surfaces as `APITimeoutError` rather than risking a double charge.
181
269
 
270
+ ## Forward compatibility
271
+
272
+ Response models subclass a base configured with `extra="allow"`, so a field the API adds
273
+ before this SDK models it is still present on the parsed object (via attribute access or
274
+ `.model_extra`). Known fields stay precisely typed.
275
+
182
276
  ## Development
183
277
 
184
278
  See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, the test/type/lint
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0" # x-release-please-version
@@ -5,13 +5,18 @@ from __future__ import annotations
5
5
  from typing import TYPE_CHECKING
6
6
 
7
7
  from ..._compat import TimeoutParam
8
- from ...types.utils import CompanyEmploymentDistributionResponse, CurrentDateResponse
8
+ from ...types.utils import (
9
+ CompanyDepartmentDistributionResponse,
10
+ CompanyEmploymentDistributionResponse,
11
+ CurrentDateResponse,
12
+ )
9
13
 
10
14
  if TYPE_CHECKING:
11
15
  from ..._client import AsyncBlitzAPI
12
16
 
13
17
  _CURRENT_DATE = "/v2/utils/current-date"
14
18
  _EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
19
+ _DEPARTMENT_DISTRIBUTION = "/v2/utils/company-department-distribution"
15
20
 
16
21
 
17
22
  class AsyncUtilsResource:
@@ -41,3 +46,18 @@ class AsyncUtilsResource:
41
46
  cast_to=CompanyEmploymentDistributionResponse,
42
47
  timeout=timeout,
43
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
+ )
@@ -7,13 +7,18 @@ from __future__ import annotations
7
7
  from typing import TYPE_CHECKING
8
8
 
9
9
  from ..._compat import TimeoutParam
10
- from ...types.utils import CompanyEmploymentDistributionResponse, CurrentDateResponse
10
+ from ...types.utils import (
11
+ CompanyDepartmentDistributionResponse,
12
+ CompanyEmploymentDistributionResponse,
13
+ CurrentDateResponse,
14
+ )
11
15
 
12
16
  if TYPE_CHECKING:
13
17
  from ..._client import BlitzAPI
14
18
 
15
19
  _CURRENT_DATE = "/v2/utils/current-date"
16
20
  _EMPLOYMENT_DISTRIBUTION = "/v2/utils/company-employment-distribution"
21
+ _DEPARTMENT_DISTRIBUTION = "/v2/utils/company-department-distribution"
17
22
 
18
23
 
19
24
  class UtilsResource:
@@ -43,3 +48,18 @@ class UtilsResource:
43
48
  cast_to=CompanyEmploymentDistributionResponse,
44
49
  timeout=timeout,
45
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
+ )
@@ -53,8 +53,10 @@ from .shared import (
53
53
  Person,
54
54
  )
55
55
  from .utils import (
56
+ CompanyDepartmentDistributionResponse,
56
57
  CompanyEmploymentDistributionResponse,
57
58
  CurrentDateResponse,
59
+ DepartmentDistributionItem,
58
60
  EmploymentDistributionItem,
59
61
  )
60
62
 
@@ -105,4 +107,6 @@ __all__ = [
105
107
  "CurrentDateResponse",
106
108
  "EmploymentDistributionItem",
107
109
  "CompanyEmploymentDistributionResponse",
110
+ "DepartmentDistributionItem",
111
+ "CompanyDepartmentDistributionResponse",
108
112
  ]
@@ -8,6 +8,8 @@ __all__ = [
8
8
  "CurrentDateResponse",
9
9
  "EmploymentDistributionItem",
10
10
  "CompanyEmploymentDistributionResponse",
11
+ "DepartmentDistributionItem",
12
+ "CompanyDepartmentDistributionResponse",
11
13
  ]
12
14
 
13
15
 
@@ -33,3 +35,21 @@ class CompanyEmploymentDistributionResponse(BlitzModel):
33
35
  company_linkedin_url: str | None = None
34
36
  total_employees: int | None = None
35
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] = []
@@ -1 +0,0 @@
1
- __version__ = "0.2.0" # x-release-please-version
File without changes
File without changes