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

How-to guide

How to Find Work Emails (in Windsurf)

One mcp_config.json entry, a free count, then a lookup that returns a current work address and its status.

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

TL;DR

  • Windsurf reaches LeadOcean through one mcp_config.json entry and a browser sign-in. You search for the people, then ask for each one's current work email and its status.
  • It takes about 15 minutes. The example run spends up to 7 of your 1,000 free records: 3 on search rows, 3 on lookups and 1 on a REST re-check.
  • Counts and enum lookups cost 0. A person we hold nothing for is a 404 and costs nothing.

Prerequisites

  • A LeadOcean account from app.leadocean.io. The free plan has no card, 1,000 records one-off, and needs a work email.
  • Windsurf installed. The Windsurf MCP docs, October 2026, say Enterprise users must turn MCP on in settings, and team admins can allowlist servers.
  • Optional, for the REST steps: curl, jq and a key in your shell as $LEADOCEAN_API_KEY. The MCP steps need no key. The lookup needs the enrich scope, which free keys have.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Add the LeadOcean MCP server

Add one remote entry to Cascade's MCP config. In the Cascade panel, open the ... menu, then the Open MCP config file icon in the MCPs section. Windsurf's docs say a remote HTTP server needs a serverUrl or url field.

json
{
  "mcpServers": {
    "leadocean": {
      "serverUrl": "https://api.leadocean.io/mcp"
    }
  }
}

Do not add a headers block. LeadOcean signs you in with OAuth 2.1 in the browser, so no key is pasted. The Windsurf docs do not show the Cascade sign-in prompt, so check the server's status in the MCPs section after you save.

On the Devin Local agent, one command adds the server.

bash
devin mcp add leadocean https://api.leadocean.io/mcp

The full setup, including the Devin file paths, is on Connect LeadOcean to Windsurf.

Step 2: Check the email filters for free

Look up the exact strings before you filter. Filters take exact values, and a guess such as "Sales" returns nothing. Ask Cascade for the email type values.

text
Use leadocean_list_enum_values with name email_type. List the values and say which
one means an address at the person's current employer. Do not call any tool that
spends records.

The answer is work. The value work_other is a business address at a different company, usually a former employer, so ask for it deliberately.

Step 3: Count the audience

Size the people you can email before you look anyone up. The example is VP-level sales leaders in the UK with a verified work address.

text
Use leadocean_count_leads with jobLevel ["VP"], jobFunction ["Sales & Business
Development"], country ["GB"], emailType ["work"], emailStatus ["verified"],
facets false. Report the total and say what email filter it used.

The count tool is free however often you call it. Passing emailStatus replaces its default of verified, catch_all_valid and catch_all. So this total is verified work addresses only, not everyone we hold.

Step 4: Search for three people

Search returns thin rows with email flags and no addresses. Keep limit small, because each person returned costs 1 record.

text
Use leadocean_search_leads with the same filters and limit 3. Show name, job title,
company, email_status and the person_id for each row. Do not call get_lead yet.

The REST version is the same filters in a flat JSON body. Filters are arrays, 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": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["GB"],
    "emailType": ["work"],
    "emailStatus": ["verified"],
    "limit": 3
  }' | tee search.json | jq -r '.data[].meta.source_ids.person_id'

Each row carries its id at meta.source_ids.person_id. There is no name plus domain lookup in the API, so this id is how you get from a search row to an address.

Step 5: Ask for the work email

Pick a row and enrich it with reveal_email set to true. That returns every address we hold for the person, each with a type and a status. It also returns career history when we hold it: past roles, education and certifications.

text
Use leadocean_get_lead with person_id <id from row 1> and reveal_email true. Give me
the work address at their current employer, its status and its type in a table.
Tell me how many records this cost.

Repeat for rows 2 and 3. That is 3 records, and 6 so far with the search.

The reply lists each address with a type and a status. Pick the one whose type is work. A work_other address belongs to a former employer and is the likeliest to bounce. If the person has no work address, the table says so. Do not ask Cascade to guess one.

Keep the spend visible. Ask Cascade to stop after the three lookups and report the records used. A prompt that says "find emails for everyone you found" will keep calling the tool, one record per person.

