Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Find Business Email Addresses (With Three API Requests)

Size the list for free, find the people, reveal one checked address each. Every step is a request you can run today.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

The reliable way to find a business email is to query a database that stores the address with a deliverability status. Guessing a pattern and hoping is the fallback, not the method.

Most guides on this topic list browser extensions and tell you to try first.last@company.com. This one is for people who want a repeatable request. You will size a list, find the people, and reveal one address each, with a status you can filter on.

Pick this route when you have a market ("US C-level leaders at 11-50 person companies") or a company domain, not a single name.

TL;DR

  • The first run takes about 15 minutes with curl.
  • It spends about 2 records per contact: 1 for the search row, 1 for the reveal. Counts, sizing and a 404 are free.
  • Send only to verified, catch_all_valid or catch_all. Check email_status before every send.

Prerequisites

  • A LeadOcean API key from app.leadocean.io. Free is 1,000 records, one-off, no card.
  • The key exported as $LEADOCEAN_API_KEY.
  • curl and jq. Examples use acme.com and Jane Doe as placeholders.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Size the audience for free

Count before you spend. Send count=true and limit=1 as query parameters. Arrays go comma-separated.

bash
curl -s -G https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "jobLevel=C-Team" \
  --data-urlencode "country=US" \
  --data-urlencode "employeeRange=11-50" \
  --data-urlencode "count=true" \
  --data-urlencode "limit=1" | jq '.meta | {total, totalIsExact, countOnly}'

REST meta.total stops at 100,000. A bigger market returns a floor with totalIsExact false. The MCP tool leadocean_count_leads is also free.

Step 2: Search the people

Search returns a thin row per person, not an address. Send a flat JSON body. Filters are arrays of strings, limit runs 1 to 100, and you page with cursor.

bash
curl -s https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobLevel": ["C-Team"],
    "country": ["US"],
    "employeeRange": ["11-50"],
    "emailStatus": ["verified", "catch_all_valid"],
    "limit": 25
  }' | jq '.data[0], .meta.nextCursor'

Each person returned costs 1 record. Pass meta.nextCursor back as cursor for the next page. One search pages to 10,000 rows, then meta.depthCapped is true. Narrow the filters instead of walking further.

Start from a company instead? Use GET /v1/companies/{domain}/people, for example /v1/companies/acme.com/people.

Step 3: Reveal the address with enrich

Enrich takes exactly one of linkedin_url, email, phone or person_id. There is no name plus domain lookup, so take the person_id from the search row at meta.source_ids.person_id.

bash
curl -s https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person_id": "PERSON_ID_FROM_STEP_2", "reveal_email": true}' \
  | tee person.json | jq '.data.contact_data | {email_status, email_type, contact_emails}'

It costs 1 record. Someone we hold nothing for is a 404 and costs nothing. Revealing adds every email and phone we hold at no extra charge.

Step 4: Read the status before you send

The address is only half the answer. email_status tells you whether to send. A verified address is safe to mail. A catch_all domain accepts everything, so the risk is higher. Filter the file you saved in Step 3; a second enrich call would spend another record.

bash
jq -r '.data.contact_data
      | select(.email_status | IN("verified","catch_all_valid","catch_all"))
      | .contact_emails[0].email' person.json

Skip risky, invalid, role, disposable and spam_trap. We do not refund bounced emails, so the filter is your protection.

Step 5: Do it from an AI agent

The hosted MCP server at https://api.leadocean.io/mcp signs in with OAuth, so you paste no key. It has 13 tools. Counting is free, so ask for the count first.

text
Count US C-Team people at companies with 11-50 employees using
leadocean_count_leads. Report the total and distinctCompanies, and say
which email filter the count used. Do not run a search yet.

Step 6: Export a whole list

For hundreds of rows, export instead of paging. POST /v1/exports takes the same filters as people search, up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free.

bash
curl -s https://api.leadocean.io/v1/exports \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "US C-Team 11-50",
    "filters": {"jobLevel": ["C-Team"], "country": ["US"],
                "employeeRange": ["11-50"],
                "emailStatus": ["verified", "catch_all_valid"]},
    "limit": 5000,
    "preset": "full"
  }'

Poll GET /v1/exports/{id}, then GET /v1/exports/{id}/download. Every row costs 1 record. The Exports page in the app does the same with a filter builder and shows the price first.

What you get

Step 1 is free. We ran leadocean_count_leads on 2026-10-21 with job level C-Team, country US and headcount 11-50, on the default mailable filter (verified, catch_all_valid or catch_all).

QueryCountExact
Mailable people (default email filter)732,580Yes
Same filters, no email condition2,808,968Yes

The mailable people span about 339,596 employers (an estimate, not exact). Roughly a quarter of the people who match have an address worth sending to. Narrow by industry or title before you export.

A revealed person comes back in this shape. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": {
    "profile_data": { "...": "name, title, company" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "email_type": "work",
      "contact_emails": [
        { "email": "jane.doe@acme.com", "type": "work", "status": "verified" }
      ]
    }
  }
}

Troubleshooting

ErrorCauseFix
401The x-api-key header is missing, or the key is wrong or revoked.Copy a fresh key from the app and reload $LEADOCEAN_API_KEY.
402Your records are spent. On Free the 1,000 are one-off.Check GET /v1/account, or move to a paid plan.
429Requests above your plan's rate limit: 5 a second on Free, 200 on Agency.Wait the Retry-After seconds, then retry.
Empty resultsA filter value is not an exact enum string, such as Chief for C-Team.Call leadocean_list_enum_values and pass the exact string.
404 on enrichWe hold nothing for that person.Nothing was charged. Try another person_id.
400 or 429 on an export400: over 50,000 rows in one export. 429: past 500,000 rows a day.Split the job across requests and days, or narrow the filters.

FAQ

Can I find a business email from a name and a company?

Not in one call. Enrich has no name plus domain lookup. Search by domain or GET /v1/companies/{domain}/people, then enrich by person_id.

Why does search not show the email?

Search returns a thin row with flags such as has_email. The address comes from enrich with reveal_email set, which costs 1 record.

How many business emails can I get on the free plan?

You have 1,000 records, one-off. A contact costs about 2: one from search and one from the reveal. That is roughly 500 contacts.

Are the addresses current?

The dataset is refreshed monthly, and each record carries its own fetched_at date. Read email_status before you send.

For a single company site, read how to find email addresses on a company website. For one senior role, see ways to find CEO email addresses, and for owners, how to find small business owner email. More recipes live in the blog hub. Plans are on pricing.

Size your list free, then reveal verified business emails

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →