Pre-Black Friday: 20% off, for as long as you stayEARLYBFon Solo and AgencyEnds Nov 28Start free

How-to guide

How to Outsource B2B Lead Generation (and Audit the Agency's List)

Size the market, brief the agency with filters, pilot on 100 rows and verify what they send. About 125 LeadOcean records.

Get your free API key →Free to start. No credit card. 1,000 records to spend whenever you like.

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.
  • curl and jq, or the LeadOcean MCP server at https://api.leadocean.io/mcp in 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.

bash
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.

json
{
  "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.

bash
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.json

This 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.

bash
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.

CheckPass lineSource
Title and company match90% of 25Enrich response
Email not invalid or spam_trap95% of 25email_status
Overlap with control sampleAny, as a sanity checkcontrol.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.

yaml
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_fee

For 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.

json
{
  "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):

json
{
  "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

ErrorCauseFix
401Missing or wrong x-api-keyCheck $LEADOCEAN_API_KEY is exported and sent as the x-api-key header
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, or slow the loop
402The 1,000 free records are spentUpgrade (Solo is $97 a month) or narrow the pilot
Empty resultsA bad enum value, such as "Vice President" instead of "VP"Look it up with leadocean_list_enum_values
Search stops at 10,000 rowsmeta.depthCapped is trueNarrow the filters instead of paging further
Export refusedOver 50,000 rows a request or 500,000 a daySplit 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 →