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

How-to guide

How to Enrich a CSV of Contacts in Claude (2026)

Connect one MCP server, test on five rows for free-plan records, then run the full file with a short script. Each matched row costs 1 record.

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

You enrich a CSV in Claude by connecting the LeadOcean MCP server, attaching the file, and asking Claude to look up each row. Claude does the lookups. LeadOcean returns the email, status and phone it holds.

This guide tests on five rows, then moves to a script for the full file. Total time is about 20 minutes.

TL;DR

  • Takes about 20 minutes: 5 minutes to connect, 5 to test on five rows, 10 to run a script on the full file.
  • Spends 1 record per row we match, so a 25-row file costs up to 25 of your 1,000 free records. A row we hold nothing for costs 0.
  • Claude handles small files in chat. Past about 25 rows, switch to the API script in Step 4. It runs faster and Claude does not need to stay open.

Prerequisites

  • A LeadOcean account. Start free: no card, 1,000 records, one-off, work email required.
  • A Claude account that can add a custom connector. The Claude connector docs, October 2026, list Free, Pro, Max, Team and Enterprise. Free allows one custom connector.
  • A CSV with a linkedin_url column. Email or phone also work as the lookup key.
  • For Step 4 only: an API key from the app, saved as $LEADOCEAN_API_KEY, plus curl and jq.

A sample contacts.csv, with placeholder rows:

csv
name,company,linkedin_url
Jane Doe,Acme,https://www.linkedin.com/in/janedoe-example
John Roe,Acme,https://www.linkedin.com/in/johnroe-example

Step 1: Connect LeadOcean to Claude

Add https://api.leadocean.io/mcp as a custom connector, then sign in with OAuth. No key is pasted. The full click path is on the Claude setup page.

The short version, on a Pro or Max Claude plan, is below.

text
Customize > Connectors > + Add > Add custom connector
Name: LeadOcean
URL:  https://api.leadocean.io/mcp

Click Continue, approve the LeadOcean sign-in in your browser, then switch the connector on in your chat under "+" and "Connectors". The server exposes 13 tools. Seven are free to call.

Step 2: Check the filters for free

Before you spend records, confirm Claude can reach the server. Ask for a free lookup:

text
Using LeadOcean, list the valid values for job level. Do not search for anyone.

Claude calls leadocean_list_enum_values. That costs 0 records. If it answers with six values, the connection works.

Step 3: Enrich five rows in chat

Attach contacts.csv to the chat and cap the run at five rows. The cap keeps the spend visible.

text
I attached contacts.csv. Take the first 5 rows. For each linkedin_url, call
leadocean_get_lead with reveal_email true, so it returns the emails and phones it holds.
Stop after 5 rows. Return a table with name, company, email, email_status, phone.
If a row is not found, write "not found" and move on. Do not guess an address.

Claude calls leadocean_get_lead once per row. reveal_email covers both emails and phone numbers and adds no record. A found row costs 1 record. A row that finds nobody costs nothing, the same as a REST 404.

Read email_status before you send. LeadOcean gives no refund or credit for bounced emails.

Step 4: Run the full file with the API

A script is the right tool above about 25 rows. It calls POST /v1/people/enrich once per row. Set reveal_email to true, which returns every email and phone we hold at no extra record.

bash
export LEADOCEAN_API_KEY=your_key_here

echo "linkedin_url,email,email_status,phone" > enriched.csv
tr -d '\r' < contacts.csv | tail -n +2 | while IFS=, read -r name company linkedin; do
  curl -s -X POST https://api.leadocean.io/v1/people/enrich \
    -H "x-api-key: $LEADOCEAN_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"linkedin_url\":\"$linkedin\",\"reveal_email\":true}" |
  jq -r --arg u "$linkedin" '[$u,
    (.data.contact_data.contact_emails[0].email // ""),
    (.data.contact_data.email_status // ""),
    (.data.contact_data.contact_phones[0].phone // "")] | @csv' >> enriched.csv
done

The script runs one request at a time, inside the Free plan's 5 requests a second. Open enriched.csv in any spreadsheet.

Each request takes exactly one of linkedin_url, email, phone or person_id. There is no name plus domain lookup. To find people at a company first, search by domain, then enrich by person_id.

Step 5: Check the result before you send

Enrichment gives you addresses. It does not tell you which ones are safe to mail. Filter on email_status first.

bash
awk -F, 'NR==1 || $3 ~ /verified|catch_all/' enriched.csv > mailable.csv

That keeps rows whose status contains verified or catch_all. Drop risky, unknown, role, disposable and spam_trap. The full list of 13 statuses is in GET /v1/enums/email_status. Count the rows left in mailable.csv before you load it into your sending tool.

In Claude, the equivalent prompt is short:

text
From the table above, keep only rows where email_status is verified or catch_all.
Say how many rows you dropped and why.

Expect some rows to come back empty. A CSV of LinkedIn URLs usually includes profiles we do not hold, and each of those is a free 404. Check the enriched.csv row count against contacts.csv so you know the match rate for your own list.

What you get

Step 2 returns the exact strings the jobLevel filter accepts. We ran it on 2026-10-01:

json
{"name":"job_level","description":"Seniority band of the person's current role.","total":6,"matched":6,"values":["C-Team","Director","Manager","Other","Staff","VP"],"truncated":false}

Steps 3 and 4 return one record per matched row. This is the response shape from the API reference, September 2026, with placeholder values:

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

Without reveal_email, contact_emails and contact_phones are absent. has_email and has_phone still tell you whether a value exists.

Troubleshooting

ErrorCauseFix
401The x-api-key header is missing or the key is wrong.Copy a fresh key from the app and re-export $LEADOCEAN_API_KEY.
402Free plan: your records are spent. The free plan is 1,000 records, one-off.Run GET /v1/account to check the balance, or move to Solo at $97 a month.
404We hold nothing for that identifier.Nothing to fix. A 404 costs 0 records. Try the email or person_id for that row instead.
429Above your plan's rate: 5 requests a second on Free, 200 on Agency.Pause a second and retry. A one-at-a-time loop does not hit this.
Empty search resultsA filter value is not an exact enum string, such as Vice President instead of VP.Call leadocean_list_enum_values and use the string it returns.
Export refusedOne export is capped at 50,000 rows, and an account at 500,000 rows a day.Split the job across requests and days, or narrow the filters.

FAQ

Can Claude read a CSV and enrich every row?

Yes for small files. Claude makes one leadocean_get_lead call per row, so a long file means a long chat. Cap each prompt at 25 rows, or use the Step 4 script for the rest.

How many records does a 25-row file use?

Up to 25. Each matched row costs 1 record. A row we hold nothing for costs 0. Counts, filter lookups and account checks are free.

Can I upload a CSV to the Exports page instead?

The Exports page in the app builds a file from filters: a filter builder, a column picker and a price preview. It does not take an uploaded list. To enrich your own rows, use Claude or the API.

What if my CSV has no LinkedIn URLs?

Use email or phone as the key instead. Each request takes exactly one identifier. For a list of company domains, search first, then enrich by person_id.

Does this work on the free plan?

Yes. Free keys get both search and enrich scopes inside the 1,000 one-off records. The MCP server is the same one paid plans use.

Enrich your own CSV in Claude, free

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

Get your free API key →