A B2B lead generation agency sells you a list, meetings, or both. The risk is that you cannot see what they sourced, so you pay for a black box. This guide gives you a brief an agency cannot fudge and a way to check their output yourself.
TL;DR
- Size your market first with a free count, so the agency's quote is checked against a real number.
- Pilot on 100 rows and spot-check 25 of them through an API. Total cost is about 125 LeadOcean records.
- Setup takes about 2 hours. The pilot runs 2 to 4 weeks. Keep the agency only if the pilot passes your own thresholds.
Prerequisites
- A LeadOcean account on the Free plan (1,000 records for life, no card, 5 requests a second). Sign up at app.leadocean.io.
- An API key stored as
$LEADOCEAN_API_KEY. curlandjq, or the LeadOcean MCP server athttps://api.leadocean.io/mcpin Claude.- One sentence describing your buyer: title, department, company size, country.
Step 1: Size the market before you talk to anyone
Run a free count so you know how many buyers exist. An agency that promises 5,000 qualified leads from a market of 54 is selling you something else.
curl -s "https://api.leadocean.io/v1/people/search?count=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP", "C-Team"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"industry": ["Computer Software"],
"limit": 1
}' | jq '.meta'count=true is a query parameter. It spends no records. Note that meta.total is capped at 100,000.
Step 2: Write the brief as filters, not adjectives
"Decision makers at growing SaaS companies" cannot be audited. A filter set can. Write the brief as the exact fields you will check later.
{
"jobLevel": ["VP", "C-Team"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"industry": ["Computer Software"],
"emailStatus": ["verified", "catch_all_valid"]
}Enum values are exact strings. Resolve them with the free leadocean_list_enum_values MCP tool before you send the brief. Then add the delivery terms: rows per week, the email status you will accept, and a rule that every row carries a source and a date.
Step 3: Pull a control sample of 100 rows
Fetch 100 people from the same filters yourself. This is your yardstick. If the agency's sample looks nothing like it, ask why.
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jobLevel": ["VP", "C-Team"],
"jobFunction": ["Sales & Business Development"],
"country": ["US"],
"employeeRange": ["51-200"],
"industry": ["Computer Software"],
"limit": 100
}' > control.jsonThis spends up to 100 records. Page with cursor if you need more. One search pages to 10,000 rows at most.
Step 4: Spot-check 25 rows from the agency's pilot list
Take 25 random rows from the agency's file and enrich each by linkedin_url or email. Compare title, company and email status to what they claimed.
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": "https://www.linkedin.com/in/jane-doe-example"}'Enrich takes exactly one of linkedin_url, email, phone or person_id. A person we hold nothing for is a 404 and costs nothing. Set pass thresholds before you look: for example, 90% of titles match and 95% of emails are not invalid.
Step 5: Score the pilot and decide
Count matches in a spreadsheet. Check that title and company still match, that the email status is what they promised, and that no row is on your do-not-contact list. Read email_status before sending. Bounced emails are not refunded.
| Check | Pass line | Source |
|---|---|---|
| Title and company match | 90% of 25 | Enrich response |
Email not invalid or spam_trap | 95% of 25 | email_status |
| Overlap with control sample | Any, as a sanity check | control.json |
If the agency fails, you lose 2 to 4 weeks, not a year-long retainer.
Step 6: Put the pilot terms in writing
Turn the thresholds into a contract schedule. Agencies sell three models: a list only, appointments set, or a full outbound program. Each needs different terms, and you can audit all three with the same checks.
pilot:
duration_weeks: 3
rows_delivered: 100
filters: brief.json # the Step 2 filter set
email_status_allowed: [verified, catch_all_valid]
per_row_fields: [title, company_domain, email, source, fetched_date]
acceptance:
title_company_match: 0.90 # of the 25-row spot check
email_not_invalid: 0.95
duplicates_vs_do_not_contact: 0
remedy:
below_threshold: replace_rows_free
second_failure: terminate_no_feeFor a list-only deal, pay per accepted row. For appointments, define a qualified meeting in the contract: who attended, their title, and the date. For a full program, ask who owns the sending domains, because you will want them if you leave.
Ask where each row came from. A fair answer names a data provider or a first-party source. "Proprietary database" with no field-level detail is a reason to run the Step 4 check on 50 rows, not 25.
Step 7: Decide on a retainer or a cheaper path
If the pilot passes, move to a month-to-month retainer with the same acceptance rules. If it fails, compare the cost with doing it yourself. A Solo plan is $97 a month and an Agency plan is $497 a month (see pricing). Paid plans have a fair-use pace, not credits.
You still need sending infrastructure and someone to write and reply. That is the part an agency really sells. If you already have it, a data API and one SDR may beat a retainer.
What you get
The Step 1 filters, counted with the free LeadOcean MCP leadocean_count_leads tool on 2026-10-21. It counted only addresses worth sending to (verified, catch_all_valid or catch_all), so the total is a mailable audience, not everyone.
{
"total": 54,
"totalIsExact": true,
"totalAll": 205,
"distinctCompanies": 30,
"credits": 0
}54 mailable people at 30 companies, out of 205 with no email condition. A market this size does not need an agency to "generate" thousands of leads.
A single search row has this shape (response shape from the API reference, placeholder values):
{
"success": true,
"data": [
{
"profile_data": {
"profile_full_name": "Jane Doe",
"profile_url": "https://www.linkedin.com/in/jane-doe-example"
},
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_current_experiences": [
{ "job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com" }
]
},
"meta": { "source_ids": { "person_id": "p_0000000" }, "fetched_at": "2026-10-01" }
}
],
"meta": { "count": 1, "nextCursor": "c_0000000" }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key | Check $LEADOCEAN_API_KEY is exported and sent as the x-api-key header |
| 429 | Above the plan's rate limit (5 a second on Free, 200 on Agency) | Honor Retry-After, or slow the loop |
| 402 | The 1,000 free records are spent | Upgrade (Solo is $97 a month) or narrow the pilot |
| Empty results | A bad enum value, such as "Vice President" instead of "VP" | Look it up with leadocean_list_enum_values |
| Search stops at 10,000 rows | meta.depthCapped is true | Narrow the filters instead of paging further |
| Export refused | Over 50,000 rows a request or 500,000 a day | Split the export; bulk CSV is not on Free |
FAQ
When does an agency beat doing it in-house?
When you lack the SDR capacity or the deliverability setup, not when you lack data. Data is a commodity you can check. Sending infrastructure and reply handling are the real work you are buying.
What should I ask an agency before signing?
Ask for the filter set, the data source per row, the email status policy and a 100-row pilot. Refuse retainers over 3 months before the pilot passes.
Can I buy only the list and skip the agency?
Yes. Search and export the list yourself. See outbound lead generation for how the list feeds sequences, and pricing for plan limits.
How does this fit the wider funnel?
The agency owns top-of-funnel outreach. You still own qualification and follow-up. The lead generation funnel shows where the handoff sits, and predictive lead generation covers scoring who to target first.
Does the first part cost anything?
No. Sizing the market with count=true spends no records. Only the 100-row control sample and the 25 enrichments do. Browse more guides on the blog.
Check your agency's list before you pay for it
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →