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

How-to guide

How to Measure and Raise Your Cold Email Response Rate (With the LeadOcean API)

Define the rate honestly, size a tight list for free, and send only to addresses worth sending to.

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

Your cold email response rate is replies divided by emails delivered, and the fastest way to raise it is to fix the list before you touch the copy. This guide defines the rate, sizes a tight segment for free, and pulls only addresses worth sending to.

TL;DR

  • Count replies against delivered emails, not sent emails, and track bounces as a separate number.
  • Narrow the list by title, function, size and country, and send only to verified addresses first.
  • It takes about 20 minutes and spends 25 LeadOcean records for the test page (the Step 4 cohorts add up to 200). Sizing queries cost nothing.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY. The Free plan has 1,000 records for life, no card, 5 requests a second.
  • curl and jq.
  • A sending tool that reports delivered, bounced and replied per email. Any sequencer that exports these counts works.

Step 1: Define the rate before you measure it

Use one formula and keep it fixed across campaigns, so numbers stay comparable.

text
delivered      = sent - bounced
response rate  = replies / delivered
positive rate  = positive replies / delivered
bounce rate    = bounced / sent

Sent is the wrong denominator. A list with 8% bounces looks like it has a worse response rate than it does, and the real problem is the list, not the copy. Log bounces and replies separately, and tag each reply as positive, negative or out of office.

Auto-replies and out-of-office messages are not responses. Strip them before you divide.

Step 2: Size a tight segment for free

A narrow list gets replies because the message fits the reader. Size candidates with a count call. It spends no records.

bash
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 '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "employeeRange": ["51-200"],
    "emailStatus": ["verified"]
  }' | jq '.meta'

count=true goes in the query string, not the JSON body, which rejects unknown fields. The body is flat JSON and every filter is an array of strings. meta.total is capped at 100,000.

In an AI client, the same check is the leadocean_count_leads MCP tool.

Step 3: Pick the email status you will send to

Deliverability decides how many emails reach a person at all. LeadOcean returns an email_status per address: verified, catch_all_valid, catch_all, risky, unknown, untested, invalid, role, disposable, spam_trap, abuse, derived or none.

Start with verified. Add catch_all_valid and catch_all once the first campaign shows a bounce rate you accept. There is no refund for bounced emails, so read the status before you send.

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"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "employeeRange": ["51-200"],
    "emailStatus": ["verified"],
    "limit": 25
  }' | jq '{next: .meta.nextCursor, rows: (.data | length)}'

This spends 25 records. Page further with the cursor from the response. One search pages to 10,000 rows, then meta.depthCapped is true: narrow the filters instead.

Before you send, check the three things that move the rate more than copy does.

  • Fit. Does the title own the problem you describe? A VP of Sales reads a pipeline email differently from a VP of Finance. Filter by jobFunction, not only by jobLevel.
  • Size. A message written for a 60-person company misses at 5,000 people. Use employeeRange to keep one message per size band.
  • Freshness. Titles change. The dataset is refreshed monthly and each record carries its own fetched_at date, so check it before a large send.

Step 4: Split into two cohorts and test one variable

Split the segment by one filter, send the same message, and compare reply rates. Seniority is a good first split because it changes who reads the email.

bash
for level in VP Director; do   # cohort A: VPs, cohort B: Directors; 100 each, 200 records
  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\":[\"$level\"],\"jobFunction\":[\"Sales & Business Development\"],\"country\":[\"US\"],\"emailStatus\":[\"verified\"],\"limit\":100}" \
    > "cohort_$level.json"
done

Change nothing else: same copy, same send window, same sender. With a few hundred emails per cohort, treat small gaps as noise. Do not call a winner on a difference of a couple of replies.

For a large send, export the segment from the Exports page in the app. It has a filter builder, a column picker, a price preview and a CSV download. You can also call POST /v1/exports, up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free.

Step 5: Log results and read them

Keep one row per cohort. Compare in this order: bounce rate first, then response rate, then positive rate.

text
cohort,sent,bounced,delivered,replies,positive,response_rate,positive_rate
vp_us_51_200,200,6,194,11,4,5.7%,2.1%

The row above is a layout example with placeholder numbers, not a benchmark. If bounce rate is above your tolerance, fix the list. If bounces are low and replies are low, fix the offer or the first line.

Step 6: Fix the weakest number

Read the three numbers in order, and change one thing per round.

  • Bounce rate high. Tighten emailStatus to verified, and drop role and risky addresses. Re-run the count to see the new list size.
  • Bounce low, response low. The list is reachable but the message misses. Narrow the segment further (add country or a smaller employeeRange) and rewrite the first line for that one group.
  • Response fine, positive low. You reach people who are not buyers. Move the title filter toward the person who owns the budget, for example from Manager to Director.

Repeat on the next 100 to 200 people from the same cursor. Stop when two rounds in a row show no gain. Keep the cohort table, because it is your own benchmark.

What you get

A free count on 2026-10-21 for VPs in Sales & Business Development, US, 51-200 employees, from the leadocean_count_leads MCP tool:

Filter setPeopleDistinct companies
Default mailable (verified, catch_all_valid, catch_all)18,56712,192
emailStatus: verified only4,5523,463
No email condition (totalAll)60,456not returned

Tightening to verified cuts the list by about three quarters. That is the trade: a smaller list with fewer bounces.

Response shape from the API reference, placeholder values (/v1/people/search returns data and meta):

json
{
  "success": true,
  "data": [
    {
      "profile_data": {
        "profile_full_name": "Jane Doe",
        "profile_headline": "VP Sales at Acme"
      },
      "contact_data": {
        "has_email": true,
        "email_status": "verified",
        "email_type": "work",
        "contact_current_experiences": [
          { "job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com" }
        ]
      },
      "meta": { "source_ids": { "person_id": "1234567" }, "fetched_at": "2026-10-01" }
    }
  ],
  "meta": { "count": 1, "limit": 25, "credits": 1, "nextCursor": "<cursor>" }
}

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keyCheck $LEADOCEAN_API_KEY and the header name.
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, or slow the loop.
402The plan is out of recordsFree has 1,000 for life. Upgrade or narrow the list. See pricing.
Empty dataA filter value is not an exact stringCheck leadocean_list_enum_values. jobLevel is VP, not vp.
400 on a countcount=true sent in the JSON bodyMove it to the query string.
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export by filter.

FAQ

What is a good cold email response rate?

It depends on your list, your offer and who you target, so your own history is the benchmark. Track your rate per cohort and improve against it. For outside figures, see cold email statistics.

Should I count open rate?

No. Opens are unreliable because some mail clients preload images. Count replies and positive replies against delivered emails.

Does a verified list raise the response rate?

It raises delivered volume, which protects your sender reputation and gives more people the chance to reply. Whether they do depends on the message.

How many records does a test cost?

Counts are free. Pulling one page of 25 people costs 25 records. The Free plan covers 1,000. Solo at $97 a month adds bulk export, and Agency at $497 a month suits teams that run many segments. See pricing.

How big should a test cohort be?

Big enough that one reply does not swing the rate. Start with 100 to 200 delivered emails per cohort, and treat gaps of a few replies as noise. Rerun the winner on a fresh slice before you scale it.

Where does this fit in a wider outbound process?

See B2B cold emailing for the process and cold email marketing tools for sending tools. More guides are on the blog.

Build a list worth replying to. Size it free, then pull it.

Free to start. No credit card. 1,000 records to spend whenever you like.

Get your free API key →