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

How-to guide

How to Write 8 Pharma Sales Cold Emails for HCPs (and Build the List They Go To)

Eight copy-ready samples, and the three API calls that size the list, pull it and read the email status before you send.

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

TL;DR

  • Eight samples below, each under 90 words, each with one ask and no efficacy claim. Copy the structure, then swap in your own approved language.
  • The list takes about 30 minutes: one free count, one search of 100 rows, one status check.
  • A first test pull spends about 100 LeadOcean records. The count spends none.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY. The Free plan gives 1,000 records for life, no card, 5 requests a second.
  • curl and jq.
  • Your company's approved messaging and its medical, legal and regulatory sign-off process. These samples are structure, not approved copy.
  • A sequencer or mail client. LeadOcean returns the list. It does not send mail.

Step 1: Size the HCP list for free

Count first. A count costs no records and tells you if the filter is too narrow before you pull a row.

Pass count=true and limit=1 as query parameters. Filters go in the flat JSON body as arrays.

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 '{
    "title": ["Cardiologist", "Cardiology"],
    "industry": ["Hospitals and Health Care", "Medical Practices"],
    "country": ["US"]
  }' | jq '.meta'

Industry names are exact strings. Resolve them with leadocean_list_enum_values (MCP) or GET /v1/enums before you guess. The industry "Physicians" is a trap here: it is a thin slice, so check the count before you rely on it.

Step 2: Pull the first 100 rows

Pull one page of 100 and keep the cursor for the next. This is where records are spent: one per person returned.

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 '{
    "title": ["Cardiologist", "Cardiology"],
    "industry": ["Hospitals and Health Care", "Medical Practices"],
    "country": ["US"],
    "limit": 100
  }' > page1.json

jq '.meta' page1.json

One search pages to 10,000 rows. If meta.depthCapped is true, narrow the filters by city or employeeRange instead of walking further.

Step 3: Keep only mailable addresses

Read email_status before you send. LeadOcean does not refund bounced emails.

The count default already limits to verified, catch_all_valid and catch_all. In a search, ask by name. Run this body in place of Step 2, so you spend records only on mailable people.

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 '{
    "title": ["Cardiologist", "Cardiology"],
    "industry": ["Hospitals and Health Care", "Medical Practices"],
    "country": ["US"],
    "emailStatus": ["verified", "catch_all_valid"],
    "limit": 100
  }'

Sending to catch_all is a risk choice. Start with verified and catch_all_valid for a first send.

Step 4: Write the eight emails

Each sample has one reason to write, one fact about them and one small ask. None claims efficacy, safety or an off-label use. Merge fields use placeholders: {{first_name}}, {{practice}}, {{topic}}.

1. Peer-reviewed data, offered not pushed

text
Subject: {{topic}} data for {{practice}}

Dr. {{last_name}}, a new peer-reviewed paper on {{topic}} came out this
month. I can send the PDF and a one-page summary from our medical team.
Want it?

Jane Doe, Acme Pharma

2. Medical education invite

text
Subject: Dinner talk on {{topic}}, {{city}}

Dr. {{last_name}}, we host a small medical education talk on {{topic}} on
{{date}} in {{city}}. Eight seats left. Should I hold one for you?

Jane Doe, Acme Pharma

3. Medical science liaison intro

text
Subject: Quick intro from our MSL, {{first_name}}

Dr. {{last_name}}, our medical science liaison, Jane Doe, covers
{{region}}. She answers unsolicited scientific questions on {{topic}}.
Worth a 15-minute call?

4. Formulary and access help

text
Subject: Prior auth support for {{practice}}

Dr. {{last_name}}, your staff may spend hours on prior authorizations.
We offer a free support line for office teams. May I send the number to
your practice manager?

5. Clinical trial awareness

text
Subject: Trial site search, {{topic}}

Dr. {{last_name}}, we are looking for sites for a phase III study in
{{topic}}. If {{practice}} sees these patients, I can send the protocol
synopsis. Interested?

6. Speaker program

text
Subject: Speaking on {{topic}}?

Dr. {{last_name}}, your work on {{topic}} stood out. We are building a
regional speaker bench. Open to hearing the format and fee policy?

7. Patient resource offer

text
Subject: Patient education leaflets for {{practice}}

Dr. {{last_name}}, we print free patient leaflets on {{topic}}. I can
ship a box to {{practice}}. Which address should it go to?

8. Follow-up after no reply

text
Subject: Re: {{topic}} data for {{practice}}

Dr. {{last_name}}, closing the loop on the paper I mentioned. If it is
not relevant, say so and I will not write again.

Step 5: Map the pulled rows to merge fields

Turn the search JSON into a CSV your sequencer can read. A search row carries the name, the current role and email flags, but not the address itself.

bash
jq -r '.data[] | [
  .meta.source_ids.person_id,
  .profile_data.profile_first_name,
  .profile_data.profile_last_name,
  .contact_data.contact_current_experiences[0].company_name,
  .contact_data.email_status
] | @csv' page1.json > hcps.csv

The fourth column fills {{practice}}. {{topic}}, {{city}} and {{date}} come from your own campaign plan.

Step 6: Reveal the address for each row

Enrich each person_id with reveal_email set to true. One record per person found; a 404 costs nothing.

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": "PERSON_ID_FROM_HCPS_CSV", "reveal_email": true}' \
  | jq '.data.contact_data.contact_emails'

Each address carries its own status. Send to the first one whose status is verified or catch_all_valid. For a larger send, use POST /v1/exports: up to 50,000 rows a request and 500,000 a day. Bulk CSV export is not on Free.

What you get

A free count, run on 2026-10-21 through the LeadOcean MCP server:

json
{
  "total": 12260,
  "totalIsExact": true,
  "totalAll": 29613,
  "distinctCompanies": 1804,
  "credits": 0
}

Filters: title Cardiologist or Cardiology, industry Hospitals and Health Care or Medical Practices, country US. The 12,260 is the mailable count: verified, catch_all_valid and catch_all only. The 29,613 is the same filters with no email condition. Titles match as keywords, so scan a sample before you send.

A search row follows this response shape from the API reference, with placeholder values:

json
{
  "profile_data": { "profile_first_name": "Jane", "profile_last_name": "Doe" },
  "contact_data": {
    "has_email": true,
    "email_status": "verified",
    "contact_current_experiences": [{ "job_title": "Cardiologist", "company_name": "Acme Heart Clinic" }]
  },
  "meta": { "source_ids": { "person_id": "123456789" } }
}

Page with meta.nextCursor. Stop and narrow when meta.depthCapped is true.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keyCheck $LEADOCEAN_API_KEY is exported and the header name is exact.
429Above the plan's rate limit (5 a second on Free, 200 on Agency)Wait for the Retry-After header, then retry slower.
402Out of recordsFree is 1,000 records for life. See pricing.
Empty resultsIndustry or title string not an exact enum valueResolve with GET /v1/enums or leadocean_list_enum_values.
meta.depthCapped trueSearch reached 10,000 rowsNarrow by city, practice size or seniority.
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export or run it the next day.

FAQ

Can I send these without approval from my compliance team?

No. Treat them as structure. Run every email through your own medical, legal and regulatory review, and check the marketing rules for your market.

How many HCP records does this spend?

A count spends none. A first page of 100 spends about 100 records. An enrichment that finds nothing is free.

Does LeadOcean send the emails?

No. It returns the list and the email status. You send from your own sequencer or mail client. See best cold email software.

Where can I find more sample emails?

Build your HCP list, then send the eight emails

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

Get your free API key →