GDPR-compliant B2B prospecting comes down to five habits. Collect only what you need. Record your legal basis. Tell people where you got their data. Honour opt-outs fast. Keep a suppression list. This guide turns each habit into a request you can run. It is engineering guidance, not legal advice. Ask counsel before you send.
TL;DR
- Takes about 30 minutes. Sizing is free. The test pull spends about 25 records, plus 1 per person you enrich.
- Narrow by country, role and work email so you hold less personal data, not more.
- Log your legal basis and source per batch, and check every list against a suppression file before you send.
Prerequisites
- A LeadOcean API key from the free plan (1,000 records for life, no card), exported as
$LEADOCEAN_API_KEY. curlandjq.- A file called
suppression.txtwith one email per line. It can start empty. - A short legitimate interest assessment written down. Recital 47 says direct marketing may be a legitimate interest, but it needs careful assessment (GDPR Recital 47, September 2026).
Step 1: Decide the scope before you pull anything
Data minimisation starts with the filter, not the export. Write down the market, the role and the reason. Then express exactly that and nothing wider.
Example scope: VPs of sales in Germany, France and the Netherlands, work email only, for a sales tooling offer. Your assessment should say why that role would reasonably expect the message.
Check the exact enum strings first. They are case sensitive.
curl -s "https://api.leadocean.io/v1/enums" \
-H "x-api-key: $LEADOCEAN_API_KEY" | jq 'keys'Use the MCP tool leadocean_list_enum_values if you work from Claude. Country takes ISO codes (DE, FR, NL). Job level takes VP. Job function takes Sales & Business Development.
Step 2: Size the list for free
Count before you search. A count spends no records and tells you whether the scope is worth a send.
curl -s "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{
"country": ["DE","FR","NL"],
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"]
}' | jq '.meta'If you work through Claude with the hosted MCP server, leadocean_count_leads does the same for free. count=true goes in the query string, not the body. The response has meta.countOnly: true and an empty data array. meta.total is capped at 100,000.
Step 3: Pull only work emails you can mail
Personal addresses carry more risk and rarely help B2B outreach. Leave them out. Ask for work addresses with a mailable status.
curl -s "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{
"country": ["DE","FR","NL"],
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"emailType": ["work"],
"emailStatus": ["verified","catch_all_valid"],
"limit": 25
}' > batch_001.jsonEach person returned costs one record. Page with cursor from the response. One search pages to 10,000 rows; narrow the filters instead of walking the index. For bigger volumes use POST /v1/exports (up to 50,000 rows a request, 500,000 a day, not on the Free plan).
Leave out what the campaign does not use. Skip phone numbers for an email-only campaign, skip personal addresses, and do not store career history (resume_data) for a cold email. "We pulled work email and job title because the message is about their job" is easy to defend.
LeadOcean refreshes the dataset monthly, and each record carries its own fetched_at date. Store it. If a record is old, re-enrich before you send.
Step 4: Log the legal basis and the source
Article 14 covers data you did not collect from the person. You must tell them within one month at the latest, including the legitimate interest you rely on (GDPR Article 14, September 2026). That means a record of where each batch came from.
jq -n --arg file "batch_001.json" '{
batch: $file,
pulled_at: (now | todate),
source: "LeadOcean people search",
basis: "legitimate interest (Art. 6(1)(f))",
assessment: "lia-2026-10-sales-tooling.pdf",
notice_due: ((now + 2592000) | todate)
}' >> prospecting_log.jsonlThe notice is usually your first email, with a privacy link and a plain opt-out. National e-marketing laws sit on top of GDPR and differ by country. Check each market you send into with counsel.
Step 5: Re-check and reveal just before you send
Data ages and people change jobs. Writing to someone about a role they no longer hold hurts deliverability and is a privacy problem.
Search rows carry no addresses. Enrich each person you will mail by the id on their search row (meta.source_ids.person_id), with reveal_email set to true. A hit counts one record. A person we hold nothing for is a 404 and costs nothing.
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{"person_id": "1234567890", "reveal_email": true}' \
| jq -r '.data.contact_data.contact_emails[0].email' >> emails.txtThe id above is a placeholder. Before you append, read data.contact_data.email_status and the current role in data.contact_data.contact_current_experiences, and drop anyone who no longer fits your scope.
Step 6: Apply the suppression list and honour objections
People can object to direct marketing at any time, and then you must stop using their data for it (GDPR Article 21, September 2026). A suppression list is how you make that real.
grep -vFxf suppression.txt emails.txt > sendable.txt
wc -l sendable.txtAppend every unsubscribe and objection to suppression.txt the same day, and check it before every send. Never delete an address from that file, or you will mail them again. Any sequencer, Clay table or n8n flow that receives the list must honour the same file. LeadOcean has no sequencer of its own, so the send step lives in a tool you choose.
Set a retention period too. If a contact has not replied within it, delete their row from your own tools and keep only the address in the suppression file.
What you get
A real free count, run on 2026-10-21 with the MCP tool leadocean_count_leads. Filters: country DE, FR, NL, jobLevel VP, jobFunction Sales & Business Development, emailType work. The tool counts verified, catch_all_valid and catch_all work addresses by default.
{
"total": 2685,
"totalIsExact": true,
"totalAll": 5787,
"distinctCompanies": 1565,
"credits": 0
}So 2,685 people at 1,565 companies match with a mailable work email, out of 5,787 matching people with no email condition. The count spent 0 records. Your batch_001.json from Step 3 has the people themselves.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Re-export $LEADOCEAN_API_KEY and send it as x-api-key |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Wait for Retry-After, then slow the loop |
| 402 | Out of records (Free is 1,000 for life) | Check GET /v1/account, then pick a plan |
Empty data | Wrong enum string, such as vp for jobLevel | Look up the exact value with GET /v1/enums |
data empty on a count call | You sent count=true, which returns totals only | Remove count=true to get rows |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on the Free plan | Split the export or move to a paid plan |
FAQ
Is B2B cold email legal under GDPR?
Often yes, on a legitimate interest basis, if you document it and respect objections. Recital 47 allows direct marketing as a legitimate interest after careful assessment. National e-marketing laws can add rules on top, so check each country with counsel.
Should I use personal emails?
Not for B2B outreach. Filter emailType to work and mail people about their job.
How do I prove where a contact came from?
Keep the batch file and the pull date in your log, as in Step 4, plus the record's fetched_at date.
How many records does the whole guide cost?
Sizing is free. The test pull costs one record per person returned, so 25 records at limit 25, plus one record for each person you enrich in Step 5.
Hub: sales prospecting guides. Related: best AI tools for sales prospecting, B2B outbound sales, GDPR-compliant B2B data providers, and pricing.
Size your EU prospect list for free, then pull only what you need
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →