blitz-api-py 0.1.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 (42) hide show
  1. blitz_api_py-0.1.0/.gitignore +31 -0
  2. blitz_api_py-0.1.0/CHANGELOG.md +17 -0
  3. blitz_api_py-0.1.0/LICENSE +21 -0
  4. blitz_api_py-0.1.0/PKG-INFO +220 -0
  5. blitz_api_py-0.1.0/README.md +189 -0
  6. blitz_api_py-0.1.0/pyproject.toml +129 -0
  7. blitz_api_py-0.1.0/src/blitz_api/__init__.py +65 -0
  8. blitz_api_py-0.1.0/src/blitz_api/_base_client.py +191 -0
  9. blitz_api_py-0.1.0/src/blitz_api/_client.py +13 -0
  10. blitz_api_py-0.1.0/src/blitz_api/_client_async.py +143 -0
  11. blitz_api_py-0.1.0/src/blitz_api/_client_sync.py +145 -0
  12. blitz_api_py-0.1.0/src/blitz_api/_compat.py +26 -0
  13. blitz_api_py-0.1.0/src/blitz_api/_constants.py +36 -0
  14. blitz_api_py-0.1.0/src/blitz_api/_exceptions.py +113 -0
  15. blitz_api_py-0.1.0/src/blitz_api/_pagination_async.py +128 -0
  16. blitz_api_py-0.1.0/src/blitz_api/_pagination_base.py +52 -0
  17. blitz_api_py-0.1.0/src/blitz_api/_pagination_sync.py +130 -0
  18. blitz_api_py-0.1.0/src/blitz_api/_rate_limit.py +14 -0
  19. blitz_api_py-0.1.0/src/blitz_api/_rate_limit_async.py +67 -0
  20. blitz_api_py-0.1.0/src/blitz_api/_rate_limit_sync.py +69 -0
  21. blitz_api_py-0.1.0/src/blitz_api/_version.py +1 -0
  22. blitz_api_py-0.1.0/src/blitz_api/py.typed +0 -0
  23. blitz_api_py-0.1.0/src/blitz_api/resources/__init__.py +27 -0
  24. blitz_api_py-0.1.0/src/blitz_api/resources/_async/__init__.py +1 -0
  25. blitz_api_py-0.1.0/src/blitz_api/resources/_async/account.py +27 -0
  26. blitz_api_py-0.1.0/src/blitz_api/resources/_async/enrichment.py +116 -0
  27. blitz_api_py-0.1.0/src/blitz_api/resources/_async/search.py +153 -0
  28. blitz_api_py-0.1.0/src/blitz_api/resources/_async/utils.py +43 -0
  29. blitz_api_py-0.1.0/src/blitz_api/resources/_sync/__init__.py +3 -0
  30. blitz_api_py-0.1.0/src/blitz_api/resources/_sync/account.py +29 -0
  31. blitz_api_py-0.1.0/src/blitz_api/resources/_sync/enrichment.py +118 -0
  32. blitz_api_py-0.1.0/src/blitz_api/resources/_sync/search.py +155 -0
  33. blitz_api_py-0.1.0/src/blitz_api/resources/_sync/utils.py +45 -0
  34. blitz_api_py-0.1.0/src/blitz_api/types/__init__.py +108 -0
  35. blitz_api_py-0.1.0/src/blitz_api/types/_models.py +23 -0
  36. blitz_api_py-0.1.0/src/blitz_api/types/account.py +27 -0
  37. blitz_api_py-0.1.0/src/blitz_api/types/enrichment.py +76 -0
  38. blitz_api_py-0.1.0/src/blitz_api/types/enums.py +633 -0
  39. blitz_api_py-0.1.0/src/blitz_api/types/filters.py +130 -0
  40. blitz_api_py-0.1.0/src/blitz_api/types/search.py +36 -0
  41. blitz_api_py-0.1.0/src/blitz_api/types/shared.py +119 -0
  42. blitz_api_py-0.1.0/src/blitz_api/types/utils.py +35 -0
