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=... curlandjq.- 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.
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.
curl -s "https://api.leadocean.io/v1/companies/acme.com/people?limit=10" \
-H "x-api-key: $LEADOCEAN_API_KEY" > acme_people.jsonEach 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.
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.jsonThe 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.
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.
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.
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.
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.
| Item | Owner | Where it lives |
|---|---|---|
audience.json filter set | Marketing drafts, sales approves | Shared repo |
| Account domain list | Sales | Same repo |
| Templates by role | Marketing | Mail tool |
| Exception list (do not email) | Sales | Mail tool suppression list |
| Email status rule | Both | audience.json |
| Monthly recount | Marketing ops | Calendar 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).
| jobFunction | Mailable | All matching | Distinct companies |
|---|---|---|---|
| Advertising & Marketing | 49,523 | 125,091 | 24,142 |
| Sales & Business Development | 129,494 | 350,517 | 58,121 |
Raw tool output for the marketing row, trimmed:
{
"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
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Check $LEADOCEAN_API_KEY is exported in this shell. |
| 429 | Above your plan's rate limit (5 a second on Free, 200 on Agency) | Wait for the Retry-After header, then retry. |
| 402 | Records spent | Free is 1,000 for life. Move to Solo ($97 a month) or Agency ($497 a month). |
| Empty results | Enum value spelled wrong, such as Marketing or United States | Use exact strings: Advertising & Marketing, US. Check GET /v1/enums. |
| Export refused | Over 50,000 rows a request or 500,000 a day, or on the Free plan | Split 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
- Template library: personalized sales email templates
- How to personalize outbound sales emails
- 11 personalized sales email letters with examples
- Pricing
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 →