To get a websearch API, sign up with a search provider, create a key, and send a query over HTTPS. You get back JSON with titles, URLs and snippets. This guide shows that flow, then adds the part a websearch API cannot do: turning a result into a named person with a work email.
Provider details differ, so the websearch steps use a placeholder host. The LeadOcean steps are real requests against https://api.leadocean.io.
TL;DR
- A websearch API returns web pages. A B2B search API returns people and companies. Most outbound and research workflows need both.
- Takes about 20 minutes and spends 6 LeadOcean records of the 1,000 free ones. Counts cost nothing.
- Websearch gets you the signal (a funding post, a launch). LeadOcean gets you the VP behind it.
Prerequisites
- An account with a websearch provider. Read its docs for the endpoint, auth header and rate limit.
- A LeadOcean account. The free plan gives 1,000 records one-off, no card: register here.
curlandjq.
export SEARCH_API_KEY="paste-your-search-key-here"
export LEADOCEAN_API_KEY="paste-your-leadocean-key-here"Step 1: Decide which kind of search you need
Pick the API by the shape of the answer you want. This one choice saves most of the rework.
| You want | You need | Example question |
|---|---|---|
| Pages, snippets, news | A websearch API | "What did Acme announce this month?" |
| People at companies | A B2B people search API | "Which VPs of Sales work in Canada?" |
| Both, joined | Websearch, then B2B search | "Who runs sales at the company that just raised?" |
A websearch API cannot tell you who the VP of Sales is with a verified email. It can tell you which page mentions them. Do not ask one tool to do the other's job.
Step 2: Create the websearch key
Sign up with the provider and open its dashboard. Generate a key and copy it once. Store it in an environment variable, never in code or a repo.
Check three things in the docs before you write code. These decide whether the API fits your use.
- The auth header name and format.
- The rate limit, in requests per second or per minute.
- What a call costs: per request, per result, or per credit.
Providers price differently, so compare on the cost of your real volume, not the headline number.
Step 3: Make the first websearch call
Send one query and read the raw JSON before you build anything on it. The host and parameter names below are placeholders: take the real ones from your provider's docs.
curl -s -X POST "https://search.example.com/v1/search" \
-H "Authorization: Bearer $SEARCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Acme Series B funding announcement",
"country": "us",
"num_results": 5
}' | jq '.results[] | {title, url, snippet}'Most providers return a ranked list with a title, a URL and a snippet per hit. The output below is an illustration of that common shape, not a real response.
{
"title": "Acme raises Series B to expand its platform",
"url": "https://news.example.com/acme-series-b",
"snippet": "Acme, a workflow software company, announced a Series B round..."
}Pull the company domain out of the hit (here, acme.com). That domain is the key into the next step.
Step 4: Size the people list at that company for free
Send count=true and limit=1 as query parameters and LeadOcean returns a total without spending a record. The filters go in a flat JSON body, and every filter is an array of strings.
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": ["acme.com"],
"jobLevel": ["VP", "C-Team"]
}' | jq '.meta'meta.total is capped at 100,000. Enum values are exact strings: VP and C-Team work, vice president returns nothing. List the allowed values with GET /v1/enums/job_level.
Step 5: Pull the people and enrich one
Search the same filter without count, then enrich the person you want. Search rows are thin and carry flags only. Enrich takes exactly one of linkedin_url, email, phone or person_id.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": ["acme.com"],
"jobLevel": ["VP", "C-Team"],
"limit": 5
}' > people.json
PID=$(jq -r '.data[0].meta.source_ids.person_id' people.json)
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\": \"$PID\", \"reveal_email\": true}"The search spends 5 records, one per person returned. The enrich spends 1. If we hold nothing for that person you get a 404 and no charge.
To page further, pass meta.nextCursor back as cursor, unchanged. One search pages to 10,000 rows.
Step 6: Join both in one script
Glue the two calls together once, then reuse it. Save this as people-for-hit.sh and run it with a domain. It takes a domain from a websearch hit and returns a free count of VP and C-Team people there before it spends anything.
#!/usr/bin/env bash
DOMAIN="$1"
TOTAL=$(curl -s -X POST \
"https://api.leadocean.io/v1/people/search?count=true&limit=1" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"domain\": [\"$DOMAIN\"], \"jobLevel\": [\"VP\", \"C-Team\"]}" \
| jq -r '.meta.total')
echo "$DOMAIN: $TOTAL leadership people on file"Set a budget before you loop over many hits. A count is free, so run it for every hit and only pull rows where the total is small enough to read. Keep the websearch call and the people call separate so you can swap either provider later.
Two habits keep this cheap. Cache the websearch result by query, so a repeated query does not cost a second call. Cache the LeadOcean record by person_id, because a record you already hold does not need a second pull.
Step 7: Let an agent do both
If you use an AI client, skip the glue code. The hosted MCP server at https://api.leadocean.io/mcp signs in with OAuth, so there is no key to paste. It has 13 tools, and leadocean_count_leads, leadocean_count_companies, leadocean_list_filters and leadocean_list_enum_values are free.
Using web search, find the company that announced a Series B this week.
Take its domain. Count VPs and C-Team people there with leadocean_count_leads.
If the count is under 50, show me the first 5 and tell me how many records that spent.Web search comes from your client. People data comes from LeadOcean. The agent should count first and spend records only after you see the total.
What you get
The free MCP tool leadocean_count_leads ran on 2026-10-21 for VPs in Sales & Business Development in Canada. It counts mailable people by default, meaning a verified, catch_all_valid or catch_all email.
{
"query": "jobLevel VP, jobFunction Sales & Business Development, country CA",
"total": 5574,
"totalIsExact": true,
"totalAll": 18800,
"distinctCompanies": 3873,
"credits": 0
}That is 5,574 mailable VPs of Sales in Canada on 2026-10-21. Without the email filter the same filters match 18,800 people across 3,873 employers. It is a mailable count, not everyone who matches the other filters.
A record-level response has the shape below (response shape from the API reference, placeholder values). Contact points appear only after enrich with reveal_email:
{
"success": true,
"data": {
"profile_data": { "name": "Jane Doe", "title": "VP Sales", "company": "Acme" },
"contact_data": {
"has_email": true,
"has_phone": true,
"email_status": "verified",
"contact_emails": [
{ "email": "jane.doe@acme.com", "type": "work", "status": "verified" }
],
"contact_phones": [
{ "phone": "+14155550133", "type": "mobile", "priority": 1 }
]
}
},
"meta": { "source": "leadocean" }
}Read email_status before you send anything. Each record carries its own fetched_at date, and the dataset refreshes monthly.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Re-export $LEADOCEAN_API_KEY and check the header name |
| 402 | Out of records. On Free the 1,000 are a one-off allowance | Move to Solo at $97 a month, or lower limit |
| 429 | Above the plan's rate limit (5 requests a second on Free, 200 on Agency) | Honour the Retry-After header and back off |
Empty data | A filter value is not an exact enum string | List values with GET /v1/enums/job_level and copy one |
meta.depthCapped is true | One search pages to 10,000 rows | Narrow the filters and run several smaller searches |
| Export refused | Over 50,000 rows a request or 500,000 a day | Split the export into several requests |
FAQ
What is the difference between a websearch API and a B2B data API?
A websearch API returns ranked web pages. A B2B data API returns structured people and company records. See what a websearch API is for the first, and API for the general term.
Does LeadOcean offer a websearch API?
No. LeadOcean is a people and company data API with a hosted MCP server. It does not return web pages. Pair it with the search provider of your choice.
Is a websearch API a REST API?
Most are. You send an HTTPS request and read JSON. See RESTful API for what that means.
How much does LeadOcean cost?
Free is $0 with 1,000 records for life and no card. Solo is $97 a month, Agency is $497 a month, and Platform is $1,997 a month. Paid plans have a fair-use pace, not credits. See pricing.
Add a people layer to your search pipeline with a free API key
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →