A B2B sales agent is software that finds accounts, picks contacts, drafts outreach and logs the result with little human input. The model is the easy part. The data loop is where most agents fail.
This guide builds that loop: size a list for free, pull 25 contacts, enrich 5 of them. Every request is real and runs against https://api.leadocean.io.
TL;DR
- Time: about 20 minutes from a free account to a working data loop.
- Cost: about 30 LeadOcean records. 25 for one search page, up to 5 for enrichment. Sizing is free.
- Result: an agent that checks list size before it spends anything, then pulls and enriches only the people it needs.
Prerequisites
- A LeadOcean account on the Free plan: 1,000 records for life, no card, 5 requests a second.
- An API key from app.leadocean.io, exported as
$LEADOCEAN_API_KEY. curlandjq, or any HTTP client.- Optional: an MCP client such as Claude Code. The hosted server is at
https://api.leadocean.io/mcpand uses OAuth sign-in, so no key is pasted.
Step 1: Define the buyer in filters
Write the target as filters, not as a prompt. An agent that guesses at lists burns records. One that sends exact enum values does not.
Filter values are exact strings. Check them with the free leadocean_list_enum_values MCP tool or GET /v1/enums.
{
"jobLevel": ["VP"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"]
}A wrong case, such as vp, returns an empty result rather than an error. That is the most common reason an agent reports "no leads found".
Step 2: Size the list before spending
Make the agent count first. Counting is free on every plan.
In an MCP client, the tool call is leadocean_count_leads with the same filters. Over REST, send count=true as a query parameter with limit=1:
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 '{"jobLevel":["VP"],"jobFunction":["Sales & Business Development"],"country":["US"]}' \
| jq '.meta'The REST total is capped at 100,000 (meta.total). The MCP count tool returns the exact figure, so use it when the number matters. Put a rule in your agent: if the count is above its budget, narrow the filters and count again.
Step 3: Pull one page of contacts
Search with a flat JSON body. Filters are arrays of strings, limit runs from 1 to 100 and you page with cursor.
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": ["US"],
"emailStatus": ["verified"],
"limit": 25
}' | tee page1.json | jq '.meta'This page costs 25 records, one per person returned. Take meta.nextCursor from the response and send it as cursor for the next page. One search pages to 10,000 rows. When meta.depthCapped is true, narrow the filters instead of walking further.
Step 4: Enrich only the people the agent will contact
Do not enrich the whole page. Let the agent score the 25 rows, then enrich the few it will message. Enrich takes exactly one of linkedin_url, email, phone or person_id.
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}'Take the id from meta.source_ids.person_id on the search row. There is no name-plus-domain lookup. Search by domain first, then enrich by person_id. A person we hold nothing for returns a 404 and costs nothing.
Enrichment also returns career history in resume_data: past roles, education and certifications. An agent can use a past role as an opening line.
Step 5: Give the loop to the agent through MCP
With the MCP server connected, the agent runs steps 1 to 4 itself. Add a short instruction so it counts before it searches:
You prospect for B2B sales teams. Before any search, call
leadocean_count_leads with the target filters. If the count is over
500, narrow the filters first. Search at most 25 people per run.
Enrich only the people you will message. Never write an email
address you did not get from a tool result.The server exposes 13 tools. Seven are free: leadocean_count_leads, leadocean_count_companies, leadocean_list_filters, leadocean_list_enum_values, leadocean_get_account, leadocean_get_export and leadocean_list_exports. The agent can size a company list with leadocean_count_companies before it picks accounts.
Step 6: Add a budget guard
An agent with no limit will keep paging. Give it a hard cap in code, not in the prompt. Models forget prompts. They do not skip an if.
#!/usr/bin/env bash
BUDGET=75 # stop at 75 records, 3 pages of 25
SPENT=0; CURSOR=""
while [ "$SPENT" -lt "$BUDGET" ]; do
BODY=$(jq -n --arg c "$CURSOR" '{jobLevel:["VP"],
jobFunction:["Sales & Business Development"],
country:["US"], limit:25} + (if $c=="" then {} else {cursor:$c} end)')
RES=$(curl -s "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" -d "$BODY")
SPENT=$((SPENT + $(echo "$RES" | jq '.data | length')))
CURSOR=$(echo "$RES" | jq -r '.meta.nextCursor // empty')
[ -z "$CURSOR" ] && break
done
echo "spent $SPENT records"Run GET /v1/account before and after to confirm the number. On paid plans there is no per-record bill: the plan has a fair-use pace and a key slows when it reaches it. The budget guard still helps, because it keeps the agent from pulling people it will never contact.
For the background on how these agents decide and act, read what an AI sales agent is and how it works. To go from data loop to a full outbound system, see AI SDR and custom sales agents.
What you get
This is a live leadocean_count_leads result for the Step 1 filters, run on 2026-10-21. Only people with a verified, catch-all-valid or catch-all email are counted by default.
{
"total": 129494,
"totalIsExact": true,
"totalAll": 350517,
"distinctCompanies": 58121,
"credits": 0
}Read it like this. 129,494 US VPs in Sales & Business Development have an email worth sending to. Another 221,023 match the filters without one. The call cost zero records.
A search row has this shape (response shape from the API reference, api.leadocean.io/openapi.json, checked October 2026). Values are placeholders:
{
"success": true,
"data": [
{
"profile_data": {
"profile_full_name": "Jane Doe",
"profile_headline": "VP Sales at Acme"
},
"contact_data": {
"has_email": true,
"has_phone": true,
"email_status": "verified"
},
"meta": { "source_ids": { "person_id": "1234567890" } }
}
],
"meta": { "count": 1, "limit": 25, "nextCursor": "CURSOR", "depthCapped": false }
}Search rows are thin: flags, no contact points. Map meta.source_ids.person_id into your agent's state and send it to enrich in Step 4.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header. | Copy the key from app.leadocean.io again and check $LEADOCEAN_API_KEY is exported in the shell the agent runs in. |
| 429 | Requests above the plan rate limit: 5 a second on Free, 200 on Agency. | Honour the Retry-After header and queue the agent's calls. |
| 402 | The 1,000 free records are spent. | Check GET /v1/account, then move to Solo at $97 a month or Agency at $497 a month. See pricing. |
| Empty results | A wrong enum value, such as vp instead of VP, or a typo in a job function. | Check the exact strings with leadocean_list_enum_values. |
| 404 on enrich | We hold nothing for that person. | Nothing is charged. Search again with looser filters. |
| Export refused | Over 50,000 rows in one request or 500,000 in a day. | Split the export, or narrow the filters. Bulk CSV export is not on Free. |
FAQ
What is a B2B sales agent?
It is software that handles part of the sales workflow, usually prospecting, research and first-touch outreach, with little human input. Some vendors call it an AI SDR. The agent needs a contact data source it can query itself.
How many records does the agent spend?
Counting, listing filters and empty enrichments cost nothing. A search page of 25 costs 25 records. On the Free plan the whole loop in this guide spends about 30 of your 1,000.
Does LeadOcean send the emails?
No. LeadOcean is a data API and MCP server. It has no sequencer, dialer or CRM. Your agent or sequencer sends the outreach. Check each address's email_status first, because bounced emails are not refunded.
Where do I compare data sources for agents?
See B2B data for sales for how the options differ.
Give your sales agent a data source it can count before it spends
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →