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

How-to guide

How to Align Sales and Marketing Email with 7 Personalization Strategies (Using the LeadOcean API)

Alignment fails when two teams email two different lists. Put one filter set under both, then personalize from fields you can query.

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

Sales and marketing email drifts apart when each team builds its own list. The fix is one saved audience definition that both teams read, and personalization drawn from fields you can query.

This is the short, technical version. Each strategy has a request you can run.

TL;DR

  • Seven strategies, each tied to a LeadOcean filter or field: shared audience, shared accounts, role split, career history, company facts, email status gating, and a monthly recount.
  • Takes about 30 minutes the first time. Counting is free. The example spends about 22 records.
  • LeadOcean supplies the data. It has no sequencer or CRM, so send from your own tools.

Prerequisites

  • A LeadOcean account. The Free plan has 1,000 records for life, no card, 5 requests a second.
  • An API key in your shell: export LEADOCEAN_API_KEY=...
  • curl and jq.
  • One written sentence from each team on who the buyer is. Disagreement here is the real alignment problem.
  • A mail tool or sequencer that both teams can use.

Step 1: Write one audience definition both teams use

Strategy 1: a single filter set, stored in a repo or a shared doc, that sales and marketing both query. Count it before anyone writes copy. Counting is free.

Example: US VPs in marketing.

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": ["Advertising & Marketing"],
    "country": ["US"],
    "limit": 1
  }' | jq '.meta'

count is a query parameter, not a body field. meta.total is capped at 100,000. Save the JSON body as audience.json. When the definition changes, the file changes, and both teams see the diff.

Step 2: Share one account list, not two

Strategy 2: marketing runs the campaign on a list of domains, and sales works the same domains. Pull everyone at one account so a rep sees who marketing already emailed. Use a placeholder domain: acme.com.

bash
curl -s "https://api.leadocean.io/v1/companies/acme.com/people?limit=10" \
  -H "x-api-key: $LEADOCEAN_API_KEY" > acme_people.json

Each person returned counts as one record. The endpoint stops at 10,000 rows. Keep the domain list in the same repo as audience.json.

Step 3: Split the message by role, not by team

Strategy 3: at one account, a VP of Sales and a VP of Marketing care about different things. Run two searches with the same domain and different jobFunction values, then write one angle for each.

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 '{
    "domain": ["acme.com"],
    "jobLevel": ["VP", "Director"],
    "jobFunction": ["Sales & Business Development", "Advertising & Marketing"],
    "limit": 10
  }' > acme_roles.json

The body is flat JSON. Filters are arrays, limit runs 1 to 100, and you page with cursor. Enum values are exact strings, so check them with GET /v1/enums or the leadocean_list_enum_values MCP tool.

Step 4: Personalize from career history

Strategy 4: one line about a past employer or role beats a first-name merge. Enrich one person by person_id and read the history. Since October 2026 enrich returns past roles, education, certifications and awards.

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_STEP_3", "reveal_email": true}' \
  | jq '{current: .data.contact_data.contact_current_experiences, past: .data.resume_data.experiences}'

Enrich takes exactly one of linkedin_url, email, phone or person_id. Each past role carries job_title, company_name, start_date and end_date. Past employers have no company_id yet, so match them by name. A person we hold nothing for is a 404 and costs nothing.

Step 5: Personalize from company facts

Strategy 5: use the account, not the person, when the person has little history. POST /v1/companies/enrich takes domain or linkedin_url.

bash
curl -s -X POST "https://api.leadocean.io/v1/companies/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "acme.com"}' \
  | jq '{data: .data.company_data, tech: .data.company_detected_technologies}'

A template line could read: "Teams your size usually run {{tech_a}} next to {{tech_b}}. Is that true for you?" Marketing owns the template. Sales owns the exception list.

Step 6: Gate on email status so sales is not cleaning up after marketing

Strategy 6: both teams send only to addresses worth sending to. Add emailStatus to the shared definition.

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"],
    "emailStatus": ["verified", "catch_all_valid", "catch_all"],
    "limit": 1
  }' | jq '.meta'

The MCP count tool applies those three statuses by default. Bounces are not refunded, so read email_status on every record before it enters a sequence.

Step 7: Recount monthly and export the same file for both teams

Strategy 7: the dataset refreshes monthly. Rerun the count on the first of the month. If the number moved, tell both teams, then export once. Bulk CSV export is not on Free; it is included on Solo and Agency.

bash
curl -s -X POST "https://api.leadocean.io/v1/exports" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "shared-audience-2026-11",
    "filters": {"jobLevel": ["VP"], "jobFunction": ["Advertising & Marketing"],
                "country": ["US"], "emailStatus": ["verified"]},
    "limit": 5000,
    "preset": "full"
  }'

An export takes up to 50,000 rows a request and 500,000 a day. The app at app.leadocean.io has an Exports page with the same filters and a price preview if you prefer clicking.

Who owns what

Alignment is a list of owners, not a meeting. Use this split as a starting point.

ItemOwnerWhere it lives
audience.json filter setMarketing drafts, sales approvesShared repo
Account domain listSalesSame repo
Templates by roleMarketingMail tool
Exception list (do not email)SalesMail tool suppression list
Email status ruleBothaudience.json
Monthly recountMarketing opsCalendar reminder

Every change to the filter set goes through review, the same as code. If sales wants a new title in the audience, it is a one-line diff that marketing can see.

Write the personalization line from one field only. A role angle from Step 3, a career line from Step 4 or a company line from Step 5. Two fields in one email reads like a dossier. Leave a person out of the batch when the field you need is empty.

What you get

Output of the free leadocean_count_leads MCP tool on 2026-10-21. It spent 0 records. The filter was jobLevel VP, country US, mailable addresses only (verified, catch_all_valid or catch_all).

jobFunctionMailableAll matchingDistinct companies
Advertising & Marketing49,523125,09124,142
Sales & Business Development129,494350,51758,121

Raw tool output for the marketing row, trimmed:

json
{
  "total": 49523,
  "totalIsExact": true,
  "totalAll": 125091,
  "distinctCompanies": 24142,
  "credits": 0,
  "facets": { "seniority": [{ "value": "vp", "count": 49523 }] }
}

The Sales row's distinct-company figure is a close estimate, not exact (distinctCompaniesIsExact was false; it is exact below 40,000). Its total is above 100,000, so the REST count=true call would return a capped meta.total of 100,000 for that filter set. Narrow it by employeeRange or industry before you export.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported in this shell.
429Above your plan's rate limit (5 a second on Free, 200 on Agency)Wait for the Retry-After header, then retry.
402Records spentFree is 1,000 for life. Move to Solo ($97 a month) or Agency ($497 a month).
Empty resultsEnum value spelled wrong, such as Marketing or United StatesUse exact strings: Advertising & Marketing, US. Check GET /v1/enums.
Export refusedOver 50,000 rows a request or 500,000 a day, or on the Free planSplit the export by filter, or upgrade.

FAQ

How many records does this guide spend?

About 12: 10 for the sample search page and 2 for two enrichments. Counts, 404s and empty enrichments are free.

Can LeadOcean send the emails?

No. LeadOcean is data only. It has no sequencer, dialer or CRM. Send from your own mail tool.

Where should the shared audience file live?

In a repo or shared doc both teams can edit, with changes reviewed. The file is the agreement.

Do I need the API, or can I use the app?

The app has an Exports page with a filter builder and column picker. The API is better when the definition must live in code.

How fresh is the data?

The dataset refreshes monthly. Each record also carries its own fetched_at date.

Keep reading

Put one audience under both teams. Start free.

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

Get your free API key →