@@ -0,0 +1,31 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ *.egg
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+ env/
14
+
15
+ # Tooling caches
16
+ .mypy_cache/
17
+ .pyright/
18
+ .ruff_cache/
19
+ .pytest_cache/
20
+ .coverage
21
+ .coverage.*
22
+ htmlcov/
23
+ coverage.xml
24
+
25
+ # uv
26
+ # (uv.lock IS committed; only ignore caches)
27
+
28
+ # Editors / OS
29
+ .idea/
30
+ .vscode/
31
+ .DS_Store
@@ -0,0 +1,17 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0](https://github.com/api-blitz/blitz-api-py/compare/v0.1.0...v0.1.0) (2026-06-02)
4
+
5
+
6
+ ### Features
7
+
8
+ * typed Python SDK for the Blitz API with automated releases ([5641a51](https://github.com/api-blitz/blitz-api-py/commit/5641a51b405108029bc701988e08d6210a1255f6))
9
+
10
+ ## Changelog
11
+
12
+ All notable changes to this project are documented in this file.
13
+
14
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
15
+ and the changelog is maintained automatically by
16
+ [release-please](https://github.com/googleapis/release-please) from
17
+ [Conventional Commits](https://www.conventionalcommits.org/).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Blitz API
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: blitz-api-py
3
+ Version: 0.1.0
4
+ Summary: Typed Python SDK for the Blitz API — B2B data, search, and enrichment.
5
+ Project-URL: Homepage, https://blitz-api.ai
6
+ Project-URL: Documentation, https://docs.blitz-api.ai
7
+ Project-URL: Repository, https://github.com/api-blitz/blitz-api-py
8
+ Project-URL: Issues, https://github.com/api-blitz/blitz-api-py/issues
9
+ Project-URL: Changelog, https://github.com/api-blitz/blitz-api-py/blob/main/CHANGELOG.md
10
+ Author-email: Blitz API <founders@blitz-api.ai>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: b2b,blitz,blitz-api,enrichment,gtm,linkedin,sales,sdk
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: httpx<1,>=0.28
28
+ Requires-Dist: pydantic<3,>=2.13
29
+ Requires-Dist: typing-extensions>=4.10
30
+ Description-Content-Type: text/markdown
31
+
32
+ # blitz-api-py
33
+
34
+ The typed Python SDK for the [Blitz API](https://blitz-api.ai) — B2B data, search,
35
+ and enrichment.
36
+
37
+ - **Fully typed** — Pydantic v2 response models with attribute access and IDE
38
+ autocomplete, `TypedDict` request filters, and a shipped `py.typed` marker so
39
+ mypy/pyright see the types in your own code.
40
+ - **Sync & async** — `BlitzAPI` and `AsyncBlitzAPI` over `httpx`.
41
+ - **Resilient** — built-in client-side rate limiting, retries with backoff on
42
+ `429`/`5xx`, and a typed exception hierarchy.
43
+ - **Forward-compatible** — new fields the API adds never break deserialization.
44
+
45
+ > Create and manage API keys at [app.blitz-api.ai](https://app.blitz-api.ai).
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install blitz-api-py
51
+ # or: uv add blitz-api-py
52
+ ```
53
+
54
+ Requires Python 3.10+.
55
+
56
+ ## Quickstart
57
+
58
+ ```python
59
+ from blitz_api import BlitzAPI
60
+ from blitz_api.types import Industry, JobLevel
61
+
62
+ # api_key defaults to the BLITZ_API_KEY environment variable.
63
+ with BlitzAPI() as client:
64
+ # Health-check the key before a batch job.
65
+ info = client.account.key_info()
66
+ print(info.valid, info.remaining_credits, info.max_requests_per_seconds)
67
+
68
+ # LinkedIn profile URL -> verified work email.
69
+ email = client.enrichment.email(
70
+ person_linkedin_url="https://www.linkedin.com/in/example-person",
71
+ )
72
+ if email.found:
73
+ print(email.email)
74
+
75
+ # Search people with typed, autocompleted filters.
76
+ people = client.search.people(
77
+ company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
78
+ people={"job_level": [JobLevel.VP]},
79
+ max_results=10,
80
+ )
81
+ for person in people.results:
82
+ print(person.full_name, person.headline)
83
+ ```
84
+
85
+ ### Async
86
+
87
+ ```python
88
+ import asyncio
89
+ from blitz_api import AsyncBlitzAPI
90
+
91
+ async def main() -> None:
92
+ async with AsyncBlitzAPI() as client:
93
+ result = await client.enrichment.company(
94
+ company_linkedin_url="https://www.linkedin.com/company/openai",
95
+ )
96
+ print(result.company.name if result.company else None)
97
+
98
+ asyncio.run(main())
99
+ ```
100
+
101
+ ## Authentication
102
+
103
+ Pass the key explicitly or via the `BLITZ_API_KEY` environment variable:
104
+
105
+ ```python
106
+ client = BlitzAPI(api_key="sk_...") # explicit
107
+ client = BlitzAPI() # reads BLITZ_API_KEY
108
+ ```
109
+
110
+ The key is sent in the `x-api-key` header. Never expose it in client-side code —
111
+ always call the API from your backend.
112
+
113
+ ## Endpoints
114
+
115
+ All methods are grouped into four namespaces:
116
+
117
+ | Namespace | Methods |
118
+ | --- | --- |
119
+ | `client.account` | `key_info()` |
120
+ | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
121
+ | `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()` |
123
+
124
+ Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
125
+ filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
126
+ member or a raw string.
127
+
128
+ ## Pagination
129
+
130
+ The search methods return an **auto-paginating page**: iterate it and the SDK fetches
131
+ each subsequent page for you. `search.people`/`search.companies` are cursor-based;
132
+ `search.employee_finder` is page-based — both behave identically here.
133
+
134
+ ```python
135
+ # Iterate every matching person across all pages — no cursor handling needed.
136
+ for person in client.search.people(people={"job_level": ["VP"]}):
137
+ print(person.full_name)
138
+
139
+ # Async works the same way.
140
+ async for person in await async_client.search.people(people={"job_level": ["VP"]}):
141
+ ...
142
+
143
+ # Bound how much you pull.
144
+ for person in client.search.people(...).auto_paging_iter(max_items=200):
145
+ ...
146
+
147
+ # Per-page control: inspect totals / cursors as you go.
148
+ for page in client.search.companies(company={...}).iter_pages(max_pages=5):
149
+ print(page.total_results, len(page.results), page.cursor)
150
+
151
+ # Or page manually.
152
+ page = client.search.people(people={...}, max_results=50)
153
+ print(page.results, page.cursor)
154
+ nxt = page.get_next_page() # None once exhausted
155
+ ```
156
+
157
+ The page types (`CursorPage`, `PageNumberPage`, and their `Async*` variants) are
158
+ exported from `blitz_api`.
159
+
160
+ ## Configuration
161
+
162
+ ```python
163
+ client = BlitzAPI(
164
+ api_key=None, # falls back to BLITZ_API_KEY
165
+ base_url="https://api.blitz-api.ai",
166
+ timeout=30.0, # seconds, or an httpx.Timeout
167
+ max_retries=3, # retries on 429 / 5xx / network errors
168
+ rate_limit_rps=5.0, # client-side throttle; None to disable
169
+ )
170
+ ```
171
+
172
+ The client-side rate limiter is a sliding window — at most `rate_limit_rps` requests
173
+ in any rolling second — so a single client instance stays under the API's limit (5 req/s
174
+ by default; check your key's limit via
175
+ `client.account.key_info().max_requests_per_seconds`). Across multiple processes you may
176
+ still hit `429` — the retry path handles that.
177
+
178
+ Every method also accepts a per-call `timeout` (seconds or an `httpx.Timeout`) when one
179
+ endpoint needs longer than the client default:
180
+
181
+ ```python
182
+ client.search.people(people={"job_level": ["VP"]}, timeout=10.0)
183
+ ```
184
+
185
+ ## Error handling
186
+
187
+ ```python
188
+ from blitz_api import (
189
+ BlitzError, AuthenticationError, InsufficientCreditsError,
190
+ NotFoundError, RateLimitError, APIStatusError, APIConnectionError,
191
+ APITimeoutError, APIResponseValidationError,
192
+ )
193
+
194
+ try:
195
+ client.enrichment.email(person_linkedin_url="...")
196
+ except InsufficientCreditsError:
197
+ ... # 402 — out of credits
198
+ except AuthenticationError:
199
+ ... # 401 — bad key
200
+ except APIStatusError as err:
201
+ print(err.status_code, err.message, err.body)
202
+ except APIResponseValidationError:
203
+ ... # 2xx whose body wasn't valid / didn't match the model
204
+ except BlitzError:
205
+ ... # base class for everything this SDK raises
206
+ ```
207
+
208
+ `429` and `5xx` are retried automatically (with backoff) up to `max_retries`;
209
+ `401`/`402`/`404` raise immediately. Connect timeouts and connection errors are retried,
210
+ but a **read timeout is not** — the server may already have processed (and billed) the
211
+ request, so it surfaces as `APITimeoutError` rather than risking a double charge.
212
+
213
+ ## Development
214
+
215
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, the test/type/lint
216
+ commands, the enum code generator, and the automated release process.
217
+
218
+ ## License
219
+
220
+ [MIT](LICENSE)
@@ -0,0 +1,189 @@
1
+ # blitz-api-py
2
+
3
+ The typed Python SDK for the [Blitz API](https://blitz-api.ai) — B2B data, search,
4
+ and enrichment.
5
+
6
+ - **Fully typed** — Pydantic v2 response models with attribute access and IDE
7
+ autocomplete, `TypedDict` request filters, and a shipped `py.typed` marker so
8
+ mypy/pyright see the types in your own code.
9
+ - **Sync & async** — `BlitzAPI` and `AsyncBlitzAPI` over `httpx`.
10
+ - **Resilient** — built-in client-side rate limiting, retries with backoff on
11
+ `429`/`5xx`, and a typed exception hierarchy.
12
+ - **Forward-compatible** — new fields the API adds never break deserialization.
13
+
14
+ > Create and manage API keys at [app.blitz-api.ai](https://app.blitz-api.ai).
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install blitz-api-py
20
+ # or: uv add blitz-api-py
21
+ ```
22
+
23
+ Requires Python 3.10+.
24
+
25
+ ## Quickstart
26
+
27
+ ```python
28
+ from blitz_api import BlitzAPI
29
+ from blitz_api.types import Industry, JobLevel
30
+
31
+ # api_key defaults to the BLITZ_API_KEY environment variable.
32
+ with BlitzAPI() as client:
33
+ # Health-check the key before a batch job.
34
+ info = client.account.key_info()
35
+ print(info.valid, info.remaining_credits, info.max_requests_per_seconds)
36
+
37
+ # LinkedIn profile URL -> verified work email.
38
+ email = client.enrichment.email(
39
+ person_linkedin_url="https://www.linkedin.com/in/example-person",
40
+ )
41
+ if email.found:
42
+ print(email.email)
43
+
44
+ # Search people with typed, autocompleted filters.
45
+ people = client.search.people(
46
+ company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
47
+ people={"job_level": [JobLevel.VP]},
48
+ max_results=10,
49
+ )
50
+ for person in people.results:
51
+ print(person.full_name, person.headline)
52
+ ```
53
+
54
+ ### Async
55
+
56
+ ```python
57
+ import asyncio
58
+ from blitz_api import AsyncBlitzAPI
59
+
60
+ async def main() -> None:
61
+ async with AsyncBlitzAPI() as client:
62
+ result = await client.enrichment.company(
63
+ company_linkedin_url="https://www.linkedin.com/company/openai",
64
+ )
65
+ print(result.company.name if result.company else None)
66
+
67
+ asyncio.run(main())
68
+ ```
69
+
70
+ ## Authentication
71
+
72
+ Pass the key explicitly or via the `BLITZ_API_KEY` environment variable:
73
+
74
+ ```python
75
+ client = BlitzAPI(api_key="sk_...") # explicit
76
+ client = BlitzAPI() # reads BLITZ_API_KEY
77
+ ```
78
+
79
+ The key is sent in the `x-api-key` header. Never expose it in client-side code —
80
+ always call the API from your backend.
81
+
82
+ ## Endpoints
83
+
84
+ All methods are grouped into four namespaces:
85
+
86
+ | Namespace | Methods |
87
+ | --- | --- |
88
+ | `client.account` | `key_info()` |
89
+ | `client.search` | `people()`, `companies()`, `employee_finder()`, `waterfall_icp()` |
90
+ | `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()` |
92
+
93
+ Every method returns a typed Pydantic model (see `blitz_api.types`). Enum-backed
94
+ filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum
95
+ member or a raw string.
96
+
97
+ ## Pagination
98
+
99
+ The search methods return an **auto-paginating page**: iterate it and the SDK fetches
100
+ each subsequent page for you. `search.people`/`search.companies` are cursor-based;
101
+ `search.employee_finder` is page-based — both behave identically here.
102
+
103
+ ```python
104
+ # Iterate every matching person across all pages — no cursor handling needed.
105
+ for person in client.search.people(people={"job_level": ["VP"]}):
106
+ print(person.full_name)
107
+
108
+ # Async works the same way.
109
+ async for person in await async_client.search.people(people={"job_level": ["VP"]}):
110
+ ...
111
+
112
+ # Bound how much you pull.
113
+ for person in client.search.people(...).auto_paging_iter(max_items=200):
114
+ ...
115
+
116
+ # Per-page control: inspect totals / cursors as you go.
117
+ for page in client.search.companies(company={...}).iter_pages(max_pages=5):
118
+ print(page.total_results, len(page.results), page.cursor)
119
+
120
+ # Or page manually.
121
+ page = client.search.people(people={...}, max_results=50)
122
+ print(page.results, page.cursor)
123
+ nxt = page.get_next_page() # None once exhausted
124
+ ```
125
+
126
+ The page types (`CursorPage`, `PageNumberPage`, and their `Async*` variants) are
127
+ exported from `blitz_api`.
128
+
129
+ ## Configuration
130
+
131
+ ```python
132
+ client = BlitzAPI(
133
+ api_key=None, # falls back to BLITZ_API_KEY
134
+ base_url="https://api.blitz-api.ai",
135
+ timeout=30.0, # seconds, or an httpx.Timeout
136
+ max_retries=3, # retries on 429 / 5xx / network errors
137
+ rate_limit_rps=5.0, # client-side throttle; None to disable
138
+ )
139
+ ```
140
+
141
+ The client-side rate limiter is a sliding window — at most `rate_limit_rps` requests
142
+ in any rolling second — so a single client instance stays under the API's limit (5 req/s
143
+ by default; check your key's limit via
144
+ `client.account.key_info().max_requests_per_seconds`). Across multiple processes you may
145
+ still hit `429` — the retry path handles that.
146
+
147
+ Every method also accepts a per-call `timeout` (seconds or an `httpx.Timeout`) when one
148
+ endpoint needs longer than the client default:
149
+
150
+ ```python
151
+ client.search.people(people={"job_level": ["VP"]}, timeout=10.0)
152
+ ```
153
+
154
+ ## Error handling
155
+
156
+ ```python
157
+ from blitz_api import (
158
+ BlitzError, AuthenticationError, InsufficientCreditsError,
159
+ NotFoundError, RateLimitError, APIStatusError, APIConnectionError,
160
+ APITimeoutError, APIResponseValidationError,
161
+ )
162
+
163
+ try:
164
+ client.enrichment.email(person_linkedin_url="...")
165
+ except InsufficientCreditsError:
166
+ ... # 402 — out of credits
167
+ except AuthenticationError:
168
+ ... # 401 — bad key
169
+ except APIStatusError as err:
170
+ print(err.status_code, err.message, err.body)
171
+ except APIResponseValidationError:
172
+ ... # 2xx whose body wasn't valid / didn't match the model
173
+ except BlitzError:
174
+ ... # base class for everything this SDK raises
175
+ ```
176
+
177
+ `429` and `5xx` are retried automatically (with backoff) up to `max_retries`;
178
+ `401`/`402`/`404` raise immediately. Connect timeouts and connection errors are retried,
179
+ but a **read timeout is not** — the server may already have processed (and billed) the
180
+ request, so it surfaces as `APITimeoutError` rather than risking a double charge.
181
+
182
+ ## Development
183
+
184
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for local setup, the test/type/lint
185
+ commands, the enum code generator, and the automated release process.
186
+
187
+ ## License
188
+
189
+ [MIT](LICENSE)
@@ -0,0 +1,129 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "blitz-api-py"
7
+ dynamic = ["version"]
8
+ description = "Typed Python SDK for the Blitz API — B2B data, search, and enrichment."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Blitz API", email = "founders@blitz-api.ai" }]
14
+ keywords = ["blitz", "blitz-api", "b2b", "enrichment", "linkedin", "sales", "gtm", "sdk"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3 :: Only",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Typing :: Typed",
28
+ ]
29
+ dependencies = [
30
+ "httpx>=0.28,<1",
31
+ "pydantic>=2.13,<3",
32
+ "typing-extensions>=4.10",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://blitz-api.ai"
37
+ Documentation = "https://docs.blitz-api.ai"
38
+ Repository = "https://github.com/api-blitz/blitz-api-py"
39
+ Issues = "https://github.com/api-blitz/blitz-api-py/issues"
40
+ Changelog = "https://github.com/api-blitz/blitz-api-py/blob/main/CHANGELOG.md"
41
+
42
+ [dependency-groups]
43
+ dev = [
44
+ "ruff>=0.15",
45
+ "mypy>=2.1",
46
+ "pyright>=1.1.390",
47
+ "pytest>=8.3",
48
+ "pytest-asyncio>=0.24",
49
+ "pytest-httpx>=0.35",
50
+ "pytest-cov>=6.0",
51
+ "tokenize-rt>=6.2.0",
52
+ ]
53
+
54
+ [tool.hatch.version]
55
+ path = "src/blitz_api/_version.py"
56
+
57
+ [tool.hatch.build.targets.wheel]
58
+ packages = ["src/blitz_api"]
59
+
60
+ [tool.hatch.build.targets.sdist]
61
+ include = ["src/blitz_api", "README.md", "LICENSE", "CHANGELOG.md"]
62
+
63
+ [tool.ruff]
64
+ line-length = 100
65
+ src = ["src", "tests", "scripts", "examples"]
66
+ target-version = "py310"
67
+ # Machine-generated modules own their own formatting (a drift guard verifies them);
68
+ # keep ruff from reformatting them. mypy/pyright still type-check them.
69
+ # - types/enums.py <- scripts/gen_enums.py
70
+ # - *_sync.py + _sync/ <- scripts/gen_sync.py (transliterated from the async source)
71
+ extend-exclude = [
72
+ "src/blitz_api/types/enums.py",
73
+ "src/blitz_api/_client_sync.py",
74
+ "src/blitz_api/_pagination_sync.py",
75
+ "src/blitz_api/_rate_limit_sync.py",
76
+ "src/blitz_api/resources/_sync",
77
+ ]
78
+
79
+ [tool.ruff.lint]
80
+ select = ["E", "F", "I", "UP", "B", "C4", "SIM", "PIE", "RUF"]
81
+ # RUF022: __all__ is intentionally grouped by category, not alphabetized.
82
+ ignore = ["RUF022"]
83
+
84
+ [tool.ruff.lint.per-file-ignores]
85
+ # RUF012: `= []` defaults are safe on Pydantic models (deep-copied per instance)
86
+ # and keep pyright strict happy (it infers the type from the field annotation).
87
+ "src/blitz_api/types/*.py" = ["RUF012"]
88
+ "src/blitz_api/_pagination_async.py" = ["RUF012"]
89
+
90
+ [tool.ruff.lint.isort]
91
+ known-first-party = ["blitz_api"]
92
+
93
+ [tool.mypy]
94
+ python_version = "3.10"
95
+ strict = true
96
+ warn_unreachable = true
97
+ warn_redundant_casts = true
98
+ plugins = ["pydantic.mypy"]
99
+ files = ["src", "tests", "scripts", "examples"]
100
+
101
+ # tokenize-rt (used only by scripts/gen_sync.py) ships no type stubs.
102
+ [[tool.mypy.overrides]]
103
+ module = ["tokenize_rt"]
104
+ ignore_missing_imports = true
105
+
106
+ # The `# type: ignore[override]` on the page __aiter__ is unused in the async source
107
+ # (BaseModel has no __aiter__) but required in the generated sync twin's __iter__.
108
+ [[tool.mypy.overrides]]
109
+ module = ["blitz_api._pagination_async"]
110
+ warn_unused_ignores = false
111
+
112
+ [tool.pyright]
113
+ include = ["src", "tests", "examples"]
114
+ pythonVersion = "3.10"
115
+ typeCheckingMode = "strict"
116
+ reportMissingTypeStubs = false
117
+ # Resources intentionally call the client's internal `_request` across modules;
118
+ # this is internal encapsulation, not a public-API typing concern (mypy allows it).
119
+ reportPrivateUsage = false
120
+
121
+ [tool.pytest.ini_options]
122
+ asyncio_mode = "auto"
123
+ testpaths = ["tests"]
124
+ pythonpath = ["."]
125
+ addopts = "-ra"
126
+
127
+ [tool.coverage.run]
128
+ source = ["blitz_api"]
129
+ branch = true
@@ -0,0 +1,65 @@
1
+ """Typed Python SDK for the Blitz API.
2
+
3
+ Quickstart::
4
+
5
+ from blitz_api import BlitzAPI
6
+
7
+ client = BlitzAPI() # reads the BLITZ_API_KEY environment variable
8
+ result = client.enrichment.email(
9
+ person_linkedin_url="https://www.linkedin.com/in/example",
10
+ )
11
+ print(result.found, result.email)
12
+
13
+ See https://docs.blitz-api.ai for the full API reference.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from ._client import AsyncBlitzAPI, BlitzAPI
19
+ from ._exceptions import (
20
+ APIConnectionError,
21
+ APIResponseValidationError,
22
+ APIStatusError,
23
+ APITimeoutError,
24
+ AuthenticationError,
25
+ BlitzError,
26
+ InsufficientCreditsError,
27
+ NotFoundError,
28
+ RateLimitError,
29
+ ServerError,
30
+ )
31
+ from ._pagination_async import AsyncCursorPage, AsyncPageNumberPage
32
+ from ._pagination_sync import CursorPage, PageNumberPage
33
+ from ._version import __version__
34
+ from .types import (
35
+ CompanyFilter,
36
+ Industry,
37
+ PeopleFilter,
38
+ )
39
+
40
+ __all__ = [
41
+ "__version__",
42
+ # clients
43
+ "BlitzAPI",
44
+ "AsyncBlitzAPI",
45
+ # pagination (returned by the search.* methods)
46
+ "CursorPage",
47
+ "AsyncCursorPage",
48
+ "PageNumberPage",
49
+ "AsyncPageNumberPage",
50
+ # exceptions
51
+ "BlitzError",
52
+ "APIConnectionError",
53
+ "APITimeoutError",
54
+ "APIResponseValidationError",
55
+ "APIStatusError",
56
+ "AuthenticationError",
57
+ "InsufficientCreditsError",
58
+ "NotFoundError",
59
+ "RateLimitError",
60
+ "ServerError",
61
+ # commonly-used types (full set under blitz_api.types)
62
+ "Industry",
63
+ "CompanyFilter",
64
+ "PeopleFilter",
65
+ ]