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.
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 exactly.
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.remaining_credits, 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);}
All methods are grouped into four namespaces. Each takes a single options object (snake_case keys) and returns a typed, Zod-validated response. The three search list methods (people, companies, employee_finder) return a paginated PagePromise (see Pagination); waterfall_icp and the enrichment / utils / account methods return their response directly.
// Current server date/time.const now = await client.utils.current_date();// Company employees grouped by country.const distribution = await client.utils.company_employment_distribution({ company_linkedin_url: "https://www.linkedin.com/company/openai",});
The search methods (people, companies, employee_finder) return a PagePromise — await it for the first page, or for await to stream every item across all pages (each fetched on demand).
// 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 for max_items, .collect(), manual paging, page metadata, and the per-result billing caveat.
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; 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 key’s request-per-second limit (rate_limit_rps, default 5) and retries automatically on 429 — see Rate limits & retries.
import { APIConnectionError, APIResponseValidationError, APIStatusError, APITimeoutError, AuthenticationError, BlitzError, InsufficientCreditsError, NotFoundError, RateLimitError, ServerError,} from "blitz-api-js";try { await client.enrichment.email({ person_linkedin_url: "..." });} catch (err) { if (err instanceof InsufficientCreditsError) { // 402 — out of credits } 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). See Rate limits & retries for the full retry and timeout behavior.
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.
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.