This is the full developer documentation for LeadSonar
# Cold email in 5 minutes
> The four parts of every cold email setup, what each one does, and where LeadSonar fits.
Cold email is a short, personal email to someone who doesn’t know you yet, sent because you can genuinely help their business. Done well, it’s one of the cheapest ways to book sales calls. Done badly, your emails land in spam and the domains you send from get burned.
Two things decide which of those happens:
1. **Reaching the right people.** No amount of setup fixes a list of people who will never buy.
2. **Landing in the inbox.** That depends on what you send from, how much you send, and how clean your list is.
## The four parts
[Section titled “The four parts”](#the-four-parts)
Every cold email setup has the same four parts, whoever you buy them from. A *stack* is just the set of tools you use together.
[Part 1 Infrastructure  Maildeck Domains and inboxes you send from ](/before-you-send/infrastructure-with-maildeck/)[Part 2 Sequencer  Instantly, PlusVibe… Sends emails and follow-ups ](/before-you-send/sequencer/)[Part 3That's us Leads  LeadSonar The right people and their emails ](/find-leads/lead-finder/)[Part 4 Verification  EmailShield Removes bad addresses first](/before-you-send/verify-with-emailshield/)
| Part | What it does | Who provides it |
| --------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| **1. Infrastructure** | The domains and inboxes your emails are sent from, set up and warmed up so they can send safely. | [Maildeck](/before-you-send/infrastructure-with-maildeck/), our sister product |
| **2. Sequencer** | Sends your emails and follow-ups on a schedule, spread across your inboxes. | A tool you sign up for yourself, such as Instantly or PlusVibe |
| **3. Leads** | Finds the right people and their work email addresses. | **LeadSonar — that’s us** |
| **4. Verification** | Checks every address before you send and removes the ones that would bounce. | [EmailShield](/before-you-send/verify-with-emailshield/), our sister product |
In one line: **LeadSonar finds the people, EmailShield cleans the list, your sequencer sends the emails, and Maildeck gives it all somewhere safe to send from.**
## Why you can’t skip parts
[Section titled “Why you can’t skip parts”](#why-you-cant-skip-parts)
* **Without good leads** (part 3), every other part works perfectly and nobody replies. Each inbox can only send a few dozen cold emails a day, so every slot spent on the wrong person is wasted.
* **Without verification** (part 4), bad addresses bounce. Email providers watch your bounce rate; too many bounces and your emails start going to spam.
* **Without separate infrastructure** (part 1), you’d be sending from your company’s main domain. If that domain’s reputation drops, your normal business email suffers too.
Words you'll see a lot
A **lead** is one person you might email. **ICP** (ideal customer profile) is a short description of the companies and people you sell to. A **bounce** is an email that comes back undelivered. The [Glossary](/help/glossary/) has the rest.
## What to read next
[Section titled “What to read next”](#what-to-read-next)
* [Your first 10 minutes](/getting-started/quickstart/) — find and download your first leads.
* [Why fresh leads matter](/find-leads/why-fresh-leads/) — the reason old lists hurt you.
* Maildeck’s own guide covers infrastructure in depth: [docs.maildeck.co](https://docs.maildeck.co/getting-started/cold-email-basics/).
# Credits and plans
> What one credit buys, what's free, and how to choose a plan.
LeadSonar runs on **credits**. Looking is free; you spend credits when you get something you keep.
## What costs credits
[Section titled “What costs credits”](#what-costs-credits)
| Action | Cost |
| ------------------------------------------------------------------------- | -------------------------------------- |
| Searching, counting and browsing leads | **Free** |
| Revealing a person’s contact details | **1 credit** per newly revealed person |
| Exporting leads | **1 credit** per lead delivered |
| AI enrichment (ICP grade, company type, what they sell, who they sell to) | **1 credit** per lead |
| AI personalization (opener, subject line, cold email) | **1 credit** per lead |
| EmailShield verification | **3 credits** per lead |
| AI ICP score via the API | **1 credit** per contact |
You never pay twice for the same person. Someone you’ve already revealed costs nothing to reveal again, and exports only include people you haven’t revealed before — so a second export with the same filters brings new people, not repeats. [Why that matters →](/find-leads/why-fresh-leads/)
AI enrichment only charges for a lead when it actually produced something. If a company’s website couldn’t be read and a field would be a guess, it’s left blank and not billed.
## Free credits
[Section titled “Free credits”](#free-credits)
* **300 credits** when you create your account.
* **10,000 credits** with the 7-day Starter trial (one trial per account).
## Plans
[Section titled “Plans”](#plans)
Credits refill every month on your plan’s billing date.
| Plan | Price | Credits per month |
| ----------- | ------------ | ----------------- |
| **Starter** | $29 / month | 50,000 |
| **Growth** | $79 / month | 250,000 |
| **Pro** | $199 / month | 800,000 |
| **Scale** | $499 / month | 3,000,000 |
How many leads do you need?
A sequence usually sends each person about three emails (the first one plus two follow-ups). A rough rule: **people needed per month ≈ emails you plan to send per month ÷ 3.** If your inboxes send 15,000 cold emails a month, you need about 5,000 new people a month. Maildeck’s [plan guide](https://docs.maildeck.co/plans/choosing-a-plan/) works this out backwards from the number of calls you want.
## Changing or cancelling
[Section titled “Changing or cancelling”](#changing-or-cancelling)
Manage your plan from **Settings → Plans & Billing** in the app. Payments are processed by Commas, our payment provider.
# Your first 10 minutes
> Sign up, describe who you want to reach, and download your first leads.
By the end of this page you’ll have a CSV of real people, with their work emails, ready for your sequencer.
1. **Create your account** at [app.leadsonar.io](https://app.leadsonar.io). You can sign up with email or Google. Every new account starts with **300 free credits** — enough to reveal 300 people.
2. **Open the Lead Finder.** This is where you describe who you want to reach. Searching and counting are free; you only spend credits when you reveal someone’s contact details.
3. **Describe your audience with a few filters.** Start broad and narrow down. A good first search is three filters:
* **Job title**, for example `Head of Sales`
* **Company size**, for example `51-200`
* **Industry**, for example `Software Development`
The count at the top updates as you go. [Every filter, explained →](/find-leads/lead-finder/)
4. **Check a few rows before you spend anything.** Results show names, titles and companies with the contact details masked. If the people look wrong, adjust the filters now — it’s free.
5. **Reveal.** Select the people you want and reveal them. Each newly revealed person costs **1 credit** and is saved to **My Leads** for good. Someone you’ve already revealed is never charged again.
6. **Download.** From My Leads, download your leads as a CSV. Import that file into your sequencer — [here’s how](/before-you-send/sequencer/).
Before you send: verify
Run your list through [EmailShield verification](/before-you-send/verify-with-emailshield/) before your first campaign. One bad batch of bounces can push a new domain into spam.
## Want more than 300?
[Section titled “Want more than 300?”](#want-more-than-300)
Start the **7-day free trial** from inside the app: it gives you **10,000 credits** on the Starter plan. You add a card at checkout and aren’t charged during the trial; cancel any time before it ends. [Plans and pricing →](/getting-started/credits-and-plans/)
## Need a hand?
[Section titled “Need a hand?”](#need-a-hand)
We’re in beta, and every customer gets 1-to-1 support. [Here’s how to reach us →](/help/getting-help/)
# LeadSonar for AI agents
> Give your AI agent a B2B lead database it can search for free, and the guardrails to spend credits only when it should.
**Your agent can already write the email. LeadSonar tells it who to send it to.**
Point any agent that can call an HTTP API at LeadSonar and it can size a market, shortlist the right people, check how well each one fits, and hand back a verified list for your sequencer, with the spending under your control.
Explore for free
Counting and browsing cost nothing. An agent can try twenty filter combinations to find the right audience before spending a single credit.
Never pays twice
Revealing someone you already own costs 0 credits, and exports skip people you already have. An agent re-running a task won’t double-charge you.
Fit, not just contacts
`icp-score` grades any contact A–D against a one-line description of your customer, from the company’s own website, in about a second.
Machine-readable end to end
One API key, JSON in and out, an OpenAPI spec for tool generation, and these docs as plain text at `/llms.txt`.
## Hand this to your agent
[Section titled “Hand this to your agent”](#hand-this-to-your-agent)
The fastest start: copy this prompt, paste your API key where it says, and give it to any agent that can make HTTP requests: Claude, ChatGPT, Cursor, or your own.
Prompt for your agent
```text
You can use LeadSonar for me. LeadSonar is a B2B lead database: it finds people
at companies (mostly in the US) and their work email addresses.
How to use it
- Read the docs first: https://docs.leadsonar.io/llms-full.txt
- API spec (generate tools from it): https://docs.leadsonar.io/openapi.json
- Base URL: https://app.leadsonar.io — endpoints are under /api/v1/
- Send my key in the X-API-Key header:
What costs money
- Free: counting (POST /api/v1/leads/search) and browsing masked results
(POST /api/v1/leads/browse), plus GET /api/v1/credits.
- 1 credit per NEW person revealed (POST /api/v1/leads/reveal) or exported
(POST /api/v1/leads/exports). People I already have are never charged again.
Rules
- Always count first and tell me the estimated_total before revealing or exporting.
- Ask me before anything that costs more than 100 credits.
- When filtering by job title, always send "exactMatch": true.
- If a count comes back 0, read the "filters" field in the response: an unknown
value matches nothing instead of raising an error.
- The data is US-focused, and revenue bands come from headcount — say so if it matters.
```
## What an agent can do with it
[Section titled “What an agent can do with it”](#what-an-agent-can-do-with-it)
| Task | Calls | Cost |
| ------------------------------------------------------------------ | --------------------- | --------------------------------------------------------- |
| “How many heads of sales at US SaaS companies with 50–200 people?” | `POST /leads/search` | Free |
| “Show me 25 of them.” | `POST /leads/browse` | Free |
| “Get contact details for these 10.” | `POST /leads/reveal` | 1 credit per new person |
| “Build me a list of 2,000 for next month’s campaign.” | `POST /leads/exports` | 1 credit per person delivered |
| “Is this lead a good fit for us?” | `POST /icp-score` | 1 credit |
| “What does this company actually do?” | `POST /scrape/jobs` | 1 credit per domain, refunded if the site returns no text |
## Set it up
[Section titled “Set it up”](#set-it-up)
1. **Create an API key** in the app under **Settings → API Keys**. Give the agent its own key, so its spending shows up separately and you can revoke it on its own.
2. **Give the agent the spec.** Most agent frameworks can generate tools straight from an OpenAPI file:
```plaintext
https://docs.leadsonar.io/openapi.json
```
Or point it at the docs as plain text: [`/llms.txt`](https://docs.leadsonar.io/llms.txt) (an index) or [`/llms-full.txt`](https://docs.leadsonar.io/llms-full.txt) (every page in one file).
3. **Or define a few tools by hand.** Four tools cover most work. Here they are in the tool format the Claude API uses; other frameworks take the same JSON Schema:
```json
[
{
"name": "count_leads",
"description": "Count people matching filters. Free. Always call this before revealing or exporting. Use estimated_total for planning.",
"input_schema": {
"type": "object",
"properties": {
"jobTitles": { "type": "array", "items": { "type": "string" }, "description": "e.g. [\"Head of Sales\", \"VP Sales\"]" },
"exactMatch": { "type": "boolean", "description": "Always true when jobTitles is set" },
"excludeTitles": { "type": "array", "items": { "type": "string" } },
"industry": { "type": "array", "items": { "type": "string" } },
"companySize": { "type": "array", "items": { "type": "string", "enum": ["1-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5001+"] } },
"country": { "type": "array", "items": { "type": "string" }, "description": "ISO codes. Data is US-focused." },
"includeKeywords": { "type": "array", "items": { "type": "string" }, "description": "Matched against the company description, not titles" }
}
}
},
{
"name": "browse_leads",
"description": "List matching people with contact details masked. Free. Same filters as count_leads plus page and limit (max 1000).",
"input_schema": { "type": "object", "properties": { "page": { "type": "integer" }, "limit": { "type": "integer" } }, "additionalProperties": true }
},
{
"name": "reveal_leads",
"description": "Unlock contact details. Costs 1 credit per person not already revealed. Ask the user before revealing more than they approved.",
"input_schema": { "type": "object", "properties": { "leadIds": { "type": "array", "items": { "type": "string" } } }, "required": ["leadIds"] }
},
{
"name": "score_icp_fit",
"description": "Grade one contact A-D against the user's ideal customer. 1 credit.",
"input_schema": {
"type": "object",
"properties": {
"first_name": { "type": "string" }, "last_name": { "type": "string" },
"title": { "type": "string" }, "company": { "type": "string" }, "domain": { "type": "string" },
"target_icp": { "type": "string", "description": "1-2 sentences, max 500 characters" }
},
"required": ["target_icp"]
}
}
]
```
Map them to `POST /api/v1/leads/search`, `/leads/browse`, `/leads/reveal` and `/icp-score`, sending the key in the `X-API-Key` header.
4. **Give it the house rules** (next section) in its system prompt.
## Guardrails to put in the system prompt
[Section titled “Guardrails to put in the system prompt”](#guardrails-to-put-in-the-system-prompt)
Agents are good at spending money quickly. These rules keep them honest; copy them as-is:
```text
You have access to the LeadSonar lead database.
- Searching and browsing are free. Revealing costs 1 credit per new person; exports cost 1 credit per person delivered.
- Always count first (count_leads). Report the estimated_total to the user before revealing or exporting.
- Never reveal or export more people than the user approved. If a request would cost more than 100 credits, ask first.
- When you filter by job title, always set exactMatch: true.
- If a count is 0, check the "filters" field in the response — an unknown filter value matches nothing rather than raising an error.
- The data is US-focused. Say so if the user asks for another country and the count is small.
- Revenue bands are derived from company headcount; don't treat them as reported revenue.
```
Spending limits are yours to set
An API key spends from the account’s credit balance; there’s no per-key spending cap yet. Keep the agent’s account on a plan whose monthly credits you’re comfortable with, and check **Settings → Usage History** for what it spent.
## Read the docs as an agent
[Section titled “Read the docs as an agent”](#read-the-docs-as-an-agent)
These docs are published for machines as well as people:
* [`/llms.txt`](https://docs.leadsonar.io/llms.txt): a short index of every page.
* [`/llms-full.txt`](https://docs.leadsonar.io/llms-full.txt): every page as plain text in one file, ready to paste into a context window.
* [`/openapi.json`](https://docs.leadsonar.io/openapi.json): the API spec, checked against the live API.
* [`/sitemap-index.xml`](https://docs.leadsonar.io/sitemap-index.xml): for crawlers.
# API overview
> Authenticate, understand credits, and find the right endpoint in the LeadSonar API.
The LeadSonar API gives you the same data and AI as the app, over HTTPS and JSON: count and browse leads for free, reveal or export the ones you want, score contacts against your ICP, and read company websites.
Checked against the live API
Every endpoint and field in this section was verified by calling the API on **6 October 2026**. The [reference](/api/reference/) is generated from the same OpenAPI spec, which you can also download: [`/api/openapi.json`](https://app.leadsonar.io/api/openapi.json).
## Base URL
[Section titled “Base URL”](#base-url)
```plaintext
https://app.leadsonar.io
```
All endpoints live under `/api/v1/`.
## Authentication
[Section titled “Authentication”](#authentication)
Create a key in the app under **Settings → API Keys**. Keys start with `ls_live_` and are shown **once** — store it somewhere safe. Send it in the `X-API-Key` header on every request:
```bash
curl https://app.leadsonar.io/api/v1/credits \
-H "X-API-Key: ls_live_your_key_here"
```
```json
{ "balance": 50278, "total_earned": 50300, "total_spent": 22 }
```
A missing key returns `401 Authentication required`; a wrong one returns `401 Invalid API key`. Requests spend the credits of the account that owns the key.
## What’s free and what costs credits
[Section titled “What’s free and what costs credits”](#whats-free-and-what-costs-credits)
| Free | Costs credits |
| ------------------------------------------- | -------------------------------------------------------------- |
| `POST /leads/search` — count matching leads | `POST /leads/reveal` — 1 credit per **new** lead |
| `POST /leads/browse` — masked results | `POST /leads/exports` — 1 credit per lead delivered |
| `GET /leads/filters` — valid filter values | `POST /icp-score` — 1 credit per contact |
| `GET /credits`, listing your jobs | `POST /scrape/jobs` — 1 credit per domain, refunded if no text |
| | `POST /enrich-csv` — per lead, by the bundles you choose |
You’re never charged twice for the same lead: revealing someone again returns `credits_charged: 0`, and exports and browse results skip people you’ve already revealed.
## The endpoints
[Section titled “The endpoints”](#the-endpoints)
| Group | What it’s for |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Leads** | `search` to count, `browse` to page through masked results, `reveal` to unlock specific leads, `exports` for bulk CSV (up to 50,000 per export). |
| **AI enrichment** | `icp-score` grades one contact against your ICP in about a second. `enrich-csv` runs AI enrichment over a whole CSV as a background job. |
| **Domain scrape** | `scrape/jobs` reads company websites and returns their text — useful for your own AI prompts. |
| **Account** | `credits` for your balance. |
[Quickstart ](/api/quickstart/)Count, browse, reveal and export in four calls.
[Limits and errors ](/api/limits-and-errors/)Rate limits, page sizes, and every error you can get.
[API reference ](/api/reference/)Every endpoint, parameter and field.
## Retired endpoints
[Section titled “Retired endpoints”](#retired-endpoints)
`POST /api/v1/enrich`, `/find-email` and `/find-phone` (waterfall lookups) have been retired. They return **`410 ENDPOINT_RETIRED`**. Use `/leads/browse` + `/leads/reveal` for contact data, or `/enrich-csv` for AI enrichment.
# API quickstart
> From zero to a CSV of leads in four API calls.
This walks the path most integrations take: **count → browse → reveal → export**. Steps 1 and 2 are free. Set your key once:
```bash
export LS_KEY="ls_live_your_key_here"
```
Note
Example values below are made up. Field names and response shapes are exactly what the API returned on 6 October 2026.
1. **Count — free.** Check how many people match before you spend anything.
```bash
curl https://app.leadsonar.io/api/v1/leads/search \
-H "X-API-Key: $LS_KEY" -H "Content-Type: application/json" \
-d '{
"jobTitles": ["Head of Sales"],
"exactMatch": true,
"industryNames": ["Software Development"],
"companySizes": ["51-200"],
"countryCodes": ["US"]
}'
```
```json
{
"firmographic_total": 179984,
"firmographic_is_exact": true,
"estimated_total": 382,
"basis": "sampled",
"note": "estimated_total is sampled: keyword/role/department filters are applied per row and cannot be counted upstream. Plan exports around estimated_total.",
"narrowed_by": null,
"keywords": null,
"filters": { "jobTitles": ["Head of Sales"], "exactMatch": true, "industryNames": ["Software Development"], "companySizes": ["51-200"], "countryCodes": ["US"], "matchAny": false }
}
```
`firmographic_total` counts the companies-side filters exactly. **`estimated_total` is the number to plan with** — it applies job titles too, from a sample. `filters` echoes what the server understood; check it whenever a count looks wrong.
2. **Browse — free.** Page through matching people with contact details masked.
```bash
curl https://app.leadsonar.io/api/v1/leads/browse \
-H "X-API-Key: $LS_KEY" -H "Content-Type: application/json" \
-d '{ "jobTitles": ["Head of Sales"], "exactMatch": true, "countryCodes": ["US"], "companySizes": ["51-200"], "limit": 25 }'
```
```json
{
"page": 1, "limit": 25, "returned": 25, "next_page": 2,
"leads": [
{
"id": "3f1c2a90-0000-4000-8000-000000000001",
"firstName": "Jordan", "jobTitle": "Head of Sales",
"companyName": "Example Software Inc.", "companySize": "101 to 250",
"industryName": "Software Development", "seniority": "Director",
"city": "Austin", "state": "TX", "countryCode": "US",
"email": "•••@•••.com", "phone": "+151****10"
}
]
}
```
Keep the `id` of each lead you want. People you’ve already revealed don’t appear here.
3. **Reveal — 1 credit per new lead.** Unlock the leads you picked (send their `id`s).
```bash
curl https://app.leadsonar.io/api/v1/leads/reveal \
-H "X-API-Key: $LS_KEY" -H "Content-Type: application/json" \
-d '{ "leadIds": ["3f1c2a90-0000-4000-8000-000000000001"] }'
```
```json
{ "revealed": [ { "id": "3f1c2a90-…", "email": "jordan@example-software.com", "…": "…" } ],
"credits_charged": 1, "new_reveals": 1, "already_revealed": 0 }
```
Revealing the same lead again returns `"credits_charged": 0, "already_revealed": 1`.
4. **Export — for bulk.** Instead of revealing page by page, export everyone matching your filters as a CSV (up to 50,000 per export).
```bash
curl https://app.leadsonar.io/api/v1/leads/exports \
-H "X-API-Key: $LS_KEY" -H "Content-Type: application/json" \
-d '{ "jobTitles": ["Head of Sales"], "exactMatch": true, "countryCodes": ["US"], "companySizes": ["51-200"], "limit": 500 }'
```
```json
{ "job_id": "4fad85cd-3e37-4797-ab77-07ed02d8f408", "status": "queued", "requested_limit": 500, "capped_to_max": null,
"poll": "/api/v1/leads/exports/4fad85cd-3e37-4797-ab77-07ed02d8f408",
"download": "/api/v1/leads/exports/4fad85cd-3e37-4797-ab77-07ed02d8f408/csv" }
```
Poll until `status` is `completed`, then download:
```bash
curl https://app.leadsonar.io/api/v1/leads/exports/4fad85cd-3e37-4797-ab77-07ed02d8f408 -H "X-API-Key: $LS_KEY"
# {"id":"4fad85cd-…","status":"completed","progress":100,"deliveredRows":500,"creditsCharged":500,"downloadable":true,…}
curl -o leads.csv https://app.leadsonar.io/api/v1/leads/exports/4fad85cd-3e37-4797-ab77-07ed02d8f408/csv -H "X-API-Key: $LS_KEY"
```
The CSV columns: `First Name, Last Name, Email, Phone, Company, Domain, Job Title, Seniority, Department, Industry, Country, State, City, Company Size, LinkedIn`.
Two things that catch people out
* **Set `"exactMatch": true` with job titles.** Without it, titles match as substrings. The app always sends it; the API leaves it to you.
* **Starting an export answers in snake_case** (`job_id`, `requested_limit`); the status endpoint answers in camelCase (`id`, `deliveredRows`). Read the id from `job_id`.
## Finding valid filter values
[Section titled “Finding valid filter values”](#finding-valid-filter-values)
Unknown filter values don’t raise an error — they just match nothing. Ask the API for the real values:
```bash
curl "https://app.leadsonar.io/api/v1/leads/filters" -H "X-API-Key: $LS_KEY"
# {"filters":["industry","seniority","country","department","company_size","revenue","companyType"], ...}
curl "https://app.leadsonar.io/api/v1/leads/filters?field=seniority" -H "X-API-Key: $LS_KEY"
# {"field":"seniority","values":[{"value":"Staff","count":"46030856"},{"value":"Manager",...},{"value":"Cxo",...},{"value":"Director",...},{"value":"Vp",...}]}
```
`jobTitles`, `excludeTitles`, `includeKeywords` and `excludeKeywords` are free text and have no fixed list. For company size you can send either the app’s bands (`"51-200"`) or the raw buckets the filters endpoint lists (`"51 to 100"`, `"101 to 250"`).
# Limits and errors
> Rate limits, size limits, and the errors the LeadSonar API returns.
## Limits
[Section titled “Limits”](#limits)
| Limit | Value |
| ------------------------------ | --------------------------------------------------------------------------- |
| Request rate | about **10 requests per second** per IP address, with short bursts up to 20 |
| Leads per browse page | **1,000** |
| Leads per export | **50,000** (ask for more and `capped_to_max` tells you it was capped) |
| ICP description (`target_icp`) | 500 characters |
Over the request rate you get **HTTP 503** from the edge — wait a second and retry with backoff.
## Coverage you should know about
[Section titled “Coverage you should know about”](#coverage-you-should-know-about)
* **US-focused data.** 68.6 million people have a country, almost all in the US; every other country has under 30,000.
* **Revenue bands are derived from headcount**, not reported revenue — each revenue band matches a company-size band exactly.
* **Counts with job titles, keywords or departments are estimates** worked out from a sample of matching companies. The same request returns the same estimate, but the number of people an export actually delivers can differ from it.
## Errors
[Section titled “Errors”](#errors)
Errors come back as JSON with an `error` message, and often a machine-readable `code`:
```json
{ "error": "Unknown export", "code": "EXPORT_NOT_FOUND" }
```
| Status | When | What to do |
| ------ | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `400` | A required field is missing or malformed — for example `leadIds array is required`, or `target_icp is required`. | Fix the request body. The message says which field. |
| `401` | `Authentication required` (no key) or `Invalid API key`. | Send `X-API-Key: ls_live_…`. |
| `402` | `INSUFFICIENT_CREDITS` — not enough credits for a reveal, scrape or enrichment job. | Top up or upgrade in **Settings → Plans & Billing**. |
| `404` | Unknown id — e.g. `EXPORT_NOT_FOUND`. A malformed id returns `400 BAD_ID`. | Check the id came from `job_id`. |
| `410` | `ENDPOINT_RETIRED` — the old waterfall endpoints. | Use `/leads/browse` + `/leads/reveal`. |
| `502` | `LEADS_SOURCE_DOWN` / `FACET_SOURCE_DOWN` — the lead database didn’t answer in time. | Retry after a few seconds. |
| `503` | Rate limit. | Back off and retry. |
## When an export runs out of credits
[Section titled “When an export runs out of credits”](#when-an-export-runs-out-of-credits)
An export doesn’t refuse upfront. It delivers rows until your credits run out, then stops and **keeps what it delivered**: the job finishes with `status: "completed"`, `capped: true`, and `deliveredRows` lower than you asked for. You’re charged only for the rows in the file. If no row could be paid for at all, the job ends `failed`.
## A search that returns 0
[Section titled “A search that returns 0”](#a-search-that-returns-0)
The API doesn’t reject unknown filter values; it matches nothing. If a count is unexpectedly zero:
1. Look at `filters` in the `/leads/search` response — it shows how your request was read.
2. Check each value against `GET /api/v1/leads/filters?field=`.
3. Remove filters one at a time to find the one that empties the result.
# Send from Maildeck
> Why cold email needs its own domains and inboxes, and where to get them set up for you.

Maildeck
Cold email infrastructure, set up for you — our sister product · [maildeck.co](https://maildeck.co)
LeadSonar finds the people. To email them you need somewhere to send **from**: domains and inboxes built for cold email. That’s **infrastructure**, part 1 of every cold email setup.
[Part 1 Infrastructure  Maildeck Domains and inboxes you send from ](/before-you-send/infrastructure-with-maildeck/)[Part 2 Sequencer  Instantly, PlusVibe… Sends emails and follow-ups ](/before-you-send/sequencer/)[Part 3That's us Leads  LeadSonar The right people and their emails ](/find-leads/lead-finder/)[Part 4 Verification  EmailShield Removes bad addresses first](/before-you-send/verify-with-emailshield/)
## Why not just use your work email?
[Section titled “Why not just use your work email?”](#why-not-just-use-your-work-email)
1. **Each inbox can only send a little.** Email providers watch for accounts that suddenly send hundreds of emails to strangers. A safe cold inbox sends a few dozen emails a day. To reach thousands of people a month you need many inboxes.
2. **Your main domain is too valuable to risk.** If cold emails from `yourcompany.com` get marked as spam, your *normal* business email — invoices, replies to clients — starts landing in spam too. Cold email goes out from separate, similar-looking domains (like `getyourcompany.com`) so your main domain is never exposed.
3. **New inboxes need warming up.** A brand-new inbox that starts sending cold email looks suspicious. **Warm-up** is a few weeks of gentle, automatic sending that builds its reputation first.
4. **The technical records must be right.** SPF, DKIM and DMARC are DNS records that prove your emails really come from you. Get them wrong and providers send you to spam.
## What Maildeck does
[Section titled “What Maildeck does”](#what-maildeck-does)
Maildeck buys and sets up the domains, creates the inboxes on Google Workspace, Outlook or SMTP, configures SPF/DKIM/DMARC, warms them up, and connects them to your sequencer.
Learn more
Maildeck’s docs explain all of this in plain words: [docs.maildeck.co](https://docs.maildeck.co/) — start with [Cold email basics](https://docs.maildeck.co/getting-started/cold-email-basics/) and [Choose a plan](https://docs.maildeck.co/plans/choosing-a-plan/).
# Load into your sequencer
> How to get LeadSonar leads into Instantly, PlusVibe, Smartlead or any other sending tool.
A **sequencer** is the tool that sends your emails and follow-ups on a schedule, spread across your inboxes — Instantly, PlusVibe, Smartlead, EmailBison, Lemlist and others. You sign up for it yourself; [Maildeck](/before-you-send/infrastructure-with-maildeck/) connects your inboxes to it.
Two of the most common:

Instantly
Sales engagement and lead intelligence · [instantly.ai](https://instantly.ai)

PlusVibe
Inbox-first cold email outreach at scale · [plusvibe.ai](https://plusvibe.ai)
Today, leads move from LeadSonar to your sequencer as a **CSV file**. Every sequencer can import one.
1. **Verify first.** Run the list through [EmailShield](/before-you-send/verify-with-emailshield/) and remove anything that isn’t *valid*.
2. **Download the CSV** from **Lead Finder → My Leads**, or export a search. [How →](/find-leads/reveal-and-export/)
3. **Import it** into your sequencer as a new lead list or campaign.
4. **Map the columns.** Match *First Name*, *Last Name*, *Email* and *Company* to the sequencer’s fields. Map enrichment columns (like the opener or cold email) to **custom variables** so you can use them in your templates.
Direct integrations
One-click pushes to Instantly, Smartlead, HubSpot, Clay and others are listed under **Integrations** in the app and marked *coming soon*. Until they’re live, CSV is the way.
# Verify with EmailShield
> Why every list needs verifying before you send, and how LeadSonar's EmailShield integration does it.

EmailShield
Email verification and list cleaning — our sister product · [emailshield.co](https://emailshield.co)
**EmailShield is a list cleaner.** Before you send, it checks every address and flags the ones that don’t exist or would bounce. Think of it as spell-check for email addresses. LeadSonar has EmailShield built in: you can verify leads without leaving the app.
[Part 1 Infrastructure  Maildeck Domains and inboxes you send from ](/before-you-send/infrastructure-with-maildeck/)[Part 2 Sequencer  Instantly, PlusVibe… Sends emails and follow-ups ](/before-you-send/sequencer/)[Part 3That's us Leads  LeadSonar The right people and their emails ](/find-leads/lead-finder/)[Part 4 Verification  EmailShield Removes bad addresses first](/before-you-send/verify-with-emailshield/)
## Why verify before you send
[Section titled “Why verify before you send”](#why-verify-before-you-send)
When you email an address that doesn’t exist, the email **bounces** — it comes back undelivered.
Email providers like Google and Microsoft watch your bounce rate. Lots of bounces tells them you’re sending to a list nobody checked, which is what spammers do. Your sender reputation drops, more of your emails land in spam, and in bad cases your domain ends up on a **blacklist** that many mail servers refuse outright.
The domain is the expensive part to lose: it took weeks of warm-up before it could send. **Verifying a list costs far less than replacing a burned domain.**
Keep bounces under 5%
If a campaign’s bounce rate goes above about 5%, pause it and clean the list before sending more.
## Why a LeadSonar list still needs it
[Section titled “Why a LeadSonar list still needs it”](#why-a-leadsonar-list-still-needs-it)
Even a fresh list goes stale: people change jobs every month, and an address that was valid when you exported it can be gone by the time you send. [Why fresh leads matter →](/find-leads/why-fresh-leads/) Verify **the week you send**, not when you build the list.
## How to verify in LeadSonar
[Section titled “How to verify in LeadSonar”](#how-to-verify-in-leadsonar)
1. In **Lead Finder → My Leads**, select the leads.
2. Click **Enrich selected** and tick **EmailShield verification**.
3. Each lead gets an **email status**: *valid* (safe to send) or *invalid* (remove it).
Verification costs **3 credits per lead**.
## What EmailShield checks
[Section titled “What EmailShield checks”](#what-emailshield-checks)
EmailShield asks the recipient’s mail server whether the mailbox exists — **without sending an email**. It also detects:
* **Catch-all domains** — servers that accept every address, so a mailbox can’t be confirmed either way. Send to these carefully.
* **Disposable addresses** — throwaway inboxes.
* **Role addresses** — shared inboxes like `info@` or `sales@`, which rarely reply to cold email.
For large lists from other sources, bulk uploads, blacklist monitoring and its own API, use EmailShield directly at [emailshield.co](https://emailshield.co).
# AI enrichment and copy
> What AI enrichment adds to each lead, what it costs, and how to write an ICP that gets good results.
**Enrichment** means filling in more about a lead so you can decide who to email first and what to say. LeadSonar reads each company’s own website and fills in fields from what it finds there.
## What you can add
[Section titled “What you can add”](#what-you-can-add)
Enrichment is sold in bundles. You’re charged **once per lead per bundle**, and only when that bundle actually filled something in.
### Enrichment — 1 credit per lead
[Section titled “Enrichment — 1 credit per lead”](#enrichment--1-credit-per-lead)
| Field | What it tells you |
| -------------------- | ------------------------------------------------------------------------------------------ |
| **ICP grade** | How well the lead fits the customer you described: **A** (strong fit) to **D** (poor fit). |
| **Who they sell to** | The company’s own customers, in a few words. |
| **Company type** | What kind of company it is, in plain words (“payroll software provider”). |
| **What they sell** | Their main product or service. |
### AI personalization — 1 credit per lead
[Section titled “AI personalization — 1 credit per lead”](#ai-personalization--1-credit-per-lead)
| Field | What it is |
| ---------------- | ------------------------------------------------------------- |
| **Opener** | A first line that refers to something real about the company. |
| **Subject line** | A short subject line written for cold email. |
| **Cold email** | One complete email built from your offer. |
### EmailShield verification — 3 credits per lead
[Section titled “EmailShield verification — 3 credits per lead”](#emailshield-verification--3-credits-per-lead)
Checks whether the address can receive email. [What verification does →](/before-you-send/verify-with-emailshield/)
## How to run it
[Section titled “How to run it”](#how-to-run-it)
1. In **Lead Finder → My Leads**, select the people you want to enrich (up to **500** per run).
2. Click **Enrich selected** and choose the bundles you want.
3. Describe **who you sell to** (your ICP) in one or two sentences — up to 500 characters.
4. If you chose AI personalization, describe **your offer** — up to 2,000 characters. Paste what you’d tell a new salesperson: what you sell, who it’s for, and the result it gets.
5. Run it. Results appear in My Leads as they finish.
Only cells a lead is still missing are filled and billed, so re-running enrichment on a list doesn’t charge you again for fields you already have.
## Why some cells stay empty
[Section titled “Why some cells stay empty”](#why-some-cells-stay-empty)
Enrichment is **grounded**: every field comes from the company’s real website. If the site can’t be read (it’s down, blocks crawlers, or is nearly empty), LeadSonar leaves the field blank rather than invent something — and you aren’t charged for it. A blank is honest; a confident guess in a cold email is how you end up describing someone’s company wrong to their face.
## Writing an ICP that works
[Section titled “Writing an ICP that works”](#writing-an-icp-that-works)
Good vs vague
**Vague:** “B2B companies that need marketing.”
**Good:** “US software companies with 20–200 employees that sell to other businesses and are hiring their first sales team.”
* **Name the kind of company**, not just the industry.
* **Give a size range.**
* **Say what makes them a fit right now** — a trigger like hiring, launching, or a recent change.
* Keep it to one or two sentences. The grade compares each company against exactly what you wrote.
# Using the Lead Finder
> Every filter in the Lead Finder, what it matches, and the mistakes that empty a search.
The **Lead Finder** (in the left sidebar) is where you describe who you want to reach. You combine filters; the count updates as you go, and the results show people with their contact details masked until you reveal them.
**Searching is free.** Change filters as often as you like.
## How filters combine
[Section titled “How filters combine”](#how-filters-combine)
* **Different filters narrow each other.** Job title *and* company size *and* industry: a person must match all of them.
* **Several values inside one filter widen it.** Industry `Software Development` *or* `IT Services and IT Consulting`.
* **Job title and Department count as one group.** A person matches if they fit *either* — so `Job title: CFO` plus `Department: Finance` finds CFOs and anyone in finance.
## The filters
[Section titled “The filters”](#the-filters)
### Job titles
[Section titled “Job titles”](#job-titles)
Free text. Type the titles you want, like `Head of Sales` or `VP Marketing`. Matching is **whole-word**: `CFO` matches “CFO” and “Group CFO”, not “CFOs Office Assistant”. LeadSonar also expands common roles to their usual variants, so `CFO` also finds “Chief Financial Officer”.
### Exclude job titles
[Section titled “Exclude job titles”](#exclude-job-titles)
Removes anyone whose title contains these words. Use it to clean up a broad search: `assistant`, `intern`, `associate`.
### Seniority
[Section titled “Seniority”](#seniority)
Five levels: **C-level, VP, Director, Manager, Staff**. The Owner, Founder and Partner options are matched on the job title itself, so they find real owners and founders rather than every C-level.
### Department
[Section titled “Department”](#department)
19 departments, from Operations and Executive to Sales, Marketing, Finance and Engineering.
### Industry
[Section titled “Industry”](#industry)
Pick a category, then narrow to specific industries inside it. Industries describe the **company**, not the person.
### Company size
[Section titled “Company size”](#company-size)
Seven bands: **1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001+** employees.
### Revenue
[Section titled “Revenue”](#revenue)
Revenue bands from *Under 1 Million* to *1 Billion and Over*.
Revenue is estimated from headcount
The revenue bands are derived from company size, not from reported revenue. Each revenue band lines up exactly with a size band, so filtering by both adds no extra precision. Use whichever reads more naturally for your ICP.
### Company type
[Section titled “Company type”](#company-type)
**Private, Education, Government, Nonprofit.** Most B2B searches want *Private*, which excludes schools, public bodies and charities in one click.
### Country
[Section titled “Country”](#country)
The data is US-focused
About 68.6 million people in the database have a country, and almost all of them are in the **United States**. Every other country has under 30,000 people (Canada about 14,000, the UK about 13,000). If your market is outside the US, check the count before you plan a campaign around it.
### Keywords (include / exclude)
[Section titled “Keywords (include / exclude)”](#keywords-include--exclude)
Keywords match against the **company’s description** — what the company says it does — never the person’s title. Use them for niches no industry captures: `payroll`, `cold storage`, `HIPAA`. Matching is whole-word, so `api` won’t match “capital”.
Exclude keywords remove companies whose description mentions a word: `staffing`, `recruitment`, `nonprofit`.
### Company name
[Section titled “Company name”](#company-name)
Find people at one specific company.
## Presets
[Section titled “Presets”](#presets)
Save a set of filters as a **preset** to reuse it later. Presets are saved to your account, so they follow you to any browser or device you log in from.
## Reading the count
[Section titled “Reading the count”](#reading-the-count)
* With only company filters (size, industry, country…), the count is **exact**.
* As soon as you add job titles, keywords or departments, the count becomes an **estimate** (shown as `~`), worked out from a sample. It’s a good guide for planning, but the number of people an export delivers can differ from it.
## When a search returns nothing
[Section titled “When a search returns nothing”](#when-a-search-returns-nothing)
1. **Too many narrow filters together.** Remove one at a time and watch which one empties the result.
2. **A non-US country.** See the note above.
3. **A keyword that’s really a job title.** Keywords search company descriptions; put roles in *Job titles*.
The count panel highlights which filter removed the most people — start there.
# Reveal, My Leads and export
> How to unlock contact details, where they're saved, and how to get them out as a CSV.
## Reveal
[Section titled “Reveal”](#reveal)
Search results show people with their contact details masked. **Revealing** someone unlocks their email and phone number.
* Each newly revealed person costs **1 credit**.
* Revealing someone you’ve already revealed is **free** — you’re never charged twice.
* You can reveal one person, a page, or a whole selection at once.
## My Leads
[Section titled “My Leads”](#my-leads)
Everyone you reveal is saved to **My Leads** — the tab inside the Lead Finder. It’s your permanent list: it doesn’t expire, and it’s where enrichment results appear. From My Leads you can select people to [enrich](/enrich/ai-enrichment/) or download.
## Export
[Section titled “Export”](#export)
There are two ways to get leads out as a CSV:
**From My Leads** — download the people you’ve already revealed. Free; you paid when you revealed them.
**From a search (export)** — export everyone matching your filters in one go, without revealing them one by one first. Each person delivered costs **1 credit**, and exports only include people you haven’t revealed before. Large exports run in the background: you can leave the page and come back, and the file is waiting for you.
| | Limit |
| ---------------------------------------- | --------------------------------- |
| Export from the app | up to 1,000,000 people per export |
| Export through the [API](/api/overview/) | up to 50,000 people per export |
A search export’s CSV has these columns: **First Name, Last Name, Email, Phone, Company, Domain, Job Title, Seniority, Department, Industry, Country, State, City, Company Size, LinkedIn**.
Before you send
A fresh export is not a verified list. Run it through [EmailShield](/before-you-send/verify-with-emailshield/) before the campaign goes out.
# Why fresh leads matter
> Contact data goes stale every month. What that does to your campaigns, and how LeadSonar keeps your lists fresh.
A lead list is a snapshot. The moment it’s made, it starts going out of date: people change jobs, get promoted, leave companies, and companies rename their email domains. Every one of those changes turns a good address into a bounce, or sends your email to someone who no longer does the job you’re writing to.
## What a stale list costs you
[Section titled “What a stale list costs you”](#what-a-stale-list-costs-you)
**Bounces hurt the domains you send from.** An email to an address that no longer exists comes straight back. Email providers like Google and Microsoft watch how often that happens. A high bounce rate looks like a spammer working through a bought list, and they respond by sending more of your emails to spam. Your [sending domains](/before-you-send/infrastructure-with-maildeck/) took weeks to warm up; a bad list can undo that in days.
**You waste sending capacity.** Each inbox can only send a few dozen cold emails a day safely. Every email to a dead address or the wrong person is a slot you could have used on someone who might reply.
**The right title at the wrong company is still the wrong person.** If your list says someone is Head of Sales at a company they left eight months ago, your personalised opener lands with a stranger.
**Re-sending to the same people burns your offer.** If the same people get your sequence twice, the second time it reads as spam to them — and they’re the ones who click “report”.
## How LeadSonar keeps it fresh
[Section titled “How LeadSonar keeps it fresh”](#how-leadsonar-keeps-it-fresh)
* **You never get the same person twice.** People you’ve already revealed are left out of new searches and exports, so a second export with the same filters brings *new* people, not repeats. (We tested this: three exports of the same filter, zero overlap.)
* **You never pay twice.** A person you’ve already revealed is never charged again.
* **Verify before you send.** Run new lists through [EmailShield](/before-you-send/verify-with-emailshield/) right before a campaign, not weeks earlier. Verification is a snapshot too — the closer to sending, the better.
A good rhythm
Pull a **new batch of leads each month** for the volume you’ll send that month, verify it the week you send, and don’t recycle people who already went through a sequence. A rough rule: people needed per month ≈ emails per month ÷ 3.
# LeadSonar Docs
> Find the right people for your cold email, explained in plain words. Start here if you've never built a lead list, or jump straight to the API.
## Every cold email setup has four parts
[Section titled “Every cold email setup has four parts”](#every-cold-email-setup-has-four-parts)
LeadSonar is part 3: it decides **who** your emails go to. The other three parts decide whether they arrive.
[Part 1 Infrastructure  Maildeck Domains and inboxes you send from ](/before-you-send/infrastructure-with-maildeck/)[Part 2 Sequencer  Instantly, PlusVibe… Sends emails and follow-ups ](/before-you-send/sequencer/)[Part 3That's us Leads  LeadSonar The right people and their emails ](/find-leads/lead-finder/)[Part 4 Verification  EmailShield Removes bad addresses first](/before-you-send/verify-with-emailshield/)
## Start here
[Section titled “Start here”](#start-here)
[Cold email in 5 minutes ](/getting-started/cold-email-basics/)The four parts, and why each one matters before you send a single email.
[Your first 10 minutes ](/getting-started/quickstart/)Sign up, find your first 25 people, and download them as a CSV.
[Credits and plans ](/getting-started/credits-and-plans/)What a credit buys, what's free, and how to pick a plan.
[Why fresh leads matter ](/find-leads/why-fresh-leads/)Contact data goes stale. Here's what that costs you, and how LeadSonar avoids it.
## Build it into your own tools
[Section titled “Build it into your own tools”](#build-it-into-your-own-tools)
REST API
Count, browse, reveal and export leads; score contacts against your ICP; scrape company websites. One API key, JSON in and out. [API overview →](/api/overview/)
For AI agents
Let your agent size a market, shortlist people and score their fit — free to explore, with guardrails on spending. [LeadSonar for AI agents →](/ai-agents/)
Every endpoint, today's schema
The reference is generated from our OpenAPI spec, checked against the live API on 6 October 2026. [API reference →](/api/reference/)
# Get help
> How to reach a real person at LeadSonar.
We're in beta
Every customer gets **1-to-1 support** from the team on Slack while we’re in beta. Hit a snag, found something that looks wrong, or have an idea? Tell us — all feedback is appreciated, and it shapes what we build next.
## Ways to reach us
[Section titled “Ways to reach us”](#ways-to-reach-us)
* **Slack** — 1-to-1 support from the team: **[join at slack.leadsonar.io](https://slack.leadsonar.io)**.
* **In the app** — **Support** in the left sidebar.
* **Email** — .
## When you write to us, include
[Section titled “When you write to us, include”](#when-you-write-to-us-include)
* The email address of your LeadSonar account.
* What you were trying to do, and what happened instead.
* For a search problem: the filters you used (or the name of your preset).
* For an API problem: the endpoint, the request body, and the response — never your API key.
# Glossary
> The words you'll meet in LeadSonar and in cold email, in plain English.
**Bounce** — An email that comes back undelivered, usually because the address doesn’t exist. A high bounce rate pushes your emails into spam.
**Catch-all** — A mail server that accepts email for any address at its domain, so verification can’t confirm whether a specific person exists.
**Credit** — The unit you spend in LeadSonar. Searching is free; revealing, exporting and AI enrichment cost credits. [Details →](/getting-started/credits-and-plans/)
**Domain** — The part of an email address after the `@`. Cold email is sent from separate domains so your main one is never at risk.
**Enrichment** — Filling in more about a lead: ICP grade, what their company does, a personalized opener. [Details →](/enrich/ai-enrichment/)
**Export** — Getting leads out of LeadSonar as a CSV file.
**ICP (ideal customer profile)** — A one- or two-sentence description of the companies and people you sell to.
**ICP grade** — How well a lead fits your ICP, from **A** (strong) to **D** (poor).
**Inbox (mailbox)** — One email account you send from. Each one can only send a few dozen cold emails a day safely.
**Lead** — One person you might email.
**My Leads** — The tab in the Lead Finder holding everyone you’ve revealed. It doesn’t expire.
**Preset** — A saved set of Lead Finder filters, kept on your account.
**Reveal** — Unlocking a lead’s contact details. 1 credit per person, never charged twice.
**Sequencer** — The tool that sends your emails and follow-ups on a schedule (Instantly, PlusVibe, Smartlead…).
**SPF, DKIM, DMARC** — DNS records that prove your emails really come from your domain. [Maildeck explains them →](https://docs.maildeck.co/domains-dns/spf-dkim-dmarc/)
**Verification** — Checking an address can receive email before you send to it. [EmailShield →](/before-you-send/verify-with-emailshield/)
**Warm-up** — A few weeks of gentle, automatic sending that builds a new inbox’s reputation before it sends cold email.