You put LeadOcean in the first position so Clay's paid providers only run on the rows it could not fill. The link is one HTTP API column calling POST /v1/people/enrich. The gate is an "Only run if" condition on every paid column after it.
TL;DR
- Takes about 30 minutes: one column, one header account, one run condition per paid provider, then a 50-row test.
- Spends at most 50 LeadOcean records on the test. A person LeadOcean holds nothing for is a 404 and costs nothing.
- Needs Clay Growth or higher for the HTTP API column (Clay pricing, September 2026). The free LeadOcean plan covers the test.
Prerequisites
- A LeadOcean key from app.leadocean.io/register. Free plan: 1,000 records, one-off, no card. Export it as
$LEADOCEAN_API_KEY. - A Clay workspace on Growth or Enterprise. The pricing page lists the HTTP API column on those two only (Clay pricing, September 2026).
- A Clay table with a column of LinkedIn profile URLs, and at least one paid email or phone provider column you want to gate.
curlin a terminal for the test call.
Step 1: Size the audience for free
Count first, so you know how many rows you are about to send. A search with count=true in the query and limit: 1 costs no records (LeadOcean API reference, September 2026). The total comes back in meta.total.
curl -X POST "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["CA"],
"emailStatus": ["verified", "catch_all_valid", "catch_all"],
"limit": 1
}'Filters are arrays. data comes back empty on a count call, so read meta.total. It is capped at 100,000.
Step 2: Test one row from a terminal
Send the exact request Clay will send per row. Use a LinkedIn URL from your own table. One identifier per request: linkedin_url, email, phone or person_id.
curl -X POST "https://api.leadocean.io/v1/people/enrich" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "content-type: application/json" \
-d '{"linkedin_url":"https://www.linkedin.com/in/your-own-row","reveal_email":true}'A hit costs one record. reveal_email costs no extra record. A miss returns 404 and costs nothing.
Step 3: Add the HTTP API column in Clay
Save the key once as a header account so it is not visible in the table. Clay shows a manually typed header in plain text to anyone with access to the column (Clay docs, September 2026).
- Click Add enrichment, pick HTTP API, open the Configure tab.
- In Select header account, click + Add account. Add the key
x-api-keywith your LeadOcean key as the value. Name it LeadOcean. - Set the method and body as below.
/LinkedIn URLis Clay's column reference.
Method: POST
URL: https://api.leadocean.io/v1/people/enrich
Account: LeadOcean (header x-api-key)
Headers: content-type: application/json
Body: {
"linkedin_url": "/LinkedIn URL",
"reveal_email": true
}
Field paths to return:
data.contact_data.email_status
data.contact_data.has_email
data.contact_data.has_phoneClay uses dot notation for field paths. Name the column LeadOcean. Click Test on one row before you run the table.
Step 4: Gate every paid provider behind it
This is what makes LeadOcean the first hop. On each paid email or phone column, open Run settings and add a condition so it runs only when the LeadOcean column came back empty.
Condition on each paid provider column:
{{LeadOcean email status}} is emptyConditional runs work like an if statement: the enrichment runs when the condition is true and is skipped when it is false (Clay docs, September 2026). The HTTP API column accepts the same setting. Clay's docs do not say how a 404 HTTP API row is shown or whether an is empty condition matches it (Clay docs, October 2026). Test it on five rows that LeadOcean does not hold before you run the full table.
Step 5: Run 50 rows and read the result
Run 50 rows, not the table. Then compare LeadOcean's own usage number with what Clay filled. GET /v1/usage reports records spent (LeadOcean API reference, September 2026).
curl "https://api.leadocean.io/v1/usage" \
-H "x-api-key: $LEADOCEAN_API_KEY"In Clay, filter the table on rows where the LeadOcean column is filled. Those rows never triggered a paid provider. The rest did.
Your fill rate is that share of the 50. It depends on your list, so use your own number. Do not size a full run from anyone else's.
What you get
A table where each row carries a LeadOcean email status, and paid provider cells stay empty on rows LeadOcean filled. A free count call gives you the audience size before you start.
Free leadocean_count_leads MCP call, run 2026-09-30 with no filters (default: verified, catch_all_valid and catch_all addresses only):
{
"total": 124786586,
"totalIsExact": true,
"credits": 0,
"defaults": "Counted only addresses worth sending to (emailStatus: verified or catch_all_valid or catch_all)"
}That is the whole mailable people set, not your audience. Step 1 narrows it with your filters.
Response shape from the API reference for each row Clay receives, placeholder values only:
{
"success": true,
"data": {
"contact_data": {
"email_status": "verified",
"email_type": "work",
"has_email": true,
"has_phone": true,
"contact_emails": [{ "email": "name@example.com", "type": "work", "status": "verified" }],
"contact_phones": [{ "phone": "+14155550133", "type": "mobile" }],
"contact_current_experiences": []
}
},
"meta": { "source": "leadocean", "credits": 1 }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 on every row | Missing or wrong x-api-key header | Re-save the header account. The name is x-api-key, not Authorization. |
| 429 on a big run | More than 100 requests a second on one key | Lower the rate limit setting on the Clay column and retry. |
| 402 partway through | The free plan's 1,000 records are spent | Stop the run, or move to Pro at $499 a month. |
| 404 on some rows | LeadOcean holds nothing for that person | Expected and free. The gated paid providers run on those rows. |
| Empty results from a search | A filter value is not in the catalogue | Resolve it with GET /v1/enums/{name}, for example email_status, and use the exact string. |
| Export refused | The job is over the ceiling of 50,000 rows a request or 500,000 a day | Split the export into several requests and spread them over days. |
FAQ
Why put LeadOcean first and not last?
Because a LeadOcean miss costs nothing, you can try it on every row. Paid providers then run only on the gap. Put the provider with the cheapest miss first.
Do I need the Clay Growth plan?
Yes, for the HTTP API column. Clay lists it on Growth and Enterprise only (Clay pricing, September 2026). On Launch, pull a CSV from LeadOcean Exports and import it instead.
What does a miss cost in Clay?
Clay lists HTTP API calls as using an Action and does not say whether a call that returns 404 is charged (Clay docs, October 2026). LeadOcean charges nothing for a miss.
Can I add phone numbers as a second hop?
Yes. Filter with hasPhone before you spend, then call GET /v2/people/phone. It costs one record per call, including a call that finds nothing. See the phone waterfall skill.
Related: what a data waterfall hop is, LeadOcean, Clay and Salesforce together, pricing. Back to the blog.
Put LeadOcean first in your Clay waterfall. Start free.
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →