`. It is **not** the LinkedIn headline that `include_headline_search` matches, so don't look for your matched words here. |
| `about_me` | `string \| null` | LinkedIn "About" section. |
| `location` | `object` | Location with `city`, `state_code`, `country_code`, `continent`, `postal_code`, `street_address`. |
| `linkedin_url` | `string` | Person LinkedIn URL — **use this** as input for `/v2/enrichment/email` and `/v2/enrichment/phone`. |
| `connections_count` | `number \| null` | LinkedIn connections count. |
| `profile_picture_url` | `string \| null` | Always `null`. Kept in the response so existing clients do not break. |
| `experiences` | `array` | Work history. Each entry: `job_title`, `company_linkedin_url`, `job_start_date`, `job_end_date`, `job_is_current`, `job_contract_type`, `job_work_arrangement`, `job_location`. |
| `education` | `array` | Education history. Each entry: `school_name`, `degree`, `start_date`, `end_date`. |
| `skills` | `array` | List of skills (strings). |
| `certifications` | `array` | List of certifications. Each entry: `name`, `authority`, `url`. |
**`icp` vs `ranking` — how to use both:**
* `icp` tells you *which tier* matched: route ICP 1–2 to your AE team, ICP 3–5 to SDR.
* `ranking` tells you *position within the company*: apply multichannel (email+LinkedIn+call) to ranking 1–3, calling-only to 4–10, and nurturing sequences to 11+.
***
## Waterfall vs. the Rest of the People Search Family
Waterfall ICP is account-scoped and returns **up to `max_results` people** (default 10, max 100), best tier first. If your need is different, pick the right tool:
| Use Case | Best Endpoint |
| :- | :- |
| Best-fit decision-makers at a **known** company, in your priority order | **Waterfall ICP** (this page) |
| Map *all* employees at one specific company | [Employee Finder](/guide/concepts/employee-finder) |
| Search decision-makers across **many companies** in one call | [Find People](/guide/concepts/find-people) |
| Just the company list (no people) | [Company Search](/guide/concepts/company-search) |
Combine company filters and person filters in a single multi-account search.
Browse every employee at a single company with paginated results.
# Authentication
Source: https://docs.blitz-api.ai/guide/getting-started/authentication
# Authentication
> How to securely authenticate your requests with BlitzAPI.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
BlitzAPI uses API Keys to authenticate requests. You can view and manage your API keys in the [BlitzAPI Dashboard](https://app.blitz-api.ai).
## The `x-api-key` Header
Authentication to the API is handled via an HTTP header. Include your API key in every request using the `x-api-key` header.
**Security Warning**: Your API keys carry many privileges. **Do not** use your API keys in client-side code (browsers, mobile apps).
Always route requests through your own backend server to keep your keys secret.
### Example Request
Here is how to set the header in various environments:
```bash cURL theme={null} theme={null}
curl "https://api.blitz-api.ai/v2/account/key-info" \
-H "x-api-key: YOUR_API_KEY"
```
```python Python theme={null} theme={null}
from blitz_api import BlitzAPI
# Pass the key explicitly, or set BLITZ_API_KEY and call BlitzAPI().
# The SDK sends it in the x-api-key header on every request.
client = BlitzAPI(api_key="YOUR_API_KEY")
```
```ts TypeScript theme={null} theme={null}
import { BlitzAPI } from "blitz-api-js";
// Pass the key explicitly, or set BLITZ_API_KEY and call new BlitzAPI().
// The SDK sends it in the x-api-key header on every request.
const client = new BlitzAPI({ api_key: "YOUR_API_KEY" });
```
**Using an AI tool?** The [MCP Server](/guide/integrations/MCP) can sign you in with your Blitz account via OAuth, so there's no key to copy. It also accepts your API key in the same `x-api-key` header.
## Verifying your Key
To check if your key is active, use the `GET /v2/account/key-info` endpoint. This is a great way to "health check" your integration before running batch jobs.
```python Python theme={null} theme={null}
info = client.account.key_info()
print(info.valid, info.records_remaining, info.max_requests_per_seconds)
```
```ts TypeScript theme={null} theme={null}
const info = await client.account.key_info();
console.log(info.valid, info.records_remaining, info.max_requests_per_seconds);
```
**Response:**
```json theme={null} theme={null}
{
"valid": true,
"id": "key_abc123",
"records_remaining": 950,
"next_reset_at": "2026-02-12T17:48:25.199Z",
"max_requests_per_seconds": 10,
"allowed_apis": [
"/search/waterfall-icp-keyword",
"/enrichment/email",
"/enrichment/phone"
],
"active_plans": [
{
"name": "Unlimited Leads",
"status": "active",
"started_at": "2026-01-12T17:48:25.200Z"
}
]
}
```
**Response Fields:**
| Field | Type | Description |
| :- | :- | :- |
| `valid` | `boolean` | `true` if the key is active and can make requests. |
| `id` | `string` | Internal identifier for your API key. |
| `records_remaining` | `number` or `"unlimited"` | Records left on your plan. Returns the string `"unlimited"` on unlimited plans. |
| `next_reset_at` | `string` | ISO 8601 timestamp of when your allowance resets. |
| `max_requests_per_seconds` | `integer` | Your plan's rate limit, applied independently per endpoint. Use this value to configure your rate limiter client-side. |
| `allowed_apis` | `array` | List of endpoint paths your key is authorized to call. |
| `active_plans` | `array` | Your active subscription(s) with name, status, and start date. |
## Errors
If authentication fails, the API will return a `401 Unauthorized` error.
| **Code** | **Meaning** | **Solution** |
| - | - | - |
| `401` | **Unauthorized** | Missing or invalid API key. Check that the `x-api-key` header is present and correct. |
| `402` | **Payment Required** | Your key is valid, but your account has reached its limit. Upgrade your plan. |
| `404` | **Not Found** | The API Key provided does not exist in our system. |
For every other status code, including `422` validation errors, see [Errors](/guide/reference/errors).
# Quickstart
Source: https://docs.blitz-api.ai/guide/getting-started/quickstart
# Quickstart
> Make your first API request in less than 2 minutes.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Welcome to BlitzAPI! In this guide, we will perform a simple but powerful task: **finding a verified professional email** from a LinkedIn profile URL.
**Prerequisites**: You need an API Key. You can grab one from your [BlitzAPI Dashboard](https://app.blitz-api.ai).
BlitzAPI is a standard REST API, so you can use it with any language.
For Python or JavaScript/TypeScript, the fastest path is the **official SDK** — it handles auth, retries, rate limiting, and pagination for you. Prefer **cURL** for a quick terminal test, or call the REST API directly from any other language.
Skip this step if you're using cURL.
```bash Python theme={null} theme={null}
pip install blitz-api-py
```
```bash Node.js theme={null} theme={null}
npm install blitz-api-js
```
See the [SDK guides](/sdks/overview) for the full API surface.
We will use the `POST /v2/enrichment/email` endpoint. Replace `YOUR_API_KEY` with your actual key, or set it as the `BLITZ_API_KEY` environment variable (the SDKs read it automatically).
```bash cURL theme={null} theme={null}
curl --request POST \
--url https://api.blitz-api.ai/v2/enrichment/email \
--header 'Content-Type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '{
"person_linkedin_url": "https://www.linkedin.com/in/example-person"
}'
```
```python Python theme={null} theme={null}
from blitz_api import BlitzAPI
client = BlitzAPI(api_key="YOUR_API_KEY") # or set BLITZ_API_KEY
result = client.enrichment.email(
person_linkedin_url="https://www.linkedin.com/in/example-person",
)
print(result.found, result.email)
```
```ts Node.js theme={null} theme={null}
import { BlitzAPI } from "blitz-api-js";
const client = new BlitzAPI({ api_key: "YOUR_API_KEY" }); // or set BLITZ_API_KEY
const result = await client.enrichment.email({
person_linkedin_url: "https://www.linkedin.com/in/example-person",
});
console.log(result.found, result.email);
```
You should receive a JSON object containing the verified email and its status.
```json theme={null} theme={null}
{
"found": true,
"email": "jane.doe@acme.com",
"all_emails": [
{
"email": "jane.doe@acme.com",
"job_order_in_profile": 1,
"company_linkedin_url": "https://www.linkedin.com/company/acme",
"email_domain": "acme.com"
}
]
}
```
**Response Fields:**
| Field | Type | Description |
| :- | :- | :- |
| `found` | `boolean` | `true` if a verified email was found. `false` if no email exists in the database. |
| `email` | `string` | The primary verified work email address. `null` if `found: false`. |
| `all_emails` | `array` | All verified email addresses found for this profile (usually 1). |
| `all_emails[].email` | `string` | The verified email address. |
| `all_emails[].job_order_in_profile` | `integer` | Position of the associated job in the person's LinkedIn profile (1 = current job). |
| `all_emails[].company_linkedin_url` | `string` | LinkedIn URL of the company associated with this email. |
| `all_emails[].email_domain` | `string` | Domain of the email address. |
All paid plans include **unlimited** requests — included in your flat monthly subscription.
## What just happened?
1. **Authentication**: You passed your key via the `x-api-key` header.
2. **Identity Matching**: BlitzAPI matched the LinkedIn profile URL against our verified B2B dataset.
3. **Verification**: We validated email deliverability (SMTP handshake) before returning it.
## Next Steps
Now that you have the basics down, explore our more advanced features.
Typed Python and TypeScript/JavaScript SDKs with built-in retries, rate limiting, and pagination.
Let Claude, Cursor, or any MCP client call Blitz endpoints for you — one-click setup.
Source decision-makers across an entire ICP in one call — combine company and person filters.
Don't have a profile URL? Find the best contact at a known company by cascade.
End-to-end recipe: Find People → enrich → CRM-ready output.
Learn how to process thousands of leads efficiently.
# MCP Server
Source: https://docs.blitz-api.ai/guide/integrations/MCP
# MCP Server
> Connect your AI tool to Blitz API — it can call every endpoint, read the docs, and use built-in skills, all from one server.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## What is the Blitz API MCP Server?
The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) is an open standard that lets AI assistants connect directly to external tools and data instead of relying on their training data.
The **Blitz API MCP Server** lets your AI assistant work with Blitz data directly. It can find and enrich people and companies, search jobs, look up the documentation when it needs to, and follow built-in skills for common workflows.
Setup takes one click: add the server URL to your AI tool, sign in with your Blitz account, and you're connected. No API key to copy and paste.
**MCP Server URL**
```text theme={null} theme={null}
https://api.blitz-api.ai/mcp
```
***
## What can it do?
The server exposes three things to your AI tool.
| Capability | What it gives your AI |
| :- | :- |
| **API tools** | One tool for every Blitz API endpoint — your AI can search, enrich, and fetch data itself instead of just writing code. |
| **Docs access** | Search and read the full Blitz documentation — endpoints, parameters, response schemas, and guides. |
| **Built-in skills** | Blitz's own playbooks, served as MCP resources, that teach your AI how to use the server and build GTM workflows. |
Tools are named after what they return, so your AI can find the right one quickly:
| Tool prefix | What it does |
| :- | :- |
| `people_*` | Find and enrich people — including `people_employee_finder` and `people_waterfall_icp` |
| `company_*` | Find and enrich companies, including TAM and headcount distribution |
| `job_*` | Search job postings |
| `docs_*` | Search and read the Blitz documentation (start with `docs_search`) |
| Account, util & changelog tools | Check your key, use utilities, and read the changelog |
| `send_feedback` | Report a bug, request a feature, or send feedback to the Blitz team |
Each API tool maps to exactly one [API endpoint](/api-reference), so everything you know about a request's parameters and response applies unchanged.
The server is built to keep token usage low. Docs and skills are read on demand rather than loaded up front, and its built-in guidance steers your AI to hand large jobs off to a script instead of pulling big payloads into the conversation. See [Tips for large jobs](#tips-for-large-jobs).
***
## Setup
1. Open [Claude.ai](https://claude.ai) and start a new conversation.
2. Click the **"+"** or attachments button.
3. Select **"Manage Connectors"** and click on **"Add custom Connector"**.
4. Copy / Paste this URL into "Remote MCP server URL": [https://api.blitz-api.ai/mcp](https://api.blitz-api.ai/mcp).
5. Click **Connect** and sign in with your Blitz account.
You may need to explicitly enable the connector for each new conversation using the attachments button.
Add the server from your terminal:
```bash theme={null} theme={null}
claude mcp add --transport http blitz-api https://api.blitz-api.ai/mcp
```
Then run `/mcp` inside Claude Code, select **blitz-api**, and sign in with your Blitz account.
Prefer an API key? Pass it as a header instead:
```bash theme={null} theme={null}
claude mcp add --transport http blitz-api https://api.blitz-api.ai/mcp \
--header "x-api-key: YOUR_API_KEY"
```
Press `Cmd + Shift + P` (macOS) or `Ctrl + Shift + P` (Windows/Linux) to open the command palette, then search for **"Open MCP Settings"**.
In your `mcp.json` file, add:
```json theme={null} theme={null}
{
"mcpServers": {
"blitz-api": {
"url": "https://api.blitz-api.ai/mcp"
}
}
}
```
Cursor will prompt you to sign in with your Blitz account. To use an API key instead, add a `headers` block:
```json theme={null} theme={null}
{
"mcpServers": {
"blitz-api": {
"url": "https://api.blitz-api.ai/mcp",
"headers": {
"x-api-key": "YOUR_API_KEY"
}
}
}
}
```
In Cursor's Agent chat, ask: `"What tools do you have available?"` — you should see the Blitz `people_*`, `company_*`, `job_*`, and `docs_*` tools listed.
Make sure the MCP server shows a **green status indicator** in your MCP settings after adding it.
In your project root, create a `.vscode/mcp.json` file (or open it if it already exists):
```json theme={null} theme={null}
{
"servers": {
"blitz-api": {
"type": "http",
"url": "https://api.blitz-api.ai/mcp"
}
}
}
```
VS Code will prompt you to sign in with your Blitz account. To use an API key, add a `headers` entry with `x-api-key`, and keep the key out of version control.
Older versions of Claude Desktop don't support remote MCP servers natively. Use the `mcp-remote` wrapper:
```json theme={null} theme={null}
{
"mcpServers": {
"blitz-api": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://api.blitz-api.ai/mcp"]
}
}
}
```
Save this in your Claude Desktop config file and restart the application. A browser window opens for you to sign in with your Blitz account.
If you use an API key in a config file, treat it like a password. Never commit it to a repository or share it in screenshots. See [Authentication](/guide/getting-started/authentication).
***
## Example Prompts
Once connected, try these prompts with your AI tool:
```text theme={null} theme={null}
Using Blitz, find the Head of Sales at stripe.com and get their work email.
```
```text theme={null} theme={null}
Find 25 VPs of Marketing at B2B SaaS companies in the US with 50-200 employees. Show name, title, company, and LinkedIn URL in a table.
```
```text theme={null} theme={null}
How many records do I have left on my Blitz plan, and what's my rate limit?
```
```text theme={null} theme={null}
What parameters does the waterfall ICP keyword search accept? Show me a complete example JSON body.
```
```text theme={null} theme={null}
Write a Python script that takes a list of company domains, converts each to a LinkedIn URL, then finds the VP of Sales using Blitz waterfall search. Save the results to a CSV and include retry logic.
```
***
## Tips for large jobs
Tool results come back into your AI's context, so big pulls get expensive quickly. For anything beyond a small lookup:
* **Ask for a script, not a giant tool call.** Have your AI use the docs tools to write a Python or JavaScript script that fetches and enriches the data and saves it locally. This keeps large payloads out of the conversation.
* **Request only what you need.** Ask for the specific fields and the small page size you actually want.
* **Know how pagination works.** Most search tools take `max_results` and a `cursor` that you send back until it is `null`. `people_employee_finder` takes a `page` number instead, and `people_waterfall_icp` returns in one shot.
* **Stay under the depth ceiling.** Each search stops at a maximum number of records: 50,000 for people, company, and TAM searches, 10,000 for `people_employee_finder`, and 5,000 for jobs. The last page can look like a clean end, so slice a bigger pull into filters that each stay under the limit.
For production pipelines, the Python and TypeScript SDKs handle retries, rate limiting, and auto-pagination for you.
***
## Docs-only server
If you only need your AI to read the documentation — no account, no API calls — you can connect to the docs server instead. It needs no sign-in and uses no records.
```text theme={null} theme={null}
https://docs.blitz-api.ai/mcp
```
Setup is the same as above with this URL. The main server at `https://api.blitz-api.ai/mcp` already includes docs access through its `docs_*` tools, so you don't need both.
***
## Troubleshooting
Some AI tools require you to explicitly enable the connector for each conversation. In Claude, use the attachments button to select the Blitz API connector. In Cursor, make sure the MCP server shows a green status indicator in your MCP settings.
Restart your AI tool after adding the MCP configuration. Most clients need a full restart to detect new MCP servers. Verify the URL is exactly `https://api.blitz-api.ai/mcp`.
The server didn't receive valid credentials. Complete the sign-in prompt in your AI tool, or send your API key in the `x-api-key` header. Don't put an API key in the `Authorization: Bearer` header — Bearer only accepts OAuth access tokens.
Older versions of Claude Desktop don't support remote MCP servers natively. Use the `mcp-remote` wrapper shown in the Claude Desktop tab above.
That's expected. The MCP endpoint only accepts requests from MCP clients, so a plain browser visit returns an error even when the server is healthy. Check the connection status in your AI tool's MCP settings instead.
Every search has a depth ceiling (see [Tips for large jobs](#tips-for-large-jobs)), and the page that hits it looks like a normal end of results. Split the query into narrower filters — for example by country, industry, or company size — so each one stays under the limit.
Check your network connection, restart your AI tool, and try again. If the issue persists, note the time of the request and the error message so you can report it to the Blitz team.
# Clay Integration
Source: https://docs.blitz-api.ai/guide/integrations/clay
# Clay Integration
> Enrich thousands of leads using the Clay HTTP API (Sculptor or Manual).
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
**Clay** is the ultimate partner for BlitzAPI. By combining our **Unlimited Data** with Clay's spreadsheet interface, you can build massive enrichment waterfalls without writing a single line of code.
## 🚀 The "Sculptor" Method (Fastest)
Clay's new **Sculptor** feature allows you to setup the integration simply by copy-pasting our documentation.
Go to our [API Reference](/api-reference) or [Quickstart](/guide/getting-started/quickstart) and copy any **cURL** command.
*Example:*
```bash theme={null} theme={null}
curl -X POST "https://api.blitz-api.ai/v2/search/waterfall-icp-keyword"\
-H "Content-Type: application/json"\
-H "x-api-key: YOUR_KEY"\
-d '{ "company_linkedin_url": "..." }'
```
In your Clay table:
1. Click **Add Enrichment** > **HTTP API**.
2. Look for the **"Paste cURL"** or **"Sculptor"** button.
3. Paste the code.
Clay's AI will automatically detect the `company_linkedin_url` (or other parameters) in the code and ask you which column in your table matches that data.
Simply select the correct column, and you are ready to run!
***
## ⚙️ Manual Setup (Standard)
If you prefer to configure the HTTP node manually, follow these settings.
1. **Method**: `POST`
2. **URL**: `https://api.blitz-api.ai/v2/search/waterfall-icp-keyword` (or other endpoint)
3. **Headers**:
* `content-type`: `application/json`
* `x-api-key`: `YOUR_API_KEY`
4. **Body**:
```json theme={null} theme={null}
{
"company_linkedin_url": "https://www.linkedin.com/company/wttj-fr",
"cascade": [
{
"include_title": ["HRD", "Human Director"],
"exclude_title": ["assistant", "intern", "product", "junior"],
"location": ["US", "CA"],
"include_headline_search": false
},
{
"include_title": ["HRD", "Human Director"],
"exclude_title": ["junior", "assistant", "intern", "hacker"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["HR", "Human resources "],
"exclude_title": ["junior", "assistant", "intern", "UX", "UI", "Design"],
"location": ["US", "CA"],
"include_headline_search": false
},
{
"include_title": ["HR", "Human resources"],
"exclude_title": ["junior", "assistant", "intern", "product"],
"location": ["US", "CA"],
"include_headline_search": true
},
{
"include_title": ["Talent", "Staff", "Office"],
"exclude_title": ["junior", "assistant", "intern"],
"location": ["WORLD"],
"include_headline_search": false
}
],
"max_results": 10
}
```
***
## 🛑 Critical: Rate Limiting
To respect BlitzAPI's throughput and ensure stability, you **must** configure the rate limit settings in Clay. Your requests-per-second limit depends on your plan and applies per endpoint; your key's exact limit is in the `max_requests_per_seconds` field of `GET /v2/account/key-info`.
In the HTTP Enrichment settings, go to **Rate Limit** and set exactly:
| Setting | Value |
| :- | :- |
| **Max Requests** | **5** |
| **Time Period** | **1000** ms |
**Strict Requirement**: Failure to set this limit to `1000ms` will result in `429 Too Many Requests` errors during bulk runs.
***
## Popular Clay Payloads
Copy-paste these JSON bodies directly into your integration.
### 1. Waterfall Search (Find Decision Maker)
*Target: Find Marketing Decision Maker.*
```json theme={null} theme={null}
{
"company_linkedin_url": "https://www.linkedin.com/company/wttj-fr",
"cascade": [
{
"include_title": ["Marketing Director", "Head Marketing", "Chief Marketing Officer"],
"exclude_title": ["assistant", "intern", "product", "junior"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["Marketing Manager", "Head Growth", "Growth manager"],
"exclude_title": ["junior", "assistant", "intern", "hacker"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["Communication Director", "Brand Director", "Content Director"],
"exclude_title": ["junior", "assistant", "intern", "UX", "UI", "Design"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["Communication", "marketing", "growth", "brand"],
"exclude_title": ["junior", "assistant", "intern", "product"],
"location": ["US", "CA"],
"include_headline_search": true
},
{
"include_title": ["CEO", "founder", "cofounder", "owner", "General Director"],
"exclude_title": ["junior", "assistant", "intern"],
"location": ["WORLD"],
"include_headline_search": false
}
],
"max_results": 10
}
```
### 2. Find People (ICP Sourcing across many companies)
*Target: Build a fresh list of VPs and Directors of Sales at IT Services companies (51–500 employees) headquartered in EMEA.*
**Endpoint**: `POST https://api.blitz-api.ai/v2/search/people`
```json theme={null} theme={null}
{
"company": {
"industry": { "include": ["IT Services and IT Consulting"] },
"employee_range": ["51-200", "201-500"],
"hq": { "sales_region": ["EMEA"] }
},
"people": {
"job_level": ["VP", "Director"],
"job_function": ["Sales & Business Development"],
"min_connections": 200
},
"max_results": 50,
"cursor": "{{Previous Cursor Column}}"
}
```
In Clay, store the returned `cursor` in a column and feed it back into the next run to paginate. Stop when `cursor` is `null`. See the [ICP List Building recipe](/guide/recipes/icp-list-building) for the full pattern.
### 3. Enrich Email (Find Work Email)
*Target: Get verified email from a Profile URL.*
```json theme={null} theme={null}
{
"person_linkedin_url": "{{Linkedin Profile Column}}"
}
```
***
## Mapping the Output
Once the request runs successfully:
1. Hover over the `results` cell in Clay.
2. Click **"Add to Table"**.
3. Select the fields you need (e.g., `email`, `phone`, `person_linkedin_url`).
Always map the `icp` field. It tells you which tier of your cascade was matched (`1` = Top Priority / Tier 1), helping you score and route your leads instantly.
# Make (Integromat) Integration
Source: https://docs.blitz-api.ai/guide/integrations/make
# Make (Integromat) Integration
> Build powerful enrichment scenarios using the HTTP module in Make.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
**Make** (formerly Integromat) allows you to integrate BlitzAPI into thousands of apps (Airtable, Hubspot, Google Sheets) visually.
Since BlitzAPI follows standard REST principles, you will use the generic **HTTP** app to interact with our endpoints.
## Standard Configuration
You will need the **HTTP** app > **Make a request** module.
Create a new scenario and add the HTTP module.
* **URL**: Paste your endpoint (e.g., `https://api.blitz-api.ai/v2/search/waterfall-icp-keyword`)
* **Method**: `POST`
Do not use the "User name/Password" fields. Instead, add a generic Header.
* **Item 1**:
* **Name**: `x-api-key`
* **Value**: `YOUR_BLITZ_API_KEY`
* **Item 2** (Optional but recommended):
* **Name**: `Content-Type`
* **Value**: `application/json`
Make offers a key-value interface, but for nested objects like our Waterfall Cascade, you must use **Raw** mode.
* **Body type**: `Raw`
* **Content type**: `JSON (application/json)`
* **Request content**: Paste the JSON recipe below and map your variables (the colorful bubbles) inside the quote marks.
***
## ⚡ Handling Rate Limits
Make processes scenarios instantly. If you trigger a run with 500 rows from Google Sheets, Make will fire 500 requests in a split second, triggering a `429 Too Many Requests` error from BlitzAPI.
To fix this, you must slow down the execution loop.
### The "Sleep" Tool Solution
1. Click on the **Tools** icon (Purple wrench) at the bottom of your screen.
2. Select **Sleep**.
3. Place this module **immediately after** your HTTP module.
4. Set **Delay** to `1` second.
**Result**: Make will wait 1 second between each operation, keeping you safely under your plan's per-endpoint rate limit.
***
## JSON Recipes (Raw Body)
Copy these payloads into the **"Request content"** field of your HTTP module. *`Note: Replace {{1.company_url}} with your actual mapped variable from previous modules.`*
### Scenario A: The Sales Leader
*Logic: Find the CRO or VP Sales. If not available, fallback to a Director level.*
```json theme={null} theme={null}
{
"company_linkedin_url": "{{1.company_linkedin_url}}",
"cascade": [
{
"include_title": ["Chief Revenue Officer", "CRO", "VP Sales"],
"location": ["US", "GB"],
"include_headline_search": false
},
{
"include_title": ["Head of Sales", "Sales Director"],
"location": ["US", "GB"],
"include_headline_search": true
}
],
"max_results": 1
}
```
### Scenario B: The Marketing Decision Maker
Logic: Prioritize the CMO globally. Fallback to VP or Head of Marketing.
```json theme={null} theme={null}
{
"company_linkedin_url": "{{1.company_linkedin_url}}",
"cascade": [
{
"include_title": ["Chief Marketing Officer", "CMO"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["VP Marketing", "Head of Marketing"],
"exclude_title": ["Assistant", "Intern"],
"location": ["WORLD"],
"include_headline_search": false
}
],
"max_results": 1
}
```
### Scenario C: Find People (ICP-wide search)
Target: Source decision-makers across an entire ICP in one HTTP module — combine company filters and person filters.
Endpoint: `POST https://api.blitz-api.ai/v2/search/people`
```json theme={null} theme={null}
{
"company": {
"industry": { "include": ["IT Services and IT Consulting"] },
"employee_range": ["51-200", "201-500"],
"hq": { "sales_region": ["EMEA"] }
},
"people": {
"job_level": ["VP", "Director"],
"job_function": ["Sales & Business Development"],
"min_connections": 200
},
"max_results": 50,
"cursor": "{{1.cursor}}"
}
```
**Pagination in Make**: wrap the HTTP module in a *Repeater* and store the returned `cursor` in a Data Store (or feed it directly via `{{1.cursor}}`). Stop the loop when the response field `cursor` equals `null`. See the [ICP List Building recipe](/guide/recipes/icp-list-building) for the end-to-end pattern.
### Scenario D: Enrich Email
Target: Convert a Profile URL to a Verified Email.
Endpoint: `POST https://api.blitz-api.ai/v2/enrichment/email`
```json theme={null} theme={null}
{
"person_linkedin_url": "{{1.person_linkedin_url}}"
}
```
## Troubleshooting
Check your Quotes. In Make's editor, it's easy to accidentally delete a quote mark " when dragging and dropping a variable bubble. Ensure your JSON syntax is valid.
Check Content Type. Ensure you explicitly selected JSON (application/json) in the Content type dropdown of the HTTP module. If you leave it blank, the API might not interpret the body correctly.
Parse the JSON. The HTTP module returns a raw JSON string/buffer. To use the data in the next step (e.g., update HubSpot), you must place a JSON > Parse JSON module after the HTTP request to convert the string back into mapped variables.
# n8n Integration
Source: https://docs.blitz-api.ai/guide/integrations/n8n
# n8n Integration
> Automate your enrichment pipelines using the HTTP Request node in n8n.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
**n8n** is the ideal orchestrator for complex BlitzAPI workflows. Its node-based architecture allows you to chain our **Waterfall Search**, **Enrichment**, and **CRM Sync** steps into a single autonomous agent.
## Standard Configuration
You will interact with BlitzAPI using the native **HTTP Request** node.
To avoid copy-pasting your key in every node, create a reusable credential.
1. Go to **Credentials** > **New** > Search for **"Header Auth"**.
2. **Name**: `x-api-key`
3. **Value**: `YOUR_BLITZ_API_KEY`
4. Save as "BlitzAPI Production".
Drag an **HTTP Request** node to your canvas.
* **Method**: `POST`
* **URL**: `https://api.blitz-api.ai/v2/search/waterfall-icp-keyword`
* **Authentication**: Select `Generic Credential Type` -> `Header Auth`.
* **Credential**: Select the "BlitzAPI Production" credential you just created.
Set **Send Body** to `active` and **Body Content Type** to `JSON`.
Use the **Expression Editor** to map your input data (e.g., `{{ $json.company_url }}`) into the JSON structure.
***
## ⚡ Handling Rate Limits (Crucial)
n8n executes workflows extremely fast. If you process 1,000 items through a single endpoint without precautions, you will hit BlitzAPI's **per-endpoint rate limit** (set by your plan) immediately, causing `429` errors.
To scale safely, you must implement a **Throttling Pattern**.
### The "Split In Batches" Pattern
Do not connect the trigger directly to the HTTP Request. Use this structure:
1. **Split In Batches** Node:
* Set **Batch Size** to `1` (or `5` maximum).
2. **HTTP Request** (BlitzAPI):
* Connect it after the split.
3. **Wait** Node:
* Connect it after the HTTP Request.
* Set **Amount** to `200` milliseconds.
4. **Loop Back**:
* Connect the Wait node back to the input of the "Split In Batches" node.
**Why?** This forces n8n to process items sequentially (or in small groups) with a tiny pause, ensuring you never exceed the API throughput capacity.
***
## Waterfall Recipes (Copy-Paste)
Here are optimized JSON payloads for common targeting scenarios.
### Scenario A: The Sales Leader
*Logic: Find the CRO or VP Sales. If not available, fallback to a Director level.*
```json theme={null} theme={null}
{
"company_linkedin_url": "{{ $json.company_linkedin_url }}",
"cascade": [
{
"include_title": ["Chief Revenue Officer", "CRO", "VP Sales"],
"location": ["US", "GB"],
"include_headline_search": false
},
{
"include_title": ["Head of Sales", "Sales Director"],
"location": ["US", "GB"],
"include_headline_search": true
}
],
"max_results": 1
}
```
### Scenario B: The Marketing Decision Maker
*Logic: Prioritize the CMO globally. Fallback to VP or Head of Marketing.*
```json theme={null} theme={null}
{
"company_linkedin_url": "{{ $json.company_linkedin_url }}",
"cascade": [
{
"include_title": ["Chief Marketing Officer", "CMO"],
"location": ["WORLD"],
"include_headline_search": false
},
{
"include_title": ["VP Marketing", "Head of Marketing"],
"exclude_title": ["Assistant", "Intern"],
"location": ["WORLD"],
"include_headline_search": false
}
],
"max_results": 1
}
```
### Scenario C: The Founder (SMB Targeting)
*Logic: Find the Owner or CEO, specifically in France or Germany.*
```json theme={null} theme={null}
{
"company_linkedin_url": "{{ $json.company_linkedin_url }}",
"cascade": [
{
"include_title": ["Founder", "Co-Founder", "Owner"],
"location": ["FR", "DE"],
"include_headline_search": true
},
{
"include_title": ["CEO", "PDG", "Gerant"],
"location": ["FR", "DE"],
"include_headline_search": false
}
],
"max_results": 1
}
```
***
## Find People in n8n (Cursor Pagination Pattern)
[Find People](/guide/concepts/find-people) (`POST /v2/search/people`) lets you source decision-makers across **many companies in one call**. It uses **cursor-based pagination**, which differs from the page-based pattern of Employee Finder — here is the canonical n8n loop.
### Workflow shape
1. **Set node** → initialize `cursor = null`.
2. **HTTP Request node** → call `/v2/search/people` with the body below.
3. **Item Lists (Split Out Items)** → fan out `results[]` for downstream enrichment.
4. **IF node** → check `{{$json.cursor}} !== null`.
5. **Set node** → update `cursor = {{$json.cursor}}` and loop back to step 2.
### Request body
```json theme={null} theme={null}
{
"company": {
"industry": { "include": ["IT Services and IT Consulting"] },
"employee_range": ["51-200", "201-500"],
"hq": { "sales_region": ["EMEA"] }
},
"people": {
"job_level": ["VP", "Director"],
"job_function": ["Sales & Business Development"],
"min_connections": 200
},
"max_results": 50,
"cursor": "={{ $json.cursor }}"
}
```
**Cursor vs. page**: do not try to compute pages from `total_results / max_results`. The `cursor` returned by the API is the only safe way to paginate — it's stable even if new profiles are added between calls. Stop the loop when the response field `cursor` equals `null`.
***
## Troubleshooting
**Check Expression Mode.** In the Body parameter, ensure you are in **JSON mode** (not Form-Urlencoded). If using expressions like `{{ $json.id }}`, make sure they resolve to valid strings, not objects.
**Check n8n Data Structure.** BlitzAPI returns a `results` array for searches. You might need to add an **"Item Lists"** node (operation: *Split Out Items*) after the HTTP Request to flatten the `results` array into separate n8n items.
**Check Credential Name.** In your "Header Auth" credential, the name of the header **must** be exactly `x-api-key`. If you named it `api-key` or `Authorization`, it will fail.
# Skills
Source: https://docs.blitz-api.ai/guide/integrations/skills
# Blitz Skills
> Drop-in agent skills that teach your AI coding agent to go to market with Blitz API.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## What are Blitz Skills?
[Blitz Skills](https://skills.sh/api-blitz/skills) are small, composable agent skills for
going to market with Blitz API — lead-finding scripts, outreach, content, analytics, and
lifecycle automation, plus the engineering that powers them.
They work with **any model** and any compatible coding agent. They're designed to be easy
to adapt: install them, then make them your own.
**Skills vs. MCP** — The [MCP Server](/guide/integrations/MCP) lets your AI tool call
every Blitz API endpoint directly and read the docs, and it comes with built-in skills.
The skills on this page are installable *playbooks* — scripts, prompts, and workflows
your coding agent can execute, and that you can adapt. They complement each other; use both.
***
## Quickstart
Install in about 30 seconds with the [skills.sh](https://skills.sh) CLI.
```bash theme={null} theme={null}
npx skills@latest add api-blitz/skills --skill '*'
```
Pick the skills you want, and select which coding agents to install them on.
You're ready to go. Ask your agent to run a GTM motion with Blitz — for example,
"build me a lead list of VPs of Sales at Series B SaaS companies."
***
## Available skills
Every skill available today lives in the **Blitz** bucket, and the three chain into one
workflow — scope the ICP, generate the script, then audit it before you run at scale. Each
also works on its own.
| Skill | What it does |
| :- | :- |
| **blitz-gtm-brainstorm** | Interviews you about a go-to-market goal and produces a validated brief (`gtm-brief.yaml`) — the right Blitz endpoint, an enum-checked ICP, an enrichment plan, and a volume estimate. |
| **blitz-create-script** | Turns that brief into a runnable script on the official Blitz SDK (`blitz-api-py` / `blitz-api-js`) — installs dependencies, handles pagination, and adds API-key safety and error handling. |
| **blitz-reviewer** | Audits an existing Blitz integration before you run it — checks MCP, SDK, and skill versions, scans your code for wrong methods and case-sensitive enum typos, and reports your key's rate limit and record balance. |
Starting a new motion? Run them in order — **brainstorm** to scope the ICP,
**create-script** to build it, **reviewer** to preflight before you scale.
The collection also ships two buckets that are still growing:
* **GTM** — general go-to-market work: outreach, content, analytics, and lifecycle automation.
* **Productivity** — general workflow tools, not GTM-specific.
***
## Learn more
See every available skill and what it does.
Read, fork, and adapt the skills — they're meant to be hacked on.
# CRM Hygiene Playbook
Source: https://docs.blitz-api.ai/guide/recipes/crm-hygiene
# CRM Hygiene Playbook
> Dynamic enrichment and automated cleaning workflows.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Data decay is inevitable, but manual cleaning is obsolete. With BlitzAPI's **Unlimited Model**, RevOps teams can shift from "Annual Cleaning" to **"Continuous Hygiene"**.
Instead of buying static lists, you can build **Dynamic Playbooks** that trigger exactly when you need them.
***
## Playbook 1: The "Dynamic Account" Enrichment
*(The "Surgical Strike" Approach)*
**The Scenario**: A Sales Rep is working a high-priority Account in Salesforce/HubSpot. The account has potential, but the Rep lacks the *right* contacts (e.g., the VP of Sales is missing).
**The Solution**: Instead of asking the Rep to go to LinkedIn and manually copy-paste data, you give them an **"Enrich Now" button** in the CRM.
The Rep clicks a button in the CRM (via a Webhook/Flow). The CRM account must have either a **Company LinkedIn URL** or a **Company Domain** stored.
BlitzAPI requires a **Company LinkedIn URL** as its primary matching key — a domain alone is not a reliable identifier.
* **If the CRM already stores the LinkedIn URL**: use it directly as `company_linkedin_url`.
* **If only a domain is available**: first call `POST /v2/enrichment/domain-to-linkedin` to resolve the domain into a LinkedIn URL, then pass the result to the next step.
Send the Company LinkedIn URL to BlitzAPI's **Waterfall ICP** endpoint (`POST /v2/search/waterfall-icp-keyword`).
* *Example query*: "Find the VP Sales or CRO in the US for this company."
BlitzAPI returns the matched contact's LinkedIn URL and profile. Pass it to the enrichment endpoints to retrieve the **Verified Email** and/or **Phone**. The automation creates the Contact in the CRM and assigns it to the Rep instantly.
***
## Playbook 2: Net-New Sourcing from your ICP
*(The "Fill the Funnel" Approach)*
**The Scenario**: Cleaning what's already in the CRM is necessary, but it doesn't grow the pipeline. You also need a steady stream of **net-new** decision-makers matching your ICP — without buying static lists.
**The Solution**: A scheduled job that runs [Find People](/guide/concepts/find-people) against your ICP definition, diffs the results against existing CRM contacts (by `linkedin_url`), and inserts only the new ones.
Store your ICP as a JSON request body (industry + employee\_range + HQ + persona). See the [ICP List Building recipe](/guide/recipes/icp-list-building) for a complete template.
A weekly cron in n8n/Make calls `POST /v2/search/people`, paginating with the `cursor` until exhausted.
For each returned person, check if `linkedin_url` already exists in your CRM. Skip duplicates.
Pass each net-new `linkedin_url` to `/v2/enrichment/email` (and `/v2/enrichment/phone` for US contacts), validate, then create the Contact in the CRM.
> **RevOps Insight**: Pair this Net-New Sourcing playbook with Playbook 1 (Dynamic Account Enrichment). One *fills* the funnel from your ICP; the other *deepens* coverage on accounts already in motion.
***
## Scaling with Low-Code (n8n, Make, Clay)
The true power of BlitzAPI is unleashed when combined with automation platforms. Because our plans are **Unlimited**, you can run massive loops without worrying about per-request costs.
> **RevOps Insight**: With the Unlimited Plan, you can set up a "Weekend Job" in n8n that scans your entire CRM, re-enriches every email, and updates job titles, ensuring your team walks in on Monday to a pristine database. Emails returned by `/v2/enrichment/email` are already verified at source — re-tested against mail servers at least once every 30 days — so no separate validation step is needed.
***
## Ready to build?
Start building your dynamic playbooks today.
Copy-paste recipes for your favorite automation tools.
# ABM Playbook
Source: https://docs.blitz-api.ai/guide/recipes/enrichment-workflow
# ABM Playbook
> Penetrate strategic accounts with surgical precision — from a named-account list to a multi-threaded buying committee.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
**No named-account list yet?** This recipe starts from a **known company list**. If you instead want to *generate* the list of decision-makers from an ICP definition (industry + size + persona), use the [ICP List Building recipe](/guide/recipes/icp-list-building) which is built around the [Find People](/guide/concepts/find-people) endpoint.
**The Challenge**: You have a list of 500 "Dream Accounts" (ICP) in your CRM.
**The Old Way**: Your SDRs spend days manually searching LinkedIn, copying random emails, and hitting "Send" to whoever they find.
**The Blitz Way**: Automate the entire breakthrough process. Identify the buying committee, verify their data, and enroll them in sequences---instantly.
This playbook demonstrates how to build an **Account Breakthrough Engine** using BlitzAPI.
***
## The Stack
* **Orchestrator**: n8n or Make (to glue everything together).
* **Data engine**: BlitzAPI (Waterfall ICP + Enrichment).
* **Source of truth**: HubSpot / Salesforce (input).
* **Execution**: Smartlead / Lemlist (cold email).
***
## The Workflow
We will move from a "Target Account List" to "Active Conversations" in up to 5 automated steps.
BlitzAPI's **Waterfall ICP** endpoint takes a `company_linkedin_url` as its primary input — not a domain. A LinkedIn URL is the only reliable company identifier in our dataset. See Step 1 for how to handle both cases.
Your CRM account record must provide a **Company LinkedIn URL** to run the Waterfall search.
* **If the CRM stores the LinkedIn URL directly**: use it as-is — skip to Step 1.
* **If only a domain is stored** (e.g., `stripe.com`): call `POST /v2/enrichment/domain-to-linkedin` first to resolve it into a Company LinkedIn URL.
```json theme={null} theme={null}
POST /v2/enrichment/domain-to-linkedin
{ "domain": "stripe.com" }
```
This returns the canonical `company_linkedin_url` to use in the next step.
Your workflow pulls the target accounts from your CRM. For each account, you now have a `company_linkedin_url` (either stored directly or resolved in Step 0).
We don't just want *any* contact. We want the **Economic Buyer** first, then the **Champion**.
Send the `company_linkedin_url` to BlitzAPI with a strict priority hierarchy:
1. **Tier 1**: C-Level & VPs (The Decision Makers).
2. **Tier 2**: Directors (The Champions).
3. **Tier 3**: Managers (The Entry Points).
Pass each matched `linkedin_url` to `POST /v2/enrichment/email` (and `/v2/enrichment/phone` for US contacts). Emails are verified at source and re-tested every 30 days — no separate validation step needed.
Push data back to the CRM with context tags:
* `Tag: Tier 1 - Decision Maker`
* `Tag: Tier 2 - Champion`
This allows Smartlead/Lemlist to send **different scripts** to the VP (Strategic value) vs. the Manager (Operational pain).
***
## Waterfall Configuration
This is the brain of the operation. By setting `max_results: 5`, we ensure we penetrate the account with multiple touchpoints without spamming the entire directory.
**Endpoint**: `POST /v2/search/waterfall-icp-keyword`
```json theme={null} theme={null}
{
"company_linkedin_url": "https://www.linkedin.com/company/target-account",
"cascade": [
{
"include_title": ["Chief Revenue Officer", "CRO", "VP Sales", "Head of Growth"],
"location": ["US", "GB"],
"include_headline_search": false
},
{
"include_title": ["Sales Director", "Director of Business Development"],
"location": ["US", "GB"],
"include_headline_search": true
},
{
"include_title": ["Sales Manager", "Account Executive Team Lead"],
"location": ["US", "GB"],
"include_headline_search": false
}
],
"max_results": 5
}
```
**Pro Tip**: Notice the `max_results: 5`. BlitzAPI will fill these 5 slots starting from the top of your cascade. If it finds 5 C-Levels, it stops there. If it only finds 1 C-Level, it fills the remaining 4 slots with Directors. **You always get the best possible seniority mix.**
***
## Why the Unlimited Model Enables This
Traditional per-call providers make this strategy prohibitively expensive at scale. With BlitzAPI's flat monthly subscription:
* **No metering**: run the playbook on 1,000 or 100,000 accounts for the same price.
* **Refresh anytime**: re-run quarterly to catch job changes and new hires without watching a meter.
* **Multi-thread freely**: pull 5 personas per account instead of 1 to maximize reply rates.
See our n8n templates to orchestrate this flow.
Prefer spreadsheets? Run this logic inside Clay.
# List Building Playbook
Source: https://docs.blitz-api.ai/guide/recipes/icp-list-building
# List Building Playbook
> Build a fresh, enriched prospecting list across your entire ICP — from zero to CRM-ready in one workflow.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Most "list building" workflows are painful because they require **two passes**: first build a company list (Company Search), then loop over each company to fetch employees (Employee Finder), then enrich each person. **Find People collapses the first two steps into one call.**
This recipe shows how to go from a blank ICP definition to a fully-enriched prospecting list ready to push to your CRM or sequencer.
***
## What You'll Build
A repeatable pipeline that:
1. Takes a single ICP definition (industry + size + geography + persona).
2. Calls **Find People** with cursor-based pagination to collect every matching decision-maker.
3. Enriches each person with a verified work email (and optionally a US phone).
4. Outputs a clean CSV / CRM payload.
***
## Step 1 — Define the ICP
The ICP lives entirely in the Find People request body. Combine **company filters** (who you sell to) with **people filters** (who you talk to inside those companies).
```json theme={null} theme={null}
{
"company": {
"industry": { "include": ["IT Services and IT Consulting", "Software Development"] },
"employee_range": ["51-200", "201-500"],
"hq": { "sales_region": ["EMEA"] },
"type": { "include": ["Privately Held"] }
},
"people": {
"job_level": ["VP", "Director"],
"job_function": ["Sales & Business Development", "Advertising & Marketing"],
"min_connections": 200
},
"max_results": 50
}
```
Iterate this JSON like you would iterate a SQL query. Loosen one filter at a time (`employee_range`, then `industry`, then `min_connections`) until your `total_results` lands in the right ballpark for your campaign volume.
***
## Step 2 — Paginate with the cursor
Find People uses **cursor-based** pagination, but the SDK handles it — iterate (or `collect()`) the returned page and it fetches each subsequent page for you. Each page holds up to `max_results` (max `50`).
```javascript Node.js theme={null} theme={null}
async function buildIcpList(icp, maxItems = 1000) {
// The SDK paginates automatically; collect() gathers every match into an array.
// max_results is only the page size — max_items is the client-side total cap that
// actually bounds spend (the API bills 1 record per result returned).
return client.search.people({ ...icp, max_results: 50, max_items: maxItems }).collect();
}
```
```python Python theme={null} theme={null}
def build_icp_list(icp, max_items=1000):
# The SDK paginates automatically; auto_paging_iter streams every match across pages.
# max_results is only the page size — max_items is the client-side total cap that
# actually bounds spend (the API bills 1 record per result returned).
return list(
client.search.people(**icp, max_results=50).auto_paging_iter(max_items=max_items)
)
```
***
## Step 3 — Enrich emails (and phones)
Find People returns LinkedIn profile URLs but no contact points. Pass each `linkedin_url` to the enrichment endpoints.
`POST /v2/enrichment/email` with `person_linkedin_url`. Returns a verified email or `found: false`.
`POST /v2/enrichment/phone` with `person_linkedin_url`. Skip people whose `location.country_code` is not `US`.
Emails returned by `/v2/enrichment/email` are already verified at source — they're re-tested against mail servers at least once every 30 days. You can push them straight to your sequencer without an additional validation step.
```javascript theme={null} theme={null}
async function enrichPerson(person) {
const email = await client.enrichment.email({
person_linkedin_url: person.linkedin_url,
});
const phone =
person.location?.country_code === "US"
? await client.enrichment.phone({
person_linkedin_url: person.linkedin_url,
})
: null;
return { ...person, email: email.email ?? null, phone: phone?.phone ?? null };
}
```
The SDK enforces the per-endpoint rate limit for you (a single client instance stays under your limit on each endpoint) and retries automatically on `429`. Reuse one `client` across your enrichment calls — see [Configuration](/sdks/typescript#configuration).
***
## Step 4 — Output for CRM / Sequencer
Map the Find People + enrichment payload to the columns your CRM expects:
| CRM Field | Source |
| :- | :- |
| `first_name` | `person.first_name` |
| `last_name` | `person.last_name` |
| `title` | `person.experiences[0].job_title` (current role) |
| `company` | `person.experiences[0].company_linkedin_url` → enrich later |
| `linkedin_url` | `person.linkedin_url` |
| `email` | `enrichment.email` |
| `phone` | `enrichment.phone` (US only) |
| `country` | `person.location.country_code` |
| `seniority` | derived from `experiences[0].job_title` |
***
## When to Re-Run
Re-run the same ICP definition on a schedule (weekly or monthly) to capture **net-new** decision-makers as people change roles. Diff against your existing CRM by `linkedin_url` to insert only new contacts.
For *cleaning* existing CRM contacts (vs. sourcing new ones), use the [CRM Hygiene Playbook](/guide/recipes/crm-hygiene) instead.
***
Full filter reference and response schema.
Need to penetrate a *named* account list instead? Use the Waterfall recipe.
Clean and re-enrich your existing contacts on a schedule.
Case-sensitive enums for industry, job level, job function, sales region.
# Reference & Standards
Source: https://docs.blitz-api.ai/guide/reference/appendix
# Reference & Standards
> Endpoint index, country codes, data logic, and performance details.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
This section covers technical standards and logic details to help you build reliable integrations with BlitzAPI.
## 📋 Endpoint Index
All v2 endpoints at a glance. Base URL: `https://api.blitz-api.ai`. All endpoints use `POST` except `key-info`.
| Endpoint | Method | Description | Minimum plan |
| :- | :- | :- | :- |
| `/v2/account/key-info` | `GET` | Check API key validity and rate limit | Any |
| `/v2/search/waterfall-icp-keyword` | `POST` | Find decision-makers via cascade hierarchy (cached data, \<600ms) | Unlimited Leads |
| `/v2/search/employee-finder` | `POST` | Search employees at one company by role and seniority level | Unlimited Leads |
| `/v2/search/people` | `POST` | Search people across many companies (company + person filters) | Unlimited Leads |
| `/v2/search/companies` | `POST` | Find companies by filters (industry, size, location, keywords) | Unlimited Leads |
| `/v2/enrichment/email` | `POST` | LinkedIn profile URL → verified work email | Unlimited Email |
| `/v2/enrichment/phone` | `POST` | LinkedIn profile URL → phone number (**US only**) | Unlimited Phone Numbers |
| `/v2/enrichment/email-to-person` | `POST` | Work email → full person profile | Unlimited Leads |
| `/v2/enrichment/phone-to-person` | `POST` | Phone number → full person profile | Unlimited Leads |
| `/v2/enrichment/company` | `POST` | Company LinkedIn URL → full company profile | Unlimited Leads |
| `/v2/enrichment/domain-to-linkedin` | `POST` | Website domain → Company LinkedIn URL | Unlimited Leads |
| `/v2/enrichment/linkedin-to-domain` | `POST` | Company LinkedIn URL → verified email domain | Unlimited Leads |
| `/v2/enrichment/company-distribution-by-country` | `POST` | Company LinkedIn URL → employee distribution by country | Unlimited Leads |
| `/v2/enrichment/company-distribution-by-department` | `POST` | Company LinkedIn URL → employee distribution by department | Unlimited Leads |
| `/v2/utils/current-date` | `POST` | Get current server date/time for a timezone | Any |
Search endpoints require a **Company LinkedIn URL** as input (not a domain). If you only have a domain, use `/v2/enrichment/domain-to-linkedin` first.
***
## 🌍 Country Codes (LinkedIn)
All BlitzAPI search endpoints use **2-letter country codes** following the ISO 3166-1 alpha-2 standard (consistent with LinkedIn). Using the wrong format (e.g., `USA` instead of `US`) will return 0 results. See the [Field Normalization reference](/guide/reference/normalization/geography#country-codes) for the full list.
Use `"WORLD"` to search globally without geographic restriction.
| Country | Code |
| :- | :- |
| **United States** | `US` |
| **United Kingdom** | `GB` |
| **France** | `FR` |
| **Canada** | `CA` |
| **Germany** | `DE` |
| **Australia** | `AU` |
| **India** | `IN` |
| **Brazil** | `BR` |
| **Singapore** | `SG` |
[*For a full list of supported codes, refer to the Microsoft LinkedIn Documentation.*](https://learn.microsoft.com/en-us/linkedin/shared/references/reference-tables/country-codes)
***
## 📧 Email Logic: Matching vs. Guessing
A common misconception is that enrichment APIs "guess" emails (permutations like `first.last@domain.com`). **BlitzAPI does not do this.**
### How we work
1. **Identity Matching**: We match the LinkedIn profile against a massive dataset of known, verified identities.
2. **No Permutations**: We only return an email if we have a concrete record of it linked to that specific individual.
3. **Freshness Guarantee**:
* We do not serve stale data.
* Every email in our database is re-validated **at least once every 30 days**.
* If an email bounces during our internal checks, it is immediately removed from the circulation.
This approach ensures a significantly lower bounce rate compared to "pattern-matching" tools.
***
## 🚦 Rate Limits & Latency
To ensure stability for all users:
* **Rate limit**: Your requests-per-second (RPS) limit depends on your plan and applies **per endpoint**. Each endpoint has its own independent budget, so calls to `/enrichment/email` and `/enrichment/phone` don't compete. Use the `max_requests_per_seconds` field from `/v2/account/key-info` to get your exact per-endpoint limit.
* **Burst**: Short bursts above the limit may be queued, but sustained overage returns `429 Too Many Requests`.
* **Retry on 429**: Wait at least 60 seconds before retrying after a server-side `429`. Client-side rate limiting should prevent this.
**Recommended Client Timeouts:**
| Endpoint Type | Recommended Timeout |
| :- | :- |
| Waterfall ICP, Employee Finder, Find People, Company Search | 10 seconds |
| Enrichment (email, phone, company) | 10 seconds |
**Error Codes:**
| Code | Meaning | Solution |
| :- | :- | :- |
| `400` | Bad Request | The request body is not valid JSON. |
| `401` | Unauthorized | Missing or invalid `x-api-key` header. |
| `402` | Payment Required | Account limit reached. Upgrade your plan. |
| `404` | Not Found | API key does not exist. |
| `422` | Unprocessable Entity | A request field is unknown or has an invalid value. The `errors` list names each one. |
| `429` | Too Many Requests | Exceeded an endpoint's rate limit. Throttle client-side to your plan's `max_requests_per_seconds`. |
| `500` | Internal Server Error | Transient server error. Retry with exponential backoff. |
See [Errors](/guide/reference/errors) for the `422` response format.
# Errors
Source: https://docs.blitz-api.ai/guide/reference/errors
HTTP status codes returned by the Blitz API and how to handle them. A 422 lists every invalid or unknown request field with its path and the closest valid field or value, and uses no records.
# Errors
> Every error returns JSON with `success: false` and a readable `message`. A `422` also lists each invalid field.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## Status codes
| Code | Meaning | What to do |
| :- | :- | :- |
| `400` | Bad Request | The request body is not valid JSON. Send a JSON object with the header `Content-Type: application/json`. |
| `401` | Unauthorized | Missing or invalid `x-api-key` header. |
| `402` | Payment Required | Account limit reached. Upgrade your plan. |
| `404` | Not Found | API key does not exist. |
| `422` | Unprocessable Entity | A request field is unknown or has an invalid value. Fix the fields listed in `errors` and resend. See [below](#validation-errors-422). |
| `429` | Too Many Requests | Exceeded an endpoint's rate limit. Throttle client-side to your plan's `max_requests_per_seconds`. |
| `500` | Internal Server Error | Transient server error. Retry with exponential backoff. |
| `503` | Service Unavailable | The service is temporarily unavailable. Retry with exponential backoff. |
Only `429`, `500`, and `503` are worth retrying as-is. A `400` or `422` fails the same way until you change the request.
***
## Validation errors (422)
The API checks the request body before it runs the request, so a `422` never uses records. A body is rejected when it contains:
* **A field the endpoint does not define**, at any depth. A misspelled filter such as `company.industry.includes` returns a `422` instead of being ignored.
* **A value outside an accepted list**, such as an industry, job level, or employee range. These values are case-sensitive: copy them from [Field Normalization](/guide/reference/normalization).
* **A wrong type or an out-of-range value**, such as a string for `max_results` or more than 50 items in a filter list.
```json Invalid value theme={null}
{
"success": false,
"message": "Invalid request body. company.industry.include[0]: Invalid value \"Software\". Did you mean \"Computer Software\", \"Software Development\" or \"Embedded Software Products\"?",
"errors": [
{
"field": "company.industry.include[0]",
"message": "Invalid value \"Software\". Did you mean \"Computer Software\", \"Software Development\" or \"Embedded Software Products\"?"
}
]
}
```
| Field | Type | Description |
| :- | :- | :- |
| `success` | `boolean` | Always `false`. |
| `message` | `string` | One-line summary of the first three errors, for logs. |
| `errors` | `array` | One item per problem, up to 20. |
| `errors[].field` | `string` | Path to the problem. Dots mark nesting and `[n]` marks an array item, e.g. `company.industry.include[0]`. |
| `errors[].message` | `string` | What is wrong. When the input is close to a valid field or value, it suggests the closest match. Otherwise a short list of allowed fields or values is given in full. |
For an unknown field, `field` is the object that contains it (`body` for a top-level field) and `message` names the rejected field:
```json Unknown field theme={null}
{
"success": false,
"message": "Invalid request body. company.industry: Unknown field \"includes\". Did you mean \"include\"?",
"errors": [
{
"field": "company.industry",
"message": "Unknown field \"includes\". Did you mean \"include\"?"
}
]
}
```
Read `errors[].field` to find what to fix, and treat `message` as text for humans: its wording can change.
Free-text filters such as `name`, `keywords`, `job_title`, `city`, and `country_code` are not checked against a list. A typo in one of them is not an error: the search runs and returns 0 results. See [Troubleshooting](/guide/reference/normalization#troubleshooting).
# Fair Use Policy
Source: https://docs.blitz-api.ai/guide/reference/fair-use-policy
# Fair Use Policy
> All plans, including unlimited plans, are subject to a fair use policy to prevent abuse of our systems.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
BlitzAPI plans are flat-rate and unlimited for normal business use. To keep the platform fast and reliable for everyone, **every plan is subject to a fair use policy**. It exists for one reason: to prevent abuse of our systems.
If your workload is legitimately high-volume, contact support before scaling up. We would much rather size a plan with you than throttle you mid-pipeline.
***
## Terms & Conditions
The fair use policy is part of our contractual terms. The authoritative version, including our rights and your obligations, lives in the Terms & Conditions.
Full legal terms governing your use of BlitzAPI, including the fair use policy.
# Companies
Source: https://docs.blitz-api.ai/guide/reference/normalization/companies
# Companies
> Accepted values, code references, and units for the company-level filters in Company Search and Find People — `company.type`, `company.employee_range`, `company.naics_code`, `company.sic_code`, `company.revenue`, `company.web_traffic`, `company.ad_spend`, and the funding filters (`company.total_funding`, `company.last_funding_amount`, `company.last_funding_year`, `company.last_funding_type`, `company.lead_investors`).
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## Employee Range
Used in: **Company Search**, **Find People** (`company.employee_range` filter)
| Value | Headcount |
| :- | :- |
| `"1-10"` | 1-10 employees |
| `"11-50"` | 11-50 employees |
| `"51-200"` | 51-200 employees |
| `"201-500"` | 201-500 employees |
| `"501-1000"` | 501-1,000 employees |
| `"1001-5000"` | 1,001-5,000 employees |
| `"5001-10000"` | 5,001-10,000 employees |
| `"10001+"` | More than 10,000 employees |
***
## Company Type
Used in: **Company Search**, **Find People** (`company.type.include` and `company.type.exclude` filters).
* `"Educational"`
* `"Educational Institution"`
* `"Government Agency"`
* `"Nonprofit"`
* `"Partnership"`
* `"Privately Held"`
* `"Public Company"`
* `"Self-Employed"`
* `"Self-Owned"`
* `"Sole Proprietorship"`
***
## NAICS Code
Used in: **Company Search**, **Find People** (`company.naics_code.include` and `company.naics_code.exclude` filters).
NAICS (North American Industry Classification System) codes are 2–6 digit strings maintained by the US Census Bureau. Codes are matched **exactly as strings** — a 6-digit query (`"541511"`) will not match a company stored at the 4-digit parent (`"5415"`) or vice versa. Use the most specific code you have.
| Example | Industry |
| :- | :- |
| `"5112"` | Software Publishers |
| `"5182"` | Data Processing, Hosting |
| `"541511"` | Custom Computer Programming Services |
| `"541512"` | Computer Systems Design Services |
| `"541613"` | Marketing Consulting Services |
Browse the full catalog at [census.gov/naics](https://www.census.gov/naics/).
***
## SIC Code
Used in: **Company Search**, **Find People** (`company.sic_code.include` and `company.sic_code.exclude` filters).
SIC (Standard Industrial Classification) codes are 4-digit strings — the older US classification still widely used by the SEC and credit databases. Like NAICS, matches are **exact strings** with no implicit prefix expansion.
| Example | Industry |
| :- | :- |
| `"7372"` | Prepackaged Software |
| `"7371"` | Computer Programming Services |
| `"7389"` | Business Services, NEC |
| `"6199"` | Finance Services |
| `"5961"` | Catalog, Mail-Order Houses |
Browse the full catalog at [osha.gov/sic-manual](https://www.osha.gov/data/sic-manual).
***
## Revenue, Web Traffic, Ad Spend
Used in: **Company Search**, **Find People** (`company.revenue`, `company.web_traffic`, `company.ad_spend` filters).
These three filters share the same `{ min, max }` shape. Pass `0` for either bound to leave it open — `{ min: 1_000_000, max: 0 }` means "at least 1M, no upper limit".
| Filter | Unit | Accepted range |
| :- | :- | :- |
| `revenue` | USD per year | `0` – `9.01e15` |
| `web_traffic` | Monthly visits (estimated) | `0` – `2.15e9` |
| `ad_spend` | USD per month on Google Ads (est.) | `0` – `1e12` |
`revenue` is matched as a range intersection: a company stored with the band `[5M, 50M]` matches a query of `{ min: 10M, max: 20M }`. `web_traffic` and `ad_spend` are matched as point ranges against the latest known monthly value.
Many companies have no public revenue, traffic, or ad-spend signal. Applying these filters narrows results aggressively — combine with a broad `industry` or `naics_code` rather than a strict `linkedin_url` list.
***
## Funding
Used in: **Company Search**, **Find People** (`company.total_funding`, `company.last_funding_amount`, `company.last_funding_year`, `company.last_funding_type`, `company.lead_investors` filters).
Qualify accounts by their fundraising history. The amount and year filters share the `{ min, max }` range shape — pass `0` on either bound to leave it open. `last_funding_type` and `lead_investors` use the `{ include, exclude }` shape.
| Filter | Shape | Unit / Values |
| :- | :- | :- |
| `total_funding` | `{ min, max }` | Total raised across all rounds, USD. `0` = unset. |
| `last_funding_amount` | `{ min, max }` | Amount raised in the most recent round, USD. `0` = unset. |
| `last_funding_year` | `{ min, max }` | Calendar year of the most recent round. `0` = unset. |
| `last_funding_type` | `{ include, exclude }` | Most recent round type — case-sensitive enum (see below). |
| `lead_investors` | `{ include, exclude }` | Keyword search across lead investor names (e.g. `"Sequoia"`). |
### Last Funding Type
`last_funding_type.include` and `last_funding_type.exclude` accept these **case-sensitive** values:
* `"Series unknown"`
* `"Pre seed"`
* `"Seed"`
* `"Series A"`
* `"Series B"`
* `"Series C"`
* `"Series D"`
* `"Series E-J"`
* `"Grant"`
* `"Angel"`
* `"Private equity"`
* `"Debt financing"`
* `"Non equity assistance"`
* `"Post IPO equity"`
* `"Undisclosed"`
* `"Post IPO debt"`
* `"Product crowdfunding"`
* `"Equity crowdfunding"`
* `"Corporate round"`
* `"Convertible note"`
* `"Secondary market"`
* `"Initial coin offering"`
* `"Post IPO secondary"`
`last_funding_amount` and `last_funding_type` describe the **most recent** round; `total_funding` is the cumulative amount across **all** rounds. `lead_investors` is a keyword search — `"Sequoia"` matches "Sequoia Capital" and "Sequoia Capital China".
Funding signals are sparse for many private companies. Applying these filters narrows results aggressively — combine them with a broad `industry` or `employee_range` rather than relying on funding alone.
# Keyword Filters
Source: https://docs.blitz-api.ai/guide/reference/normalization/filters
# Keyword Filters
> How `include` / `exclude` keyword search works across BlitzAPI Search endpoints, plus the exact-match bracket syntax.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
`.include` and `.exclude` filters are used as keyword search filters.
The phrases in one array work as OR filters. Inside one phrase, **all words must appear** in the value, in any order (see [How a phrase matches](#how-a-phrase-matches)).
For example, if you want to look for "Director" in the search results, you can use the following filter:
```json theme={null}
{
"include": ["Director"],
"exclude": []
}
```
```json theme={null}
[
"Director",
"Director of Sales",
"Director of Marketing",
"Director of Product",
...
]
```
```json theme={null}
{
"include": ["Director", "Manager"],
"exclude": ["Sales", "Marketing", "Product"]
}
```
Giving:
```json theme={null}
[
"Director of IT",
"Director of Finance",
"Engineering Manager",
"Finance Manager",
...
]
```
This will result in the following search:
```mermaid theme={null}
graph LR
Q[Query]
subgraph Includes[Include OR branches]
I1[Director]
I2[Manager]
end
E[Exclude on every branch:
Sales, Marketing, Product]
Q --> I1
Q --> I2
I1 --> D1[Director of IT]
I1 --> D2[Director of Sales]
I1 --> D3[Director of Marketing]
I1 --> D4[Director of Finance]
I2 --> M1[Engineering Manager]
I2 --> M2[Sales Manager]
I2 --> M3[Marketing Manager]
I2 --> M4[Finance Manager]
E -. remove .-> D2
E -. remove .-> D3
E -. remove .-> M2
E -. remove .-> M3
classDef excluded fill:#ffecec,stroke:#ff4d4f,color:#a8071a,stroke-width:1px;
class D2,D3,M2,M3 excluded;
```
## How a phrase matches
A phrase with more than one word is not searched as a fixed string. These rules apply to every `include` / `exclude` value without brackets, for example job titles in [Find People](/guide/concepts/find-people) and [Waterfall ICP](/guide/concepts/waterfall-logic):
* **All words must appear.** `"Head Marketing"` needs both `head` and `marketing` in the title.
* **The word order is free.** `"Head Marketing"` matches `Marketing Head` as well as `Head of Marketing`.
* **Words match as whole words.** `"Demand Gen"` does not match `Demand Generation`, and `"grow"` does not match `growth`.
* **Nothing is stemmed or expanded.** There are no synonyms, no abbreviation expansion (`VP` is not `Vice President`) and no stop-word removal, so `of` counts as a word when you write it.
* **Case and accents are ignored.** `"Céo"` and `"ceo"` are the same word.
* **Hyphens and punctuation split words.** `Co-CEO` is read as `co` + `ceo`, so the phrase `"CEO"` also matches it.
* **The phrases in one array are OR'd.** A value matches as soon as one of the phrases matches.
| Phrase | Matches | Does not match |
| :- | :- | :- |
| `"Head Marketing"` | `Head of Marketing`, `Marketing Head`, `Head, Marketing`, `Head of Product Marketing` | `Head of Sales`, `Marketing Manager` |
| `"Head of Marketing"` | `Head of Marketing`, `Head of Product Marketing` | `Marketing Head`, `Head, Marketing` (no `of`) |
| `"Demand Gen"` | `Demand Gen Manager`, `VP Demand Gen` | `Demand Generation Manager` |
| `"VP Sales"` | `VP of Sales`, `Sales VP`, `Senior VP Sales` | `Vice President of Sales`, `SVP Sales` |
To cover the variants of a title, list each form as its own phrase, for example `["VP Demand Gen", "VP Demand Generation", "Vice President Demand Generation"]`. Phrases in one array are OR'd, so any of them can match.
## Exact Match Syntax
On top of the regular keyword search, you can also use the exact match syntax.
Wrap a value in **square brackets** to switch to **exact match**: `"[CEO]"` matches only values whose lowercased, unaccented form equals `"ceo"`.
| Value | Behavior | Matches ✅ | Does **not** match ❌ | Case sensitive | Accent sensitive |
| :- | :- | :- | :- | :- | :- |
| `"CEO"` | Keyword search (default) | `CEO`, `Co ceo`, `ceo Office` | — | No | No |
| `"[CEO]"` | Exact (case- and accent-insensitive) | `CEO`, `ceo`, `Céo` | `Co ceo`, `CEO Office` | No | No |
The bracket syntax works in both `include` and `exclude`, and you can mix it in the same array — e.g. `["[CEO]", "Founder"]` means *exact `"ceo"` OR keyword `"Founder"`*.
# Geography
Source: https://docs.blitz-api.ai/guide/reference/normalization/geography
# Geography
> Sales regions, continents, and country codes (ISO 3166-1 alpha-2) for `location` filters across BlitzAPI Search endpoints.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## Sales Regions
Used in: **Employee Finder**, **Find People** (`people.location.sales_region` and `company.hq.sales_region`)
| Value | Coverage |
| :- | :- |
| `"NORAM"` | North America (US, Canada) |
| `"LATAM"` | Latin America |
| `"EMEA"` | Europe, Middle East, and Africa |
| `"APAC"` | Asia-Pacific |
***
## Continents
Used in: **Employee Finder**, **Find People** (`people.location.continent` and `company.hq.continent`)
| Value |
| :- |
| `"Africa"` |
| `"Antarctica"` |
| `"Asia"` |
| `"Europe"` |
| `"North America"` |
| `"Oceania"` |
| `"South America"` |
***
## Country Codes
Used in: **Waterfall ICP** (`location` field), **Employee Finder** (`country_code` field), **Company Search** (`hq.country_code` field).
Country codes follow the **ISO 3166-1 alpha-2** standard (consistent with LinkedIn).
For **Waterfall ICP Search**, use `"WORLD"` to search globally without geographic restriction. For **Employee Finder**, use `["WORLD"]` as `country_code` default or simply omit the field. For **Company Search** omit the location/hq fields entirely or pass empty arrays.
### Common Codes
| Country | Code |
| :- | :- |
| United States | `US` |
| United Kingdom | `GB` |
| France | `FR` |
| Canada | `CA` |
| Germany | `DE` |
| Australia | `AU` |
| Netherlands | `NL` |
| Spain | `ES` |
| Italy | `IT` |
| India | `IN` |
| Brazil | `BR` |
| Singapore | `SG` |
| Sweden | `SE` |
| Switzerland | `CH` |
| Belgium | `BE` |
| Denmark | `DK` |
| Norway | `NO` |
| Finland | `FI` |
| Poland | `PL` |
| Israel | `IL` |
| Japan | `JP` |
| South Korea | `KR` |
| China | `CN` |
| Mexico | `MX` |
| Argentina | `AR` |
| Chile | `CL` |
| Colombia | `CO` |
| South Africa | `ZA` |
| UAE | `AE` |
| Saudi Arabia | `SA` |
For the complete list of all country codes, refer to the [official ISO 3166-1 standard](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) or the [Microsoft LinkedIn Documentation](https://learn.microsoft.com/en-us/linkedin/shared/references/reference-tables/country-codes).
# Field Normalization
Source: https://docs.blitz-api.ai/guide/reference/normalization/index
# Field Normalization
> Accepted values for industry, employee range, job level, job function, company type, sales region, and country codes. All values are case-sensitive.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
BlitzAPI Search endpoints (Company Search, Employee Finder, **Find People**, Waterfall ICP) use **normalized values** for categorical filters. Passing a value outside the accepted list (e.g., `"SaaS"` instead of `"Software Development"`) returns a [`422`](/guide/reference/errors#validation-errors-422) that names the field and, when a valid value is close, suggests it. A `422` uses no records. Free-text filters such as `country_code`, `city`, `job_title`, and `keywords` are not checked against a list, so a wrong value there returns 0 results instead of an error.
All enum values are **case-sensitive** and must match exactly. Copy-paste from the linked pages to avoid typos.
***
## Sections
This reference is split across the following pages so each is small enough to load fast and easy to copy from:
`include` / `exclude` keyword search behavior, exact-match brackets, and the visual diagram of how branches and exclusions combine.
The full list of 534 accepted industry values for `company.industry.include` and `company.industry.exclude`.
`people.job_level` enum (C-Team, VP, Director, …) and the 22-value `people.job_function` enum.
`company.type` and `employee_range` enums, NAICS / SIC code references, units for `revenue`, `web_traffic`, and `ad_spend`, and the funding filters (`last_funding_type` values, `total_funding`, `lead_investors`).
Sales regions, continents, and country codes (ISO 3166-1 alpha-2) for `location` filters.
Accepted LinkedIn URL formats and what BlitzAPI normalizes for you.
***
## Troubleshooting
The most common cause is a wrong value in a free-text filter such as `country_code`, `city`, `job_title`, or `keywords`. These are not checked against a list, so a wrong value returns 0 results instead of an error. The usual one:
* **Country code**: `"USA"` is not valid, use `"US"`. `"United Kingdom"` is not valid, use `"GB"`.
See [Geography](/guide/reference/normalization/geography#country-codes) for every accepted country code.
A value outside an accepted list, or a field the endpoint does not define, returns a [`422`](/guide/reference/errors#validation-errors-422) instead of results. Each item in `errors` gives the `field` to fix and a `message` with the closest valid value. Common causes:
* **Industry**: `"Tech"` is not valid, use `"Information Technology and Services"` or `"Computer Software"` or `"Internet"`.
* **Employee range**: `"50-200"` is not valid, use `"51-200"`.
* **Job level**: `"vp"` is not valid, use `"VP"`. `"C-Level"` is not valid, use `"C-Team"`.
* **Job function**: `"Sales"` is not valid, use `"Sales & Business Development"`.
* **Sales region**: `"NA"` is not valid, use `"NORAM"`.
* **Field name**: `"includes"` is not a field, use `"include"`.
All values are case-sensitive. Copy-paste from the linked pages.
LinkedIn's industry taxonomy is granular. Try using multiple values in your `industry.include` array to broaden the search. For example, instead of just `"Computer Software"`, also include `"Information Technology and Services"` and `"Internet"`.
Check that you're using the right combination of `job_level` and `job_function`. For example, to find senior sales leaders, use `"job_level": ["C-Team", "VP", "Director"]` combined with `"job_function": ["Sales & Business Development"]`.
If the request succeeds but returns nothing:
* Make sure at least one of `company` or `people` is provided.
* Avoid over-filtering: combining a narrow `industry`, a small `employee_range` bucket, **and** a strict `hq.country_code` will quickly empty the result set.
* For person geography, set `people.location.country_code` (not `company.hq.country_code`) — those are independent filters.
Find People uses **cursor-based** pagination (not page-based). Pass the `cursor` value from the previous response back into the next request and stop when the API returns `cursor: null`. Do not assume `total_results / max_results` — use the cursor as the source of truth.
# Industry
Source: https://docs.blitz-api.ai/guide/reference/normalization/industries
# Industry
> The full list of 534 accepted industry values for `company.industry.include` and `company.industry.exclude` filters.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Used in: **Company Search**, **Find People** (`company.industry.include` and `company.industry.exclude`)
Industry values are **case-sensitive** and must match exactly. Copy-paste from this page to avoid typos.
* `"Abrasives and Nonmetallic Minerals Manufacturing"`
* `"Accessible Architecture and Design"`
* `"Accessible Hardware Manufacturing"`
* `"Accommodation and Food Services"`
* `"Accounting"`
* `"Administration of Justice"`
* `"Administrative and Support Services"`
* `"Advertising Services"`
* `"Agricultural Chemical Manufacturing"`
* `"Agriculture; Construction; Mining Machinery Manufacturing"`
* `"Air; Water; and Waste Program Management"`
* `"Airlines and Aviation"`
* `"Airlines/Aviation"`
* `"Alternative Dispute Resolution"`
* `"Alternative Fuel Vehicle Manufacturing"`
* `"Alternative Medicine"`
* `"Ambulance Services"`
* `"Amusement Parks and Arcades"`
* `"Animal Feed Manufacturing"`
* `"Animation"`
* `"Animation and Post-production"`
* `"Apparel Manufacturing"`
* `"Apparel and Fashion"`
* `"Appliances; Electrical; and Electronics Manufacturing"`
* `"Architectural and Structural Metal Manufacturing"`
* `"Architecture and Planning"`
* `"Armed Forces"`
* `"Artificial Rubber and Synthetic Fiber Manufacturing"`
* `"Artists and Writers"`
* `"Arts and Crafts"`
* `"Audio and Video Equipment Manufacturing"`
* `"Automation Machinery Manufacturing"`
* `"Automotive"`
* `"Aviation and Aerospace"`
* `"Aviation and Aerospace Component Manufacturing"`
* `"Baked Goods Manufacturing"`
* `"Banking"`
* `"Bars; Taverns; and Nightclubs"`
* `"Bed-and-Breakfasts; Hostels; Homestays"`
* `"Beverage Manufacturing"`
* `"Biomass Electric Power Generation"`
* `"Biotechnology"`
* `"Biotechnology Research"`
* `"Blockchain Services"`
* `"Blogs"`
* `"Boilers; Tanks; and Shipping Container Manufacturing"`
* `"Book Publishing"`
* `"Book and Periodical Publishing"`
* `"Breweries"`
* `"Broadcast Media"`
* `"Broadcast Media Production and Distribution"`
* `"Building Construction"`
* `"Building Equipment Contractors"`
* `"Building Finishing Contractors"`
* `"Building Materials"`
* `"Building Structure and Exterior Contractors"`
* `"Business Consulting and Services"`
* `"Business Content"`
* `"Business Intelligence Platforms"`
* `"Business Supplies and Equipment"`
* `"Cable and Satellite Programming"`
* `"Capital Markets"`
* `"Caterers"`
* `"Chemical Manufacturing"`
* `"Chemical Raw Materials Manufacturing"`
* `"Chemicals"`
* `"Child Day Care Services"`
* `"Chiropractors"`
* `"Circuses and Magic Shows"`
* `"Civic and Social Organization"`
* `"Civic and Social Organizations"`
* `"Civil Engineering"`
* `"Claims Adjusting; Actuarial Services"`
* `"Clay and Refractory Products Manufacturing"`
* `"Climate Data and Analytics"`
* `"Climate Technology Product Manufacturing"`
* `"Coal Mining"`
* `"Collection Agencies"`
* `"Commercial Real Estate"`
* `"Commercial and Industrial Equipment Rental"`
* `"Commercial and Industrial Machinery Maintenance"`
* `"Commercial and Service Industry Machinery Manufacturing"`
* `"Communications Equipment Manufacturing"`
* `"Community Development and Urban Planning"`
* `"Community Services"`
* `"Computer Games"`
* `"Computer Hardware"`
* `"Computer Hardware Manufacturing"`
* `"Computer Networking"`
* `"Computer Networking Products"`
* `"Computer Software"`
* `"Computer and Network Security"`
* `"Computers and Electronics Manufacturing"`
* `"Conservation Programs"`
* `"Construction"`
* `"Construction Hardware Manufacturing"`
* `"Consumer Electronics"`
* `"Consumer Goods"`
* `"Consumer Goods Rental"`
* `"Consumer Services"`
* `"Correctional Institutions"`
* `"Cosmetics"`
* `"Cosmetology and Barber Schools"`
* `"Courts of Law"`
* `"Credit Intermediation"`
* `"Cutlery and Handtool Manufacturing"`
* `"Dairy"`
* `"Dairy Product Manufacturing"`
* `"Dance Companies"`
* `"Data Infrastructure and Analytics"`
* `"Data Security Software Products"`
* `"Death Care Services"`
* `"Defense and Space"`
* `"Defense and Space Manufacturing"`
* `"Dentists"`
* `"Design"`
* `"Design Services"`
* `"Desktop Computing Software Products"`
* `"Digital Accessibility Services"`
* `"Distilleries"`
* `"E-Learning Providers"`
* `"E-learning"`
* `"Economic Programs"`
* `"Education"`
* `"Education Administration Programs"`
* `"Education Management"`
* `"Electric Lighting Equipment Manufacturing"`
* `"Electric Power Generation"`
* `"Electric Power Transmission; Control; and Distribution"`
* `"Electrical Equipment Manufacturing"`
* `"Electrical and Electronic Manufacturing"`
* `"Electronic and Precision Equipment Maintenance"`
* `"Embedded Software Products"`
* `"Emergency and Relief Services"`
* `"Energy Technology"`
* `"Engineering Services"`
* `"Engines and Power Transmission Equipment Manufacturing"`
* `"Entertainment"`
* `"Entertainment Providers"`
* `"Environmental Quality Programs"`
* `"Environmental Services"`
* `"Equipment Rental Services"`
* `"Events Services"`
* `"Executive Office"`
* `"Executive Offices"`
* `"Executive Search Services"`
* `"Fabricated Metal Products"`
* `"Facilities Services"`
* `"Family Planning Centers"`
* `"Farming"`
* `"Farming; Ranching; Forestry"`
* `"Fashion Accessories Manufacturing"`
* `"Financial Services"`
* `"Fine Art"`
* `"Fine Arts Schools"`
* `"Fire Protection"`
* `"Fisheries"`
* `"Fishery"`
* `"Flight Training"`
* `"Food Production"`
* `"Food and Beverage Manufacturing"`
* `"Food and Beverage Retail"`
* `"Food and Beverage Services"`
* `"Food and Beverages"`
* `"Footwear Manufacturing"`
* `"Footwear and Leather Goods Repair"`
* `"Forestry and Logging"`
* `"Fossil Fuel Electric Power Generation"`
* `"Freight and Package Transportation"`
* `"Fruit and Vegetable Preserves Manufacturing"`
* `"Fuel Cell Manufacturing"`
* `"Fundraising"`
* `"Funds and Trusts"`
* `"Funeral Services"`
* `"Furniture"`
* `"Furniture and Home Furnishings Manufacturing"`
* `"Gambling Facilities and Casinos"`
* `"Gambling and Casinos"`
* `"Geothermal Electric Power Generation"`
* `"Glass Product Manufacturing"`
* `"Glass; Ceramics and Concrete"`
* `"Glass; Ceramics and Concrete Manufacturing"`
* `"Golf Courses and Country Clubs"`
* `"Government Administration"`
* `"Government Relations"`
* `"Government Relations Services"`
* `"Graphic Design"`
* `"Ground Passenger Transportation"`
* `"HVAC and Refrigeration Equipment Manufacturing"`
* `"Health and Human Services"`
* `"Health; Wellness and Fitness"`
* `"Higher Education"`
* `"Highway; Street; and Bridge Construction"`
* `"Historical Sites"`
* `"Holding Companies"`
* `"Home Health Care Services"`
* `"Horticulture"`
* `"Hospital and Health Care"`
* `"Hospitality"`
* `"Hospitals"`
* `"Hospitals and Health Care"`
* `"Hotels and Motels"`
* `"Household Appliance Manufacturing"`
* `"Household Services"`
* `"Household and Institutional Furniture Manufacturing"`
* `"Housing Programs"`
* `"Housing and Community Development"`
* `"Human Resources"`
* `"Human Resources Services"`
* `"Hydroelectric Power Generation"`
* `"IT Services and IT Consulting"`
* `"IT System Custom Software Development"`
* `"IT System Data Services"`
* `"IT System Design Services"`
* `"IT System Installation and Disposal"`
* `"IT System Operations and Maintenance"`
* `"IT System Testing and Evaluation"`
* `"IT System Training and Support"`
* `"Import and Export"`
* `"Individual and Family Services"`
* `"Industrial Automation"`
* `"Industrial Machinery Manufacturing"`
* `"Industry Associations"`
* `"Information Services"`
* `"Information Technology and Services"`
* `"Insurance"`
* `"Insurance Agencies and Brokerages"`
* `"Insurance Carriers"`
* `"Insurance and Employee Benefit Funds"`
* `"Interior Design"`
* `"International Affairs"`
* `"International Trade and Development"`
* `"Internet"`
* `"Internet Marketplace Platforms"`
* `"Internet News"`
* `"Internet Publishing"`
* `"Interurban and Rural Bus Services"`
* `"Investment Advice"`
* `"Investment Banking"`
* `"Investment Management"`
* `"Janitorial Services"`
* `"Judiciary"`
* `"Landscaping Services"`
* `"Language Schools"`
* `"Laundry and Drycleaning Services"`
* `"Law Enforcement"`
* `"Law Practice"`
* `"Leasing Non-residential Real Estate"`
* `"Leasing Residential Real Estate"`
* `"Leather Product Manufacturing"`
* `"Legal Services"`
* `"Legislative Offices"`
* `"Leisure; Travel and Tourism"`
* `"Libraries"`
* `"Lime and Gypsum Products Manufacturing"`
* `"Loan Brokers"`
* `"Logistics and Supply Chain"`
* `"Luxury Goods and Jewelry"`
* `"Machinery"`
* `"Machinery Manufacturing"`
* `"Magnetic and Optical Media Manufacturing"`
* `"Management Consulting"`
* `"Manufacturing"`
* `"Maritime"`
* `"Maritime Transportation"`
* `"Market Research"`
* `"Marketing Services"`
* `"Marketing and Advertising"`
* `"Mattress and Blinds Manufacturing"`
* `"Measuring and Control Instrument Manufacturing"`
* `"Meat Products Manufacturing"`
* `"Mechanical Or Industrial Engineering"`
* `"Media Production"`
* `"Media and Telecommunications"`
* `"Medical Device"`
* `"Medical Equipment Manufacturing"`
* `"Medical Practice"`
* `"Medical Practices"`
* `"Medical and Diagnostic Laboratories"`
* `"Mental Health Care"`
* `"Metal Ore Mining"`
* `"Metal Treatments"`
* `"Metal Valve; Ball; and Roller Manufacturing"`
* `"Metalworking Machinery Manufacturing"`
* `"Military"`
* `"Military and International Affairs"`
* `"Mining"`
* `"Mining and Metals"`
* `"Mobile Computing Software Products"`
* `"Mobile Food Services"`
* `"Mobile Games"`
* `"Mobile Gaming Apps"`
* `"Motion Pictures and Film"`
* `"Motor Vehicle Manufacturing"`
* `"Motor Vehicle Parts Manufacturing"`
* `"Movies and Sound Recording"`
* `"Movies; Videos; and Sound"`
* `"Museums"`
* `"Museums and Institutions"`
* `"Museums; Historical Sites; and Zoos"`
* `"Music"`
* `"Musicians"`
* `"Nanotechnology"`
* `"Nanotechnology Research"`
* `"Natural Gas Distribution"`
* `"Natural Gas Extraction"`
* `"Newspaper Publishing"`
* `"Newspapers"`
* `"Non-profit Organization Management"`
* `"Non-profit Organizations"`
* `"Nonmetallic Mineral Mining"`
* `"Nonresidential Building Construction"`
* `"Nuclear Electric Power Generation"`
* `"Nursing Homes and Residential Care Facilities"`
* `"Office Administration"`
* `"Office Furniture and Fixtures Manufacturing"`
* `"Oil Extraction"`
* `"Oil and Coal Product Manufacturing"`
* `"Oil and Energy"`
* `"Oil and Gas"`
* `"Oil; Gas; and Mining"`
* `"Online Audio and Video Media"`
* `"Online Media"`
* `"Online and Mail Order Retail"`
* `"Operations Consulting"`
* `"Optometrists"`
* `"Other"`
* `"Outpatient Care Centers"`
* `"Outsourcing and Offshoring Consulting"`
* `"Outsourcing/Offshoring"`
* `"Package/Freight Delivery"`
* `"Packaging and Containers"`
* `"Packaging and Containers Manufacturing"`
* `"Paint; Coating; and Adhesive Manufacturing"`
* `"Paper and Forest Product Manufacturing"`
* `"Paper and Forest Products"`
* `"Parts Distribution"`
* `"Pension Funds"`
* `"Performing Arts"`
* `"Performing Arts and Spectator Sports"`
* `"Periodical Publishing"`
* `"Personal Care Product Manufacturing"`
* `"Personal Care Services"`
* `"Personal and Laundry Services"`
* `"Pet Services"`
* `"Pharmaceutical Manufacturing"`
* `"Pharmaceuticals"`
* `"Philanthropic Fundraising Services"`
* `"Philanthropy"`
* `"Photography"`
* `"Physical; Occupational and Speech Therapists"`
* `"Physicians"`
* `"Pipeline Transportation"`
* `"Plastics"`
* `"Plastics Manufacturing"`
* `"Plastics and Rubber Product Manufacturing"`
* `"Political Organization"`
* `"Political Organizations"`
* `"Postal Services"`
* `"Primary Metal Manufacturing"`
* `"Primary and Secondary Education"`
* `"Primary/Secondary Education"`
* `"Printing"`
* `"Printing Services"`
* `"Professional Organizations"`
* `"Professional Services"`
* `"Professional Training and Coaching"`
* `"Program Development"`
* `"Public Assistance Programs"`
* `"Public Health"`
* `"Public Policy"`
* `"Public Policy Offices"`
* `"Public Relations and Communications"`
* `"Public Relations and Communications Services"`
* `"Public Safety"`
* `"Public Works"`
* `"Publishing"`
* `"Racetracks"`
* `"Radio and Television Broadcasting"`
* `"Rail Transportation"`
* `"Railroad Equipment Manufacturing"`
* `"Railroad Manufacture"`
* `"Ranching"`
* `"Ranching and Fisheries"`
* `"Real Estate"`
* `"Real Estate Agents and Brokers"`
* `"Real Estate and Equipment Rental Services"`
* `"Recreational Facilities"`
* `"Recreational Facilities and Services"`
* `"Regenerative Design"`
* `"Religious Institutions"`
* `"Renewable Energy Equipment Manufacturing"`
* `"Renewable Energy Power Generation"`
* `"Renewable Energy Semiconductor Manufacturing"`
* `"Renewables and Environment"`
* `"Repair and Maintenance"`
* `"Research"`
* `"Research Services"`
* `"Residential Building Construction"`
* `"Restaurants"`
* `"Retail"`
* `"Retail Apparel and Fashion"`
* `"Retail Appliances; Electrical; and Electronic Equipment"`
* `"Retail Art Dealers"`
* `"Retail Art Supplies"`
* `"Retail Books and Printed News"`
* `"Retail Building Materials and Garden Equipment"`
* `"Retail Florists"`
* `"Retail Furniture and Home Furnishings"`
* `"Retail Gasoline"`
* `"Retail Groceries"`
* `"Retail Health and Personal Care Products"`
* `"Retail Luxury Goods and Jewelry"`
* `"Retail Motor Vehicles"`
* `"Retail Musical Instruments"`
* `"Retail Office Equipment"`
* `"Retail Office Supplies and Gifts"`
* `"Retail Pharmacies"`
* `"Retail Recyclable Materials and Used Merchandise"`
* `"Reupholstery and Furniture Repair"`
* `"Robot Manufacturing"`
* `"Robotics Engineering"`
* `"Rubber Products Manufacturing"`
* `"Satellite Telecommunications"`
* `"Savings Institutions"`
* `"School and Employee Bus Services"`
* `"Seafood Product Manufacturing"`
* `"Secretarial Schools"`
* `"Securities and Commodity Exchanges"`
* `"Security Guards and Patrol Services"`
* `"Security Systems Services"`
* `"Security and Investigations"`
* `"Semiconductor Manufacturing"`
* `"Semiconductors"`
* `"Services for Renewable Energy"`
* `"Services for the Elderly and Disabled"`
* `"Sheet Music Publishing"`
* `"Shipbuilding"`
* `"Shuttles and Special Needs Transportation Services"`
* `"Sightseeing Transportation"`
* `"Skiing Facilities"`
* `"Smart Meter Manufacturing"`
* `"Soap and Cleaning Product Manufacturing"`
* `"Social Networking Platforms"`
* `"Software Development"`
* `"Solar Electric Power Generation"`
* `"Sound Recording"`
* `"Space Research and Technology"`
* `"Specialty Trade Contractors"`
* `"Spectator Sports"`
* `"Sporting Goods"`
* `"Sporting Goods Manufacturing"`
* `"Sports"`
* `"Sports Teams and Clubs"`
* `"Sports and Recreation Instruction"`
* `"Spring and Wire Product Manufacturing"`
* `"Staffing and Recruiting"`
* `"Steam and Air-Conditioning Supply"`
* `"Strategic Management Services"`
* `"Subdivision of Land"`
* `"Sugar and Confectionery Product Manufacturing"`
* `"Supermarkets"`
* `"Surveying and Mapping Services"`
* `"Taxi and Limousine Services"`
* `"Technical and Vocational Training"`
* `"Technology; Information and Internet"`
* `"Technology; Information and Media"`
* `"Telecommunications"`
* `"Telecommunications Carriers"`
* `"Telephone Call Centers"`
* `"Temporary Help Services"`
* `"Textile Manufacturing"`
* `"Textiles"`
* `"Theater Companies"`
* `"Think Tanks"`
* `"Tobacco"`
* `"Tobacco Manufacturing"`
* `"Translation and Localization"`
* `"Transportation Equipment Manufacturing"`
* `"Transportation Programs"`
* `"Transportation/Trucking/Railroad"`
* `"Transportation; Logistics; Supply Chain and Storage"`
* `"Travel Arrangements"`
* `"Truck Transportation"`
* `"Trusts and Estates"`
* `"Turned Products and Fastener Manufacturing"`
* `"Urban Transit Services"`
* `"Utilities"`
* `"Utilities Administration"`
* `"Utility System Construction"`
* `"Vehicle Repair and Maintenance"`
* `"Venture Capital and Private Equity"`
* `"Venture Capital and Private Equity Principals"`
* `"Veterinary"`
* `"Veterinary Services"`
* `"Vocational Rehabilitation Services"`
* `"Warehousing"`
* `"Warehousing and Storage"`
* `"Waste Collection"`
* `"Waste Treatment and Disposal"`
* `"Water Supply and Irrigation Systems"`
* `"Water; Waste; Steam; and Air Conditioning Services"`
* `"Wellness and Fitness Services"`
* `"Wholesale"`
* `"Wholesale Alcoholic Beverages"`
* `"Wholesale Apparel and Sewing Supplies"`
* `"Wholesale Appliances; Electrical; and Electronics"`
* `"Wholesale Building Materials"`
* `"Wholesale Chemical and Allied Products"`
* `"Wholesale Computer Equipment"`
* `"Wholesale Drugs and Sundries"`
* `"Wholesale Food and Beverage"`
* `"Wholesale Footwear"`
* `"Wholesale Furniture and Home Furnishings"`
* `"Wholesale Hardware; Plumbing; Heating Equipment"`
* `"Wholesale Import and Export"`
* `"Wholesale Luxury Goods and Jewelry"`
* `"Wholesale Machinery"`
* `"Wholesale Metals and Minerals"`
* `"Wholesale Motor Vehicles and Parts"`
* `"Wholesale Paper Products"`
* `"Wholesale Petroleum and Petroleum Products"`
* `"Wholesale Photography Equipment and Supplies"`
* `"Wholesale Raw Farm Products"`
* `"Wholesale Recyclable Materials"`
* `"Wind Electric Power Generation"`
* `"Wine and Spirits"`
* `"Wineries"`
* `"Wireless"`
* `"Wireless Services"`
* `"Women\'s Handbag Manufacturing"`
* `"Wood Product Manufacturing"`
* `"Writing and Editing"`
* `"Zoos and Botanical Gardens"`
# Job Levels & Functions
Source: https://docs.blitz-api.ai/guide/reference/normalization/job-levels
# Job Levels & Functions
> Accepted values for `people.job_level` and `people.job_function` filters in Employee Finder and Find People.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
## Job Levels
Used in: **Employee Finder**, **Find People** (`people.job_level` filter)
| Value | Description |
| :- | :- |
| `"C-Team"` | C-Level executives (CEO, CTO, CFO, CMO, CRO…) |
| `"VP"` | Vice Presidents |
| `"Director"` | Directors |
| `"Manager"` | Managers |
| `"Staff"` | Individual contributors, specialists, analysts |
| `"Other"` | Roles that don't fit the above categories |
### How a title gets its level
The level comes from the words of the job title. When a title matches several rows below, the first rule that matches wins. `Other` signals and a short list of exceptions (such as `Account Manager` or `Chief of Staff`) are checked first, then `C-Team`, `VP`, `Director`, `Manager` and `Staff`, in that order. A title that matches no rule becomes `Staff`.
| Title wording | Level |
| :- | :- |
| Chief X Officer, CEO, CTO, CFO, CMO, Founder, Co-founder, Owner, President, Chair, Managing Director, Managing Partner, Partner | `"C-Team"` |
| VP, Vice President, SVP, EVP, AVP | `"VP"` |
| Director, **Head of X**, Board Member, General Director | `"Director"` |
| Manager, Team Lead, Lead, Supervisor, General Manager | `"Manager"` |
| Account Manager, Relationship Manager, Chief of Staff, Lead Generation, Business Partner, HR Partner | `"Staff"` |
| Intern, Student, Trainee, Volunteer, Retired | `"Other"` |
For example, `Head of Marketing` is a `"Director"`, and `Vice President of Sales` is a `"VP"`.
The level depends on the wording of the title, so an unusual wording can get a lower level. `Marketing Head` (no `of`) matches no rule and becomes `"Staff"`, while `Head of Marketing` is a `"Director"`. When you need exact titles, use title keywords instead of, or together with, `job_level`: `people.job_title` in [Find People](/guide/concepts/find-people) or `include_title` in [Waterfall ICP](/guide/concepts/waterfall-logic). See [Keyword Filters](/guide/reference/normalization/filters) for how they match.
***
## Job Functions
Used in: **Employee Finder**, **Find People** (`people.job_function` filter)
* `"Advertising & Marketing"`
* `"Art, Culture and Creative Professionals"`
* `"Construction"`
* `"Customer/Client Service"`
* `"Education"`
* `"Engineering"`
* `"Finance & Accounting"`
* `"General Business & Management"`
* `"Healthcare & Human Services"`
* `"Human Resources"`
* `"Information Technology"`
* `"Legal"`
* `"Manufacturing & Production"`
* `"Operations"`
* `"Other"`
* `"Public Administration & Safety"`
* `"Purchasing"`
* `"Research & Development"`
* `"Sales & Business Development"`
* `"Science"`
* `"Supply Chain & Logistics"`
* `"Writing/Editing"`
# LinkedIn URLs
Source: https://docs.blitz-api.ai/guide/reference/normalization/urls
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
This is a list of all supported LinkedIn URL formats (for fields such as `person_linkedin_url` or `company_linkedin_url`).
## People
### Supported
| Format | Example |
| :- | :- |
| Profile URL | `https://www.linkedin.com/in/john-smith-2a1ba6258` |
| Profile URL with LinkedIn's token | `https://www.linkedin.com/in/ACoAAB1cD2eF3gH...` |
| Sales Navigator lead URL | `https://www.linkedin.com/sales/lead/ACwAAA...,NAME_SEARCH,VAKJ` |
| Sales Navigator people URL | `https://www.linkedin.com/sales/people/ACwAAA...` |
| Profile URN | `urn:li:fsd_profile:ACoAAB1cD2eF3gH...` |
| Sales Navigator profile URN | `urn:li:fs_salesProfile:(ACwAAA...,NAME_SEARCH,VAKJ)` |
| Numeric member URN | `urn:li:member:122138853` |
### Not supported
* Sales Navigator profile-view URLs — `/sales/profile/...`
* Recruiter URLs — `/talent/profile/...`
* Legacy URLs — `/pub/...` and `/public-profile/in/...`
* Shortened links — `lnkd.in/...`
* `urn:li:person:...` — the public-API person URN is opaque and scoped to a single LinkedIn developer application, so it cannot be resolved to a profile
* A bare token on its own (e.g. `ACoAAB...`), without the surrounding `/in/` URL or `urn:li:` wrapper
## Companies
### Supported
| Format | Example |
| :- | :- |
| Company URL (vanity name) | `https://www.linkedin.com/company/microsoft` |
| Company URL (numeric ID) | `https://www.linkedin.com/company/1035` |
| Sales Navigator company URL | `https://www.linkedin.com/sales/company/90878032` |
| Organization URN | `urn:li:organization:1035` |
| Company URN | `urn:li:company:1035` |
# Welcome to BlitzAPI
Source: https://docs.blitz-api.ai/index
High-performance B2B data infrastructure for Growth & Revenue teams.
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
**BlitzAPI** provides a programmable interface to access **verified B2B data** from a proprietary LinkedIn-based dataset covering 550M+ contacts worldwide. We enable Growth Engineers and RevOps teams to build automated lead pipelines at scale — no scrapers to maintain, no static databases to manage.
***
## ⚡ Core Logic: Waterfall ICP
BlitzAPI's most popular feature is the **Waterfall ICP Search**. It solves a common engineering challenge: mapping a target account to a specific decision-maker without manual filtering.
Instead of retrieving a raw list of employees, you define a **priority hierarchy**. The API executes a cascading search until it matches your criteria.
You configure a JSON rule: *"First, look for the CEO in the US. If not found, look for the VP of Sales. If not found, look for a Sales Director."*
The API queries our proprietary dataset in priority order, stopping as soon as your criteria are matched.
You receive the single most relevant decision-maker for that company, ready for enrichment.
See how to construct hierarchical queries to maximize relevance.
***
## ♾️ Flat-Rate Unlimited
BlitzAPI is a **flat monthly subscription — no per-request fees, no overage surprises**. Choose the plan that unlocks the APIs you need.
| Plan | Price | Includes |
| :- | :- | :- |
| **Unlimited Leads** | \$399/mo | Waterfall ICP, Company Search, Employee Finder, Domain→LinkedIn, and more |
| **Unlimited Email** | \$499/mo | Everything above + Email Enrichment (65M+ emails, 97% accuracy) |
| **Unlimited Phone Numbers** | \$599/mo | Everything above + Phone Enrichment (US only, 45M+ mobile numbers) |
Detailed feature matrix, use case guide, and free trial info.
***
## People Search Family
Three complementary endpoints — pick the one that matches your scope.
Search decision-makers across **many companies** in one call. Combine company filters (industry, size, HQ) with person filters (job title, level, location).
Map **all employees** at one specific company with paginated, filtered results.
Get the **single best** decision-maker at a known company via a priority cascade.
***
## What do you want to build?
Select the documentation path that matches your technical goal.
Get your API Key and run your first enrichment request via the SDK or cURL.
Typed Python and TypeScript/JavaScript clients with retries, rate limiting, and auto-pagination.
One-click setup for Claude, Cursor, and more. Your AI can call every endpoint, read the docs, and use built-in skills.
Generate a fresh prospecting list across hundreds of accounts in one Find People call.
Chain Search, Enrichment, and Validation into a single automated pipeline.
Interactive OpenAPI documentation to test endpoints and view schema definitions.
***
## Supported Integrations
BlitzAPI acts as the data engine behind your existing stack.
| Category | Compatible Tools |
| :- | :- |
| **Orchestrators** | n8n, Make (Integromat), Zapier |
| **Data Operations** | Clay, Airtable, Google Sheets |
| **CRM & Sales** | HubSpot, Salesforce, Pipedrive |
| **Outreach** | Smartlead, Instantly, Lemlist |
| **AI Tools** | Claude, GPT, Cursor, Cursor |
**Building a custom integration?** Our API is platform-agnostic. As long as your tool can make an HTTP POST request, it works with BlitzAPI.
# Official SDKs
Source: https://docs.blitz-api.ai/sdks/overview
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Blitz ships official, fully typed SDKs for **Python** and **TypeScript / JavaScript**. Both wrap the same v2 REST API, use the exact same **snake\_case** field names you see in the [API reference](/api-reference/account/get-api-key-details), and handle the boilerplate for you — client-side rate limiting, retries with backoff on `429`/`5xx`, auto-pagination, and a typed error hierarchy.
`pip install blitz-api-py` — sync + async clients, Pydantic v2 models, Python 3.10+.
`npm install blitz-api-js` — Zod-validated types, ESM + CJS, Node 20+.
## Install
```bash Python theme={null} theme={null}
pip install blitz-api-py
# or: uv add blitz-api-py
```
```bash JavaScript / TypeScript theme={null} theme={null}
npm install blitz-api-js
# or: pnpm add blitz-api-js / yarn add blitz-api-js
```
## Why use an SDK?
* **Fully typed** — Pydantic v2 (Python) / Zod-inferred types (TS) for every request filter and response field, with editor autocomplete.
* **Auto-pagination** — iterate every result across pages without writing a cursor or page loop.
* **Resilient by default** — automatic retries with backoff on `429` and `5xx`, plus a typed exception hierarchy.
* **Usage metering built in** — every metered response carries a `fair_usage` block: the records the call consumed, the balance left, your rate-limit headroom, and a request id.
* **Client-side rate limiting** — a single client instance stays under your per-endpoint request-per-second limit.
* **Forward-compatible** — fields the API adds later are preserved, never dropped or rejected.
**Never expose your API key in client-side code** (browsers, mobile apps). Both SDKs send the key in the `x-api-key` header — always call Blitz from your backend. See [Authentication](/guide/getting-started/authentication).
## Quickstart
Both SDKs read the key from the `BLITZ_API_KEY` environment variable (or take it explicitly), then expose the same seven namespaces.
```python Python theme={null} theme={null}
from blitz_api import BlitzAPI
with BlitzAPI() as client:
# LinkedIn profile URL -> verified work email.
email = client.enrichment.email(
person_linkedin_url="https://www.linkedin.com/in/example-person",
)
if email.found:
print(email.email)
```
```ts TypeScript theme={null} theme={null}
import { BlitzAPI } from "blitz-api-js";
const client = new BlitzAPI();
// LinkedIn profile URL -> verified work email.
const email = await client.enrichment.email({
person_linkedin_url: "https://www.linkedin.com/in/example-person",
});
if (email.found) console.log(email.email);
```
## Endpoint coverage
Every v2 endpoint is a typed method, grouped into seven namespaces. Method names and fields are identical across both SDKs.
| Namespace | Method | REST endpoint | API reference |
| :- | :- | :- | :- |
| `account` | `key_info()` | `GET /v2/account/key-info` | [Get API key details](/api-reference/account/get-api-key-details) |
| `search` | `people()` | `POST /v2/search/people` | [Find people](/api-reference/people-search/find-people) |
| `search` | `companies()` | `POST /v2/search/companies` | [Company search](/api-reference/company-search/company-search) |
| `search` | `employee_finder()` | `POST /v2/search/employee-finder` | [Employee finder](/api-reference/people-search/employee-finder) |
| `search` | `waterfall_icp()` | `POST /v2/search/waterfall-icp-keyword` | [Waterfall ICP](/api-reference/people-search/waterfall-icp-search) |
| `jobs` | `search()` | `POST /v2/jobs/search` | [Search jobs](/api-reference/job-search/search-jobs) |
| `jobs` | `company()` | `POST /v2/jobs/company` | [Search company jobs](/api-reference/job-search/company-jobs) |
| `company` | `tam_by_jobs()` | `POST /v2/company/tam-by-jobs` | [TAM By Jobs](/api-reference/company-search/tam-by-jobs) |
| `enrichment` | `email()` | `POST /v2/enrichment/email` | [Find work email](/api-reference/people-enrichment/find-work-email) |
| `enrichment` | `phone()` | `POST /v2/enrichment/phone` | [Find mobile & direct phone](/api-reference/people-enrichment/find-mobile-&-direct-phone) |
| `enrichment` | `email_to_person()` | `POST /v2/enrichment/email-to-person` | [Reverse email lookup](/api-reference/people-enrichment/reverse-email-lookup) |
| `enrichment` | `phone_to_person()` | `POST /v2/enrichment/phone-to-person` | [Reverse phone lookup](/api-reference/people-enrichment/reverse-phone-lookup) |
| `enrichment` | `company()` | `POST /v2/enrichment/company` | [Company enrichment](/api-reference/company-enrichment/company-enrichment) |
| `enrichment` | `domain_to_linkedin()` | `POST /v2/enrichment/domain-to-linkedin` | [Domain to LinkedIn](/api-reference/company-enrichment/domain-to-linkedin-url) |
| `enrichment` | `linkedin_to_domain()` | `POST /v2/enrichment/linkedin-to-domain` | [LinkedIn to domain](/api-reference/company-enrichment/linkedin-url-to-domain) |
| `enrichment` | `company_distribution_by_country()` | `POST /v2/enrichment/company-distribution-by-country` | [Company distribution by country](/api-reference/utilities/company-employment-distribution) |
| `enrichment` | `company_distribution_by_department()` | `POST /v2/enrichment/company-distribution-by-department` | [Company distribution by department](/api-reference/utilities/company-department-distribution) |
| `utils` | `current_date()` | `POST /v2/utils/current-date` | [Current date & time](/api-reference/utilities/get-current-date-and-time) |
| `changelog` | `list()` | `GET /changelog` | [Get Changelog](/api-reference/changelog/changelog) |
## Next steps
Install, auth, async, pagination, configuration, and error handling for `blitz-api-py`.
Install, auth, pagination, configuration, and error handling for `blitz-api-js`.
Stream results across pages and cap spend with `max_items`.
The client-side limiter, automatic `429`/`5xx` retries, and timeout behavior.
How API keys work and how to health-check your key.
Full request/response schemas and an interactive try-it console.
# Pagination
Source: https://docs.blitz-api.ai/sdks/pagination
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
The search methods return an **auto-paginating page**. Iterate it and the SDK fetches each subsequent page for you — no cursor or page bookkeeping. This works identically in Python and TypeScript; only the syntax differs.
## Which methods paginate
| Method | Pagination |
| :- | :- |
| `client.search.people()` | Cursor-based |
| `client.search.companies()` | Cursor-based |
| `client.search.employee_finder()` | Page-based |
| `client.company.tam_by_jobs()` | Cursor-based |
| `client.jobs.search()` | Cursor-based |
| `client.jobs.company()` | Cursor-based |
| `client.search.waterfall_icp()` | None — one ranked result set |
| `client.changelog.list()` | None (a plain array of entries) |
| `client.enrichment.*` / `client.utils.*` / `client.account.*` | None — a single response |
Cursor vs page is an implementation detail — the SDK exposes the same interface for both. Cursors are stable even if new records are added between calls, so you won't see duplicates.
`company.tam_by_jobs` pages carry no `total_results` (the API omits it for TAM), so iterate until the `cursor` is `null`. `job.min_per_company` can also make a page come back partial: keep paging rather than stopping on a short page.
## Stream every result
Iterate the returned page to walk every match across all pages. Each page is fetched on demand, through the client's [rate limiter](/sdks/rate-limits).
```python Python theme={null} theme={null}
# The SDK fetches each subsequent page for you.
for person in client.search.people(people={"job_level": ["VP"]}):
print(person.full_name)
```
```ts TypeScript theme={null} theme={null}
// The SDK fetches each subsequent page for you.
for await (const person of client.search.people({ people: { job_level: ["VP"] } })) {
console.log(person.full_name);
}
```
`max_results` is the **page size** (1–50), not a total, and the API bills **1 record per result returned**. A bare loop streams *every* match up to the server-side cap (people / companies: 50,000 results or 1,000 pages; employee finder: 10,000; jobs: 5,000). Bound it with `max_items`, `break` out of the loop, or drive pages manually (below).
## Bound how much you pull
`max_items` is a **client-side** total cap — it stops the SDK fetching once reached and is never sent on the wire. Use it (with `max_results` tuned for page size) to keep spend predictable.
```python Python theme={null} theme={null}
# Stop after 200 results, across however many pages that takes.
for person in client.search.people(people={"job_level": ["VP"]}).auto_paging_iter(max_items=200):
print(person.full_name)
```
```ts TypeScript theme={null} theme={null}
// max_items goes in the options object.
for await (const person of client.search.people({ people: { job_level: ["VP"] }, max_items: 200 })) {
console.log(person.full_name);
}
// Or collect into an array (also honors max_items):
const people = await client.search.people({ people: { job_level: ["VP"] }, max_items: 200 }).collect();
```
## Per-page and manual control
Take the first page, inspect totals and cursors, and fetch the next page yourself when you need explicit control (your loop, your spend).
```python Python theme={null} theme={null}
# First page + manual paging.
page = client.search.people(people={"job_level": ["VP"]}, max_results=50)
print(page.results, page.cursor) # items on this page; cursor is None once exhausted
nxt = page.get_next_page() # None once exhausted
# Or walk pages and inspect totals as you go.
for p in client.search.companies(company={"industry": {"include": ["Software Development"]}}).iter_pages(max_pages=5):
print(p.total_results, len(p.results), p.cursor)
```
```ts TypeScript theme={null} theme={null}
// First page + manual paging.
const page = await client.search.companies({ company: { industry: { include: ["Software Development"] } }, max_results: 25 });
page.data; // Company[] — items on this page
page.response.total_results; // the full parsed response (snake_case, 1:1 with the API)
if (page.has_next_page()) {
const next = await page.get_next_page();
}
// Or walk pages directly:
const first = await client.search.employee_finder({ company_linkedin_url: "https://www.linkedin.com/company/openai", max_results: 50 });
for await (const p of first.iter_pages()) {
console.log(`page ${p.response.page}/${p.response.total_pages} — ${p.data.length} items`);
}
```
## Page object shape
* **Python** — items are on `page.results`; cursor on `page.cursor`. The page types (`CursorPage`, `PageNumberPage`, and their `Async*` variants) are exported from `blitz_api`.
* **TypeScript** — items are on `page.data`; the full parsed response (snake\_case, 1:1 with the API — e.g. `total_results`, `page`, `total_pages`) is on `page.response`.
## Next steps
How the client-side limiter and automatic `429`/`5xx` retries work.
Full method reference for `blitz-api-py`.
Full method reference for `blitz-api-js`.
Request/response schemas and a try-it console.
# Python SDK
Source: https://docs.blitz-api.ai/sdks/python
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
`blitz-api-py` is the official, typed Python SDK for the Blitz API. It ships sync and async clients over `httpx`, Pydantic v2 response models, `TypedDict` request filters, and a `py.typed` marker so mypy/pyright see the types in your own code.
`blitz-api-py` on the Python Package Index.
Source, changelog, and issues.
## Install
```bash theme={null} theme={null}
pip install blitz-api-py
# or: uv add blitz-api-py
```
Requires Python 3.10+.
## Quickstart
```python theme={null} theme={null}
from blitz_api import BlitzAPI
from blitz_api.types import Industry, JobLevel
# api_key defaults to the BLITZ_API_KEY environment variable.
with BlitzAPI() as client:
# Health-check the key before a batch job.
info = client.account.key_info()
print(info.valid, info.records_remaining, info.max_requests_per_seconds)
# LinkedIn profile URL -> verified work email.
email = client.enrichment.email(
person_linkedin_url="https://www.linkedin.com/in/example-person",
)
if email.found:
print(email.email)
# Search people with typed, autocompleted filters.
people = client.search.people(
company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
people={"job_level": [JobLevel.VP]},
max_results=10,
)
for person in people.results:
print(person.full_name, person.headline)
```
## Authentication
Pass the key explicitly or via the `BLITZ_API_KEY` environment variable. It is sent in the `x-api-key` header on every request.
```python theme={null} theme={null}
client = BlitzAPI(api_key="sk_...") # explicit
client = BlitzAPI() # reads BLITZ_API_KEY
```
Never expose your API key in client-side code (browsers, mobile apps). Always call Blitz from your backend.
## Async
Use `AsyncBlitzAPI` for `async`/`await`. Every method mirrors the sync client.
```python theme={null} theme={null}
import asyncio
from blitz_api import AsyncBlitzAPI
async def main() -> None:
async with AsyncBlitzAPI() as client:
result = await client.enrichment.company(
company_linkedin_url="https://www.linkedin.com/company/openai",
)
print(result.company.name if result.company else None)
asyncio.run(main())
```
## Endpoints
All methods are grouped into seven namespaces. Enum-backed filter fields (e.g. `Industry`, `JobLevel`, `Continent`) accept either an enum member or a raw string.
### `client.account`
```python theme={null} theme={null}
info = client.account.key_info()
print(info.valid, info.records_remaining, info.max_requests_per_seconds)
print(info.allowed_apis)
```
### `client.search`
```python theme={null} theme={null}
# People across many companies (cursor-paginated — see Pagination below).
people = client.search.people(
company={
"industry": {"include": ["IT Services and IT Consulting"]},
"employee_range": ["51-200", "201-500"],
"hq": {"sales_region": ["EMEA"]},
},
people={
"job_level": ["VP", "Director"],
"job_function": ["Sales & Business Development"],
"min_connections": 200,
},
max_results=25,
)
for person in people.results:
print(person.full_name, person.headline, person.linkedin_url)
# Companies by ICP (cursor-paginated).
companies = client.search.companies(
company={
"keywords": {"include": ["SaaS"]},
"industry": {"include": ["Software Development"]},
"hq": {"country_code": ["FR", "DE"]},
"employee_range": ["51-200", "201-500"],
},
max_results=25,
)
for company in companies.results:
print(company.name, company.industry, company.employees_on_linkedin)
# All employees at one company (page-paginated).
employees = client.search.employee_finder(
company_linkedin_url="https://www.linkedin.com/company/openai",
job_level=["C-Team", "VP", "Director"],
job_function=["Sales & Business Development"],
sales_region=["NORAM"],
max_results=50,
)
print(f"Page {employees.page} of {employees.total_pages}")
for person in employees.results:
print(person.full_name, person.headline)
# Single best decision-maker via a priority cascade.
match = client.search.waterfall_icp(
company_linkedin_url="https://www.linkedin.com/company/openai",
cascade=[
{"include_title": ["CTO", "VP Engineering"], "location": ["WORLD"], "include_headline_search": False},
{"include_title": ["Engineering Director", "Engineering Manager"], "location": ["WORLD"], "include_headline_search": False},
],
max_results=5,
)
for item in match.results:
print(f"[Tier {item.icp} | Rank #{item.ranking}]", item.person.full_name)
```
### `client.jobs`
```python theme={null} theme={null}
# Live job postings across companies (cursor-paginated — see Pagination below).
jobs = client.jobs.search(
job={
"title": {"include": ["Head of Sales"]},
"seniority": {"include": ["5-10"]},
"employment_type": {"include": ["FULL_TIME"]},
"work_arrangement": {"include": ["Hybrid", "Remote OK"]},
"date_posted": {"last_days": 30},
},
company={
"industry": {"include": ["Software Development"]},
"size": {"include": ["51-200", "201-500"]},
},
max_results=25,
)
for job in jobs.results:
print(job.company_name, job.title, job.location.city if job.location else None)
# Postings at one company (cursor-paginated).
company_jobs = client.jobs.company(
company_linkedin_url="https://www.linkedin.com/company/openai",
job={"field": {"include": ["Software Engineering"]}},
max_results=25,
)
for job in company_jobs.results:
print(job.title, job.url)
```
### `client.company`
```python theme={null} theme={null}
# Companies hiring for a role (deduplicated), each with its matching-posting count.
tam = client.company.tam_by_jobs(
job={
"title": {"include": ["Account Executive"]},
"min_per_company": 3,
},
company={"industry": {"include": ["Software Development"]}},
max_results=50,
)
for match in tam.results:
print(match.company.name if match.company else None, match.matched_jobs)
```
### `client.enrichment`
```python theme={null} theme={null}
# LinkedIn profile URL -> verified work email.
email = client.enrichment.email(person_linkedin_url="https://www.linkedin.com/in/example-person")
if email.found:
print(email.email)
# LinkedIn profile URL -> direct phone (US only).
phone = client.enrichment.phone(person_linkedin_url="https://www.linkedin.com/in/example-person")
if phone.found:
print(phone.phone)
# Work email -> full person profile.
by_email = client.enrichment.email_to_person(email="jane.doe@acme.com")
if by_email.found:
print(by_email.person.full_name)
# Phone number -> full person profile (US only).
by_phone = client.enrichment.phone_to_person(phone="+14155551234")
if by_phone.found:
print(by_phone.person.full_name)
# Company LinkedIn URL -> full company profile.
company = client.enrichment.company(company_linkedin_url="https://www.linkedin.com/company/openai")
print(company.company.name, company.company.industry, company.company.employees_on_linkedin)
# Website domain -> Company LinkedIn URL.
to_li = client.enrichment.domain_to_linkedin(domain="openai.com")
if to_li.found:
print(to_li.company_linkedin_url)
# Company LinkedIn URL -> email domain.
to_domain = client.enrichment.linkedin_to_domain(company_linkedin_url="https://www.linkedin.com/company/openai")
if to_domain.found:
print(to_domain.email_domain)
# Company employees grouped by country.
by_country = client.enrichment.company_distribution_by_country(
company_linkedin_url="https://www.linkedin.com/company/openai",
)
for row in by_country.distribution:
print(row.country, row.count, row.percentage_ratio)
# Company employees grouped by department.
by_department = client.enrichment.company_distribution_by_department(
company_linkedin_url="https://www.linkedin.com/company/openai",
)
for row in by_department.distribution:
print(row.department, row.count, row.percentage_ratio)
```
### `client.utils`
```python theme={null} theme={null}
# Current server date/time.
now = client.utils.current_date()
```
### `client.changelog`
```python theme={null} theme={null}
# Public API changelog, newest first. No API key required, and not paginated.
entries = client.changelog.list(days=30, limit=10)
for entry in entries:
print(entry.date, entry.type, entry.title, entry.affected_endpoints)
```
## Pagination
The list methods (`search.people`, `search.companies`, `search.employee_finder`, `jobs.search`, `jobs.company`, `company.tam_by_jobs`) return an **auto-paginating page** — iterate it and the SDK fetches each subsequent page for you.
```python theme={null} theme={null}
# Stream every match across all pages — no cursor handling needed.
for person in client.search.people(people={"job_level": ["VP"]}):
print(person.full_name)
```
See **[Pagination](/sdks/pagination)** for `max_items`, manual paging, page metadata, and the per-result billing caveat.
## Usage & rate limit
Every metered `/v2` response carries a `fair_usage` block: what the call cost, what is left on the plan, your rate-limit headroom, and a request id to quote to support. Read it to meter a long run without extra `key_info()` calls.
```python theme={null} theme={null}
result = client.enrichment.email(person_linkedin_url="https://www.linkedin.com/in/example-person")
if result.fair_usage is not None:
print(result.fair_usage.records_used) # records this call consumed
print(result.fair_usage.records_remaining) # a number, or "unlimited"
print(result.fair_usage.next_reset_at) # None on an unlimited plan
print(result.fair_usage.request_id) # quote this to support
if result.fair_usage.rate_limit is not None: # omitted where the API doesn't send it
print(result.fair_usage.rate_limit.remaining_this_second)
# Pages carry the block from the request that fetched them.
for page in client.search.people(people={"job_level": ["VP"]}).iter_pages(max_pages=5):
print(page.fair_usage.records_used if page.fair_usage else None)
```
`InsufficientRecordsError` (`402`) carries the block too, so you can read `next_reset_at` without a second call. Two endpoints don't return it: the public `changelog.list()`, which is not metered, and `account.key_info()`, which reports the balance in its own top-level `records_remaining`, `next_reset_at`, and `max_requests_per_seconds` fields.
## Configuration
```python theme={null} theme={null}
client = BlitzAPI(
api_key=None, # falls back to BLITZ_API_KEY
base_url="https://api.blitz-api.ai",
timeout=30.0, # seconds, or an httpx.Timeout
max_retries=3, # retries on 429 / 5xx / network errors
rate_limit_rps=5.0, # client-side throttle, per endpoint; None to disable
)
```
A single client instance stays under your per-endpoint request-per-second limit and retries automatically on `429`; see **[Rate limits & retries](/sdks/rate-limits)**. `rate_limit_rps` defaults to `5`; set it to your key's `max_requests_per_seconds` to use your plan's full per-endpoint throughput. Each method also accepts a per-call `timeout`:
```python theme={null} theme={null}
client.search.people(people={"job_level": ["VP"]}, timeout=10.0)
```
## Error handling
```python theme={null} theme={null}
from blitz_api import (
BlitzError, AuthenticationError, InsufficientRecordsError,
NotFoundError, RateLimitError, APIStatusError, APIConnectionError,
APITimeoutError, APIResponseValidationError,
)
try:
client.enrichment.email(person_linkedin_url="...")
except InsufficientRecordsError as err:
... # 402: out of records; err.fair_usage.next_reset_at
except AuthenticationError:
... # 401 — bad key
except APIStatusError as err:
print(err.status_code, err.message, err.body)
except APIResponseValidationError:
... # 2xx whose body didn't match the model
except BlitzError:
... # base class for everything this SDK raises
```
`401` / `402` / `404` raise immediately; `429` and `5xx` are retried automatically; read timeouts surface as `APITimeoutError` (not retried). `InsufficientCreditsError` still exists as a deprecated alias of `InsufficientRecordsError`, so older `except` blocks keep working. See **[Rate limits & retries](/sdks/rate-limits)** for the full retry and timeout behavior.
A `400` or `422` also raises immediately, as `APIStatusError`. For a `422`, `err.body["errors"]` lists each invalid field as `{"field": ..., "message": ...}`; see **[Errors](/guide/reference/errors#validation-errors-422)**.
## Types & enums
Response models are Pydantic v2 objects with attribute access and IDE autocomplete. Enum helpers live in `blitz_api.types`:
```python theme={null} theme={null}
from blitz_api.types import Industry, JobLevel, Continent
client.search.people(
company={"industry": {"include": [Industry.SOFTWARE_DEVELOPMENT]}},
people={"job_level": [JobLevel.VP]},
)
```
Enum-backed fields accept an enum member **or** a raw string, so a value missing from the vendored taxonomy never blocks you. New fields the API adds are preserved on the parsed model rather than breaking deserialization.
## Next steps
The same API surface for Node and the browser-adjacent runtimes.
Accepted values for industry, job level, job function, and geography filters.
Full request/response schemas and an interactive try-it console.
End-to-end workflows: build an ICP list, enrich it, and sync to your CRM.
# Rate limits & retries
Source: https://docs.blitz-api.ai/sdks/rate-limits
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
Blitz enforces a **per-endpoint** request-per-second limit that depends on your plan. The limit applies independently to each endpoint, so calls to `/enrichment/email` and `/enrichment/phone` run at the same time without competing for the same budget. Both SDKs handle this for you: a client-side limiter keeps your outgoing requests under the cap, and any `429` that still slips through is retried automatically. In most cases you don't need to write any rate-limit handling yourself.
## Find your limit
Your per-endpoint limit is on `key_info()`. Read it rather than hard-coding a number, so your code stays correct when you change plan.
```python Python theme={null} theme={null}
info = client.account.key_info()
print(info.max_requests_per_seconds) # your per-endpoint req/s limit
```
```ts TypeScript theme={null} theme={null}
const info = await client.account.key_info();
console.log(info.max_requests_per_seconds); // your per-endpoint req/s limit
```
Every metered `/v2` response also reports live headroom in its `fair_usage` block, so you can watch the budget mid-run without a second call:
```python Python theme={null} theme={null}
result = client.enrichment.email(person_linkedin_url="...")
if result.fair_usage and result.fair_usage.rate_limit:
print(result.fair_usage.rate_limit.remaining_this_second) # calls left this second
```
```ts TypeScript theme={null} theme={null}
const result = await client.enrichment.email({ person_linkedin_url: "..." });
console.log(result.fair_usage?.rate_limit?.remaining_this_second); // calls left this second
```
See [Authentication](/guide/getting-started/authentication) for the full `key_info` response.
## Client-side rate limiting
Each client throttles its outgoing requests to `rate_limit_rps` (default `5`) **per endpoint**: every endpoint path gets its own limiter, mirroring the API's per-endpoint budget. In Python it's a **sliding window** (at most N requests to a given endpoint in any rolling second); in TypeScript it's a **token bucket** (admits at most N per second, per endpoint). A single client instance therefore stays under the API limit on every endpoint on its own, as long as `rate_limit_rps` doesn't exceed your plan's limit. Set it to `None` / `null` to disable.
```python Python theme={null} theme={null}
client = BlitzAPI(rate_limit_rps=5.0) # default; None to disable
```
```ts TypeScript theme={null} theme={null}
const client = new BlitzAPI({ rate_limit_rps: 5 }); // default; null to disable
```
**Reuse one client per process.** The limiter lives on the client instance, so a single shared `client` keeps every endpoint's calls under its limit. If your plan allows more than 5 req/s, the default leaves throughput on the table: set `rate_limit_rps` to `max_requests_per_seconds` from your key to use the full budget.
## Automatic retries
`429` (rate limited) and `5xx` (server errors) are retried automatically with exponential backoff — TypeScript adds jitter — up to `max_retries` (default `3`). `400` / `401` / `402` / `404` / `422` are **not** retried; they raise immediately. If the retries are exhausted, the error surfaces as `RateLimitError` (`429`) or `ServerError` / `APIStatusError` (`5xx`).
```python Python theme={null} theme={null}
from blitz_api import BlitzAPI, RateLimitError
client = BlitzAPI(max_retries=5) # default 3
try:
client.search.people(people={"job_level": ["VP"]})
except RateLimitError:
... # still 429 after retries — back off and try again later
```
```ts TypeScript theme={null} theme={null}
import { BlitzAPI, RateLimitError } from "blitz-api-js";
const client = new BlitzAPI({ max_retries: 5 }); // default 3
try {
await client.search.people({ people: { job_level: ["VP"] } });
} catch (err) {
if (err instanceof RateLimitError) {
// still 429 after retries — back off and try again later
}
}
```
## Timeouts are not retried
Each method takes a per-call `timeout` (Python keyword arg; TypeScript options object as the last argument). Unlike `429`/`5xx`, a **read timeout is not retried** — the server may already have processed (and billed) the request, so the SDK surfaces `APITimeoutError` immediately rather than risk a double charge. Raise the per-call timeout for genuinely slow endpoints instead of relying on retries.
```python Python theme={null} theme={null}
client.enrichment.email(person_linkedin_url="...", timeout=10.0)
```
```ts TypeScript theme={null} theme={null}
await client.enrichment.email({ person_linkedin_url: "..." }, { timeout: 10 });
```
## Running many workers
The limiter is **per client instance** (per process), and the API limit is **per endpoint**. If you fan the SDK out across multiple processes or workers that hit the **same endpoint**, their combined rate can exceed that endpoint's limit and you'll see `429`s — the retry path absorbs occasional ones, but for steady throughput divide `rate_limit_rps` across the workers sharing an endpoint (e.g. 5 workers all calling `/enrichment/email` on a 10 req/s key → `rate_limit_rps = 2` each). Workers calling **different** endpoints don't compete — each endpoint has its own budget.
## Next steps
Stream results across pages and cap spend with `max_items`.
The full exception hierarchy for `blitz-api-py`.
The full exception hierarchy for `blitz-api-js`.
Request/response schemas and a try-it console.
# TypeScript / JavaScript SDK
Source: https://docs.blitz-api.ai/sdks/typescript
> **Agents & LLMs**: a Markdown version of this page is available by appending `.md` to the URL, and the full documentation index is at [llms.txt](https://docs.blitz-api.ai/llms.txt).
`blitz-api-js` is the official, typed TypeScript SDK for the Blitz API. It is `fetch`-based, Zod-validated, ships both ESM and CommonJS builds with `.d.ts` / `.d.cts` types, and uses **snake\_case** request and response fields that match the [API reference](/api-reference/account/get-api-key-details) exactly.
`blitz-api-js` on the npm registry.
Source, changelog, and issues.
## Install
```bash theme={null} theme={null}
npm install blitz-api-js
# or: pnpm add blitz-api-js / yarn add blitz-api-js
```
Requires Node.js 20+ (or any runtime with a global `fetch`). Ships both ESM and CommonJS builds.
## Quickstart
```ts theme={null} theme={null}
import { BlitzAPI } from "blitz-api-js";
// api_key defaults to the BLITZ_API_KEY environment variable.
const client = new BlitzAPI();
// Health-check the key before a batch job.
const info = await client.account.key_info();
console.log(info.valid, info.records_remaining, info.max_requests_per_seconds);
// LinkedIn profile URL -> verified work email.
const email = await client.enrichment.email({
person_linkedin_url: "https://www.linkedin.com/in/example-person",
});
if (email.found) console.log(email.email);
// Search people — list methods are paginated; one page's items live on `.data`.
const page = await client.search.people({
company: { industry: { include: ["Software Development"] } },
people: { job_level: ["VP"] },
max_results: 10,
});
for (const person of page.data) {
console.log(person.full_name, person.headline);
}
```
CommonJS works too:
```js theme={null} theme={null}
const { BlitzAPI } = require("blitz-api-js");
```
## Authentication
Pass the key explicitly or via the `BLITZ_API_KEY` environment variable. It is sent in the `x-api-key` header on every request.
```ts theme={null} theme={null}
const explicit = new BlitzAPI({ api_key: "sk_..." }); // explicit
const fromEnv = new BlitzAPI(); // reads BLITZ_API_KEY
```
Never expose your API key in client-side code (browsers, mobile apps). Always call Blitz from your backend.
## Endpoints
All methods are grouped into seven namespaces. Each takes a single options object (snake\_case keys) and returns a typed, Zod-validated response. The six **list** methods (`search.people`, `search.companies`, `search.employee_finder`, `jobs.search`, `jobs.company`, `company.tam_by_jobs`) return a paginated `PagePromise` (see [Pagination](#pagination)); `waterfall_icp`, `changelog.list`, and the `enrichment` / `utils` / `account` methods return their response directly.
### `client.account`
```ts theme={null} theme={null}
const info = await client.account.key_info();
console.log(info.valid, info.records_remaining, info.max_requests_per_seconds);
console.log(info.allowed_apis);
```
### `client.search`
```ts theme={null} theme={null}
// People across many companies (cursor-paginated — see Pagination below).
const people = await client.search.people({
company: {
industry: { include: ["IT Services and IT Consulting"] },
employee_range: ["51-200", "201-500"],
hq: { sales_region: ["EMEA"] },
},
people: {
job_level: ["VP", "Director"],
job_function: ["Sales & Business Development"],
min_connections: 200,
},
max_results: 25,
});
for (const person of people.data) {
console.log(person.full_name, person.headline, person.linkedin_url);
}
// Companies by ICP (cursor-paginated).
const companies = await client.search.companies({
company: {
keywords: { include: ["SaaS"] },
industry: { include: ["Software Development"] },
hq: { country_code: ["FR", "DE"] },
employee_range: ["51-200", "201-500"],
},
max_results: 25,
});
for (const company of companies.data) {
console.log(company.name, company.industry, company.employees_on_linkedin);
}
// All employees at one company (page-paginated).
const employees = await client.search.employee_finder({
company_linkedin_url: "https://www.linkedin.com/company/openai",
job_level: ["C-Team", "VP", "Director"],
job_function: ["Sales & Business Development"],
sales_region: ["NORAM"],
max_results: 50,
});
console.log(`Page ${employees.response.page} of ${employees.response.total_pages}`);
for (const person of employees.data) {
console.log(person.full_name, person.headline);
}
// Single best decision-maker via a priority cascade (returned directly).
const match = await client.search.waterfall_icp({
company_linkedin_url: "https://www.linkedin.com/company/openai",
cascade: [
{ include_title: ["CTO", "VP Engineering"], location: ["WORLD"], include_headline_search: false },
{ include_title: ["Engineering Director", "Engineering Manager"], location: ["WORLD"], include_headline_search: false },
],
max_results: 5,
});
for (const item of match.results) {
console.log(`[Tier ${item.icp} | Rank #${item.ranking}]`, item.person.full_name);
}
```
### `client.jobs`
```ts theme={null} theme={null}
// Live job postings across companies (cursor-paginated — see Pagination below).
const jobs = await client.jobs.search({
job: {
title: { include: ["Head of Sales"] },
seniority: { include: ["5-10"] },
employment_type: { include: ["FULL_TIME"] },
work_arrangement: { include: ["Hybrid", "Remote OK"] },
date_posted: { last_days: 30 },
},
company: {
industry: { include: ["Software Development"] },
size: { include: ["51-200", "201-500"] },
},
max_results: 25,
});
for (const job of jobs.data) {
console.log(job.company_name, job.title, job.location?.city);
}
// Postings at one company (cursor-paginated).
const companyJobs = await client.jobs.company({
company_linkedin_url: "https://www.linkedin.com/company/openai",
job: { field: { include: ["Software Engineering"] } },
max_results: 25,
});
for (const job of companyJobs.data) {
console.log(job.title, job.url);
}
```
### `client.company`
```ts theme={null} theme={null}
// Companies hiring for a role (deduplicated), each with its matching-posting count.
for await (const match of client.company.tam_by_jobs({
job: { title: { include: ["Account Executive"] }, min_per_company: 3 },
company: { industry: { include: ["Software Development"] } },
max_results: 50,
max_items: 200,
})) {
console.log(match.company?.name, match.matched_jobs);
}
```
### `client.enrichment`
```ts theme={null} theme={null}
// LinkedIn profile URL -> verified work email.
const email = await client.enrichment.email({ person_linkedin_url: "https://www.linkedin.com/in/example-person" });
if (email.found) console.log(email.email);
// LinkedIn profile URL -> direct phone (US only).
const phone = await client.enrichment.phone({ person_linkedin_url: "https://www.linkedin.com/in/example-person" });
if (phone.found) console.log(phone.phone);
// Work email -> full person profile.
const byEmail = await client.enrichment.email_to_person({ email: "jane.doe@acme.com" });
if (byEmail.found) console.log(byEmail.person.full_name);
// Phone number -> full person profile (US only).
const byPhone = await client.enrichment.phone_to_person({ phone: "+14155551234" });
if (byPhone.found) console.log(byPhone.person.full_name);
// Company LinkedIn URL -> full company profile.
const company = await client.enrichment.company({ company_linkedin_url: "https://www.linkedin.com/company/openai" });
console.log(company.company.name, company.company.industry, company.company.employees_on_linkedin);
// Website domain -> Company LinkedIn URL.
const toLinkedin = await client.enrichment.domain_to_linkedin({ domain: "openai.com" });
if (toLinkedin.found) console.log(toLinkedin.company_linkedin_url);
// Company LinkedIn URL -> email domain.
const toDomain = await client.enrichment.linkedin_to_domain({ company_linkedin_url: "https://www.linkedin.com/company/openai" });
if (toDomain.found) console.log(toDomain.email_domain);
// Company employees grouped by country.
const byCountry = await client.enrichment.company_distribution_by_country({
company_linkedin_url: "https://www.linkedin.com/company/openai",
});
for (const row of byCountry.distribution) {
console.log(row.country, row.count, row.percentage_ratio);
}
// Company employees grouped by department.
const byDepartment = await client.enrichment.company_distribution_by_department({
company_linkedin_url: "https://www.linkedin.com/company/openai",
});
for (const row of byDepartment.distribution) {
console.log(row.department, row.count, row.percentage_ratio);
}
```
### `client.utils`
```ts theme={null} theme={null}
// Current server date/time.
const now = await client.utils.current_date();
```
### `client.changelog`
```ts theme={null} theme={null}
// Public API changelog, newest first. No API key required, and not paginated.
const entries = await client.changelog.list({ days: 30, limit: 10 });
for (const entry of entries) console.log(entry.date, entry.type, entry.title);
```
## Pagination
The list methods (`search.people`, `search.companies`, `search.employee_finder`, `jobs.search`, `jobs.company`, `company.tam_by_jobs`) return a `PagePromise` — `await` it for the first page, or `for await` to stream every item across all pages (each fetched on demand).
```ts theme={null} theme={null}
// Stream every match across all pages — no cursor handling needed.
for await (const person of client.search.people({ people: { job_level: ["VP"] } })) {
console.log(person.full_name);
}
```
See **[Pagination](/sdks/pagination)** for `max_items`, `.collect()`, manual paging, page metadata, and the per-result billing caveat.
## Usage & rate limit
Every metered `/v2` response carries a `fair_usage` block reporting what the request cost and what is left, so you can meter a batch job without a second `key_info()` call.
```ts theme={null} theme={null}
const email = await client.enrichment.email({ person_linkedin_url: "https://www.linkedin.com/in/example-person" });
const usage = email.fair_usage;
console.log(usage?.records_used); // records this request consumed
console.log(usage?.records_remaining); // a number, or "unlimited"
console.log(usage?.next_reset_at); // null on an unlimited plan
console.log(usage?.rate_limit?.remaining_this_second); // calls left this second
console.log(usage?.request_id); // quote this id to support
// On a paginated method the block belongs to each page's raw body.
const page = await client.search.people({ people: { job_level: ["VP"] }, max_results: 50 });
console.log(page.response.fair_usage?.records_used);
```
Two endpoints don't return the block: the public `changelog.list()`, which is not metered, and `account.key_info()`, which reports the balance in its own top-level `records_remaining`, `next_reset_at`, and `max_requests_per_seconds` fields. Every field is optional, so a response predating the block still parses.
## Configuration
```ts theme={null} theme={null}
const client = new BlitzAPI({
api_key: undefined, // falls back to BLITZ_API_KEY
base_url: "https://api.blitz-api.ai",
timeout: 30, // default per-request timeout, seconds (via AbortSignal.timeout)
max_retries: 3, // retries on 429 / 5xx / pre-response network errors
rate_limit_rps: 5, // client-side token bucket, per endpoint; null to disable
fetch: undefined, // custom fetch implementation (tests / runtimes)
});
// Override the timeout for a single call — pass an options object as the last argument:
await client.enrichment.email({ person_linkedin_url: "..." }, { timeout: 5 });
```
A single client instance stays under your per-endpoint request-per-second limit and retries automatically on `429`; see **[Rate limits & retries](/sdks/rate-limits)**. `rate_limit_rps` defaults to `5`; set it to your key's `max_requests_per_seconds` to use your plan's full per-endpoint throughput.
## Error handling
```ts theme={null} theme={null}
import {
APIConnectionError,
APIResponseValidationError,
APIStatusError,
APITimeoutError,
AuthenticationError,
BlitzError,
FairUsageLimitError,
NotFoundError,
RateLimitError,
ServerError,
} from "blitz-api-js";
try {
await client.enrichment.email({ person_linkedin_url: "..." });
} catch (err) {
if (err instanceof FairUsageLimitError) {
// 402: Fair Use record limit reached; err.fair_usage?.next_reset_at
} else if (err instanceof AuthenticationError) {
// 401 — bad key
} else if (err instanceof APIResponseValidationError) {
// 2xx, but the body wasn't valid JSON or didn't match the schema
} else if (err instanceof APIStatusError) {
console.log(err.status_code, err.message, err.body, err.request_id);
} else if (err instanceof BlitzError) {
// base class for everything this SDK raises
}
}
```
`401` / `402` / `404` throw immediately; `429` and `5xx` are retried automatically; timeouts surface as `APITimeoutError` (not retried). `InsufficientCreditsError` is still exported as a deprecated alias of `FairUsageLimitError` (the same class, not a subclass), so existing `instanceof` checks keep working. See **[Rate limits & retries](/sdks/rate-limits)** for the full retry and timeout behavior.
A `400` or `422` also throws immediately, as `APIStatusError`. For a `422`, `err.body.errors` lists each invalid field as `{ field, message }`; see **[Errors](/guide/reference/errors#validation-errors-422)**. The API rejects any field it does not define, so an extra key in a params object returns a `422` even when TypeScript does not flag it.
## Types & enums
Response objects keep their snake\_case wire keys and **preserve unknown fields** — if the API adds a property before this SDK models it, the value is still present (typed as `unknown`); known fields stay precisely typed.
```ts theme={null} theme={null}
import { INDUSTRY } from "blitz-api-js"; // the full value array (534 industries)
import type { CompanyFilter, Industry } from "blitz-api-js";
```
Enum-backed filter fields (e.g. `industry`, `job_level`, `continent`) accept a known value — autocompleted from a union like `Industry` — or any raw string, so a value missing from the vendored taxonomy never blocks you.
## Next steps
The same API surface with sync + async clients.
Accepted values for industry, job level, job function, and geography filters.
Full request/response schemas and an interactive try-it console.
End-to-end workflows: build an ICP list, enrich it, and sync to your CRM.