Step 6: Re-check one lookup over REST

The REST route is one request to a documented endpoint. It returns at most one address, at the person's current employer, and only if it is verified, catch_all_valid or catch_all.

bash
ID=$(jq -r '.data[0].meta.source_ids.person_id' search.json)
curl -s "https://api.leadocean.io/v2/people/email/work?person_id=$ID" \
  -H "x-api-key: $LEADOCEAN_API_KEY"

This call costs 1 record, even when data comes back null. A 404, where we hold nothing for the person, costs 0. Field detail is on Find a work email.

Step 7: Read the status before you send

Ask Cascade to flag anything weaker than verified.

text
For each address, say whether it is safe to send to. verified is safe.
catch_all_valid and catch_all can still bounce. Flag everything else. Do not guess
an address from a name pattern.

LeadOcean gives no refund for bounces. The status is your only protection.

What you get

The Step 2 and Step 3 results below are real tool runs from 21 October 2026. Both are free. The email type lookup returned seven values.

json
{
  "name": "email_type",
  "total": 7,
  "values": ["work", "work_other", "work_any", "personal", "other", "unknown", "none"],
  "labels": {
    "work": "Work (current employer)",
    "work_other": "Work (a different company)",
    "work_any": "Any work address",
    "personal": "Personal",
    "other": "Other",
    "unknown": "Unknown",
    "none": "No email"
  }
}

The count for VP, Sales & Business Development, country GB, emailType work, emailStatus verified returned this.

json
{
  "total": 819,
  "totalIsExact": true,
  "distinctCompanies": 640,
  "credits": 0,
  "sample": 1,
  "hasMore": true,
  "source": "leadocean"
}

There are 819 people in the UK, at 640 companies, who match and whose best email is a verified work address. Treat it as an upper bound: the status on each enriched address is the final word. Your number will differ as the data refreshes monthly.

The lookup in Step 6 returns this shape. It is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": {
    "email": "jane.doe@acme.com",
    "status": "verified",
    "verified_batch_date": "2026-09-14"
  }
}

When no address qualifies, data is null. That means none that qualify, not that the person has no work email. The whole run costs up to 7 records: 3 for the search, 3 for the Step 5 lookups and 1 for Step 6.

Troubleshooting

ErrorCauseFix
401Missing, wrong or revoked key on a REST call, or the MCP sign-in was not approvedRe-copy the key from app.leadocean.io and export $LEADOCEAN_API_KEY again. For MCP, repeat the browser sign-in.
429Above your plan's rate limit (5 a second on Free, 50 on Solo, 200 on Agency), or a fair-use window reachedWait the Retry-After seconds and send fewer calls.
402The 1,000 free records are spentFree records do not reset. Check GET /v1/account, or move to Solo at $97 a month.
Count or search returns 0A filter value outside the catalogue, such as emailType: "business"Call leadocean_list_enum_values and pass the exact string.
data: null on a lookupNo address at the current employer is verified, catch_all_valid or catch_allA retry will not change it. It still cost 1 record. Try a personal email or skip the person.
400 export_limit_rowsAn export limit above 50,000 rowsSplit the audience by country or headcount band and run several exports. Exports need Solo or above.

FAQ

Can Windsurf find a work email from just a name and company?

Not in one call. The API has no name plus domain lookup. Search by title and domain, pick the right row, then enrich its person_id.

How many records does one work email cost?

One per lookup. That includes a lookup that returns null. A 404 costs 0. The free plan's 1,000 records cover about 1,000 lookups. Solo is $97 a month and Agency $497 a month, each with a fair-use pace instead of credits. See pricing.

Can I find emails for a list in Windsurf?

Run it per person for a handful. For a list, use the Exports page in the app at app.leadocean.io. It has a filter builder, a column picker, the price before you start and a CSV download. Filter with emailType work and emailStatus verified. Bulk CSV export is not on Free: it starts on Solo.

Is there a skill that does this?

Yes. The Find Work Email skill wraps these steps for Claude. For another editor, see find work emails in VS Code. More recipes are in the blog hub.

Find your first work email in Windsurf, free

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

Get your free API key →