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

How-to guide

How to Design a Personal Sales Email That Feels Written for One Person (From Real Profile Data)

An email feels personal when one line could only be true of the reader. Pull the facts first, pick one, then write around it.

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

A personal sales email contains one fact that is true of the reader and of nobody else on your list. Everything else in the email serves that line. This guide shows how to pull candidate facts with the LeadOcean API, choose one, and build the email around it.

TL;DR

  • Count a small segment for free, pull five people, enrich one for career history, then write one email around one fact.
  • It takes about 20 minutes and spends about 6 records, inside the free 1,000.
  • If no fact in the data is specific, do not fake one. A generic email with a merge tag is not personal.

Prerequisites

  • A free LeadOcean key in $LEADOCEAN_API_KEY (start free, no card: see pricing).
  • curl and jq.
  • Any inbox or sending tool. LeadOcean returns data only. It has no sequencer or inbox.
  • Related reading: the email templates that use the same fields, and inbox setup. More guides are in the blog hub.

Step 1: Pick a segment and size it for free

Choose a narrow segment first. A narrow segment makes the shared context obvious, which is what makes the email feel written for one person. Counting costs nothing.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "employeeRange": ["201-500"],
    "limit": 1
  }' | jq '.meta | {total, distinctCompanies}'

On 2026-10-21 the free MCP tool leadocean_count_leads returned 12,281 people with a verified, catch_all_valid or catch_all email, across 6,321 companies. With no email condition the same filters matched 35,380. Say which number you mean when you quote one.

Step 2: Pull five people

One search page of 5 is 5 records. Ask only for addresses worth sending to.

bash
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"],
    "employeeRange": ["201-500"],
    "emailStatus": ["verified"],
    "limit": 5
  }' > people.json

jq -r '.data[] | [.meta.source_ids.person_id,
  .profile_data.profile_full_name,
  .contact_data.contact_current_experiences[0].job_title,
  .contact_data.contact_current_experiences[0].company_name,
  .contact_data.email_status] | @tsv' people.json

Search is a flat JSON body, filters are arrays, and limit runs 1 to 100. Page on with cursor when you want more.

Step 3: Enrich one person for candidate facts

Search gives you title and company. Enrich adds career history: past roles, schools, certifications and awards. These are the facts a stranger would not guess. Enrich takes exactly one of linkedin_url, email, phone or person_id. Use the person_id from the first column of Step 2.

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 '{"person_id": "1234567"}' > person.json

jq '.data | {now: .contact_data.contact_current_experiences[0],
     past: .resume_data.experiences[0:2],
     school: .resume_data.educations[0:1],
     awards: .resume_data.awards[0:1]}' person.json

A person we hold nothing for is a 404 and costs nothing. Past employers carry no company_id yet, so compare them by name. Each section appears only when held.

Step 4: Score the facts and choose one

Not every fact is personal. Use this test: could you paste the line into an email to the person next to them on the list? If yes, it is a merge tag, not a personal line.

text
Fact                          Passes the test?   Why
Title: VP Sales               No                 Everyone in the segment has it
Company size: 201-500         No                 Shared by the whole segment
Past role: Head of Sales,     Yes                Specific to this person's path
  previous employer (by name)
Award in resume_data.awards   Yes                Rare, recent and checkable
School                        Maybe              Only if you share it or it ties to the ask

Pick one fact. Two facts in one email read as research done by a script.

Step 5: Write around the one fact

Put the fact in the first sentence, tie it to one problem, and ask one question. Keep the email under 90 words.

text
Subject: From {{past_company}} to {{company}}

Hi {{first_name}},

You moved from {{past_title}} at {{past_company}} to running sales at {{company}}.
Teams that make that jump often rebuild how they source pipeline in the first year.

I work on {{problem}}. Is that on your list this quarter?

{{your_name}}

Fill the variables in your own script or sending tool. Read every email aloud once. If a line only works because of a variable, cut it.

Step 6: Check the email status before sending

Read email_status on every row. We do not refund bounces.

bash
jq -r '.data[] | select(.contact_data.email_status=="verified") | .meta.source_ids.person_id' people.json | wc -l

What you get

Response shape from the API reference, with placeholder values (not a real person):

json
{
  "success": true,
  "data": [
    {
      "profile_data": { "profile_full_name": "Jane Doe" },
      "contact_data": {
        "has_email": true,
        "email_status": "verified",
        "contact_current_experiences": [
          { "job_title": "VP of Sales", "company_name": "Acme", "company_domain": "acme.com" }
        ]
      },
      "meta": { "source_ids": { "person_id": "1234567" } }
    }
  ],
  "meta": { "count": 1, "limit": 5, "nextCursor": null }
}

Enrich adds resume_data with experiences[], educations[], certifications[] and awards[], each present only when held.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keyCopy the key from app.leadocean.io and export it again
429Above the plan rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, or move to a higher plan
402Records spent (Free has 1,000 for life)Check GET /v1/usage, then pick a plan on pricing
Empty resultsA bad enum value, such as vp instead of VP for jobLevelCheck exact strings with leadocean_list_enum_values
404 on enrichNothing held for that personNo cost. Try another person_id
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export. Bulk CSV is not on Free

FAQ

How many facts should one email use?

One. A second fact turns research into a list. Save it for the follow-up.

Is a merge tag for first name and company personal?

No. Both are in every record on your list. Treat them as formatting.

What if the enriched record has no usable fact?

Send a plain, short email and say why you are writing. See the template guide. Do not invent a hook. Pace and tone matter more than fake detail; for sending from a work platform, see Pardot sending from a salesperson.

How many records does this cost?

About 6 here. Counting costs nothing, and an enrichment that finds nobody costs nothing.

Pull the one fact that makes your next email personal

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

Get your free API key →