TL;DR
- Three workflows, one project folder: size territories, audit account coverage, flag job changes. Each is a prompt plus a few API calls.
- It takes about 30 minutes and spends about 70 of your 1,000 free records: 50 for the coverage audit and 20 for the job-change check. Sizing costs nothing.
- Claude Code reads and writes CSV files. It does not touch your CRM unless you connect a CRM tool yourself, so the output is a file you review and import.
Prerequisites
- A LeadOcean account and API key from app.leadocean.io. The free plan has no card and 1,000 records, one-off.
- The key in your shell as
$LEADOCEAN_API_KEY. - Claude Code installed, plus
curlandjq. - A CRM account export as
accounts.csvwith adomaincolumn andcontacts.csvwithname,title,linkedin_url. Any CRM can produce both.
export LEADOCEAN_API_KEY="paste-your-key-here"
mkdir revops && cd revopsStep 1: Give Claude Code the rules and the data
Put your territory definition in a CLAUDE.md file. Claude Code's memory docs describe it as persistent instructions read at the start of each session. Use exact filter values, not prose.
## RevOps project
### Territories
- West: hqCountry US, hqState California, Washington, Colorado
- East: hqCountry US, hqState New York, Massachusetts, Virginia
- Segment: employeeRange 51-200, industry Software Development
### Rules
- Use the leadocean MCP server. Run a free count before any call that spends records.
- Say how many records a call will spend before you make it. Wait for my go-ahead.
- Never write to the CRM. Output CSV files only.Then add the hosted MCP server. Claude Code's docs say to run /mcp in a session to sign in to a remote server with OAuth, so no key goes into the chat.
claude mcp add --transport http leadocean https://api.leadocean.io/mcp
claude/mcpPick leadocean, approve the sign-in and confirm it lists 13 tools. Seven of them never spend records, including both count tools.
Step 2: Size every territory for free
Count companies before you cut territories. The company count tool is free, exact and returns a breakdown by HQ state, so one call shows whether a split is balanced.
Run leadocean_count_companies for the segment in CLAUDE.md: hqCountry US,
employeeRange 51-200, industry Software Development, hasMailableContacts true.
Show the total and the top 10 HQ states. Do not call anything that spends records.The same count over REST is GET /v1/companies/count. It takes the company-search filters.
curl -s "https://api.leadocean.io/v1/companies/count?hqCountry=US&employeeRange=51-200&industry=Software%20Development&hasMailableContacts=true" \
-H "x-api-key: $LEADOCEAN_API_KEY" | jq '{total, state: .facets.hq_state[:5]}'To size the buyers inside those accounts, count people. A people count carries meta.distinctCompanies, the number of employers the matched people span.
Run leadocean_count_leads with country US, employeeRange 51-200, industry
Software Development, jobLevel VP, jobFunction Sales & Business Development,
facets false. Report total, totalAll and distinctCompanies.Step 3: Audit account coverage
Coverage is how many of your CRM accounts have at least one reachable buyer on file. Pull a few people per account for a sample of accounts, then let Claude Code mark the gaps.
GET /v1/companies/{domain}/people lists the people held at one company, one record per person returned. Keep limit small. The endpoint stops at 10,000 rows per company.
head -11 accounts.csv | tail -10 | cut -d, -f1 > sample.txt
while read -r DOMAIN; do
curl -s "https://api.leadocean.io/v1/companies/$DOMAIN/people?limit=5" \
-H "x-api-key: $LEADOCEAN_API_KEY" \
| jq -c --arg d "$DOMAIN" '{domain: $d, people: .data}'
done < sample.txt > coverage.jsonl
wc -l coverage.jsonlThat is 10 accounts at up to 5 people each, so 50 records at most. A company we hold nobody for returns a 404 and costs nothing.
Read coverage.jsonl and accounts.csv. Write coverage.csv with columns:
domain, people_found, has_vp_or_above, has_work_email, gap.
Set gap to "no buyer on file" when nobody is at director level or above.
Do not guess. Leave a field empty when the record does not show it.Step 4: Flag job changes
Stale contacts are the main source of CRM decay. Enrich returns the current role in contact_data.contact_current_experiences[] and, since October 2026, career history in resume_data. Compare the current employer with the one in your CRM.
Enrich takes exactly one of linkedin_url, email, phone or person_id. You have LinkedIn URLs in the export, so use those.
head -21 contacts.csv | tail -20 | while IFS=, read -r NAME TITLE LINKEDIN; do
curl -s https://api.leadocean.io/v1/people/enrich \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d "{\"linkedin_url\": \"$LINKEDIN\"}" \
| jq -c --arg n "$NAME" --arg t "$TITLE" '{crm_name: $n, crm_title: $t, now: .data.contact_data.contact_current_experiences, past: .data.resume_data.experiences}'
done > roles.jsonlRead roles.jsonl. For each row compare crm_title and the employer in the CRM
with the current role. Write job_changes.csv with columns: crm_name, crm_title,
current_title, current_company, status (same, changed, unknown), evidence.
Say "unknown" when the record has no current role. Past employers carry no
company_id yet, so match on company name only and flag fuzzy matches.That is 20 records at most. Review job_changes.csv by hand, then import the changed rows through your CRM's own import tool. LeadOcean is a data source, not a CRM, so it does not sync back by itself.
Step 5: Save the workflows as reusable commands
Claude Code can run a saved prompt again next quarter. Store each step's prompt in a file and call it from a session, so a new RevOps hire repeats the same audit.
mkdir -p prompts
cat > prompts/coverage-audit.md <<'PROMPT'
Run the account coverage audit from CLAUDE.md on accounts.csv.
Count first with leadocean_count_companies and tell me the record cost.
Pull at most 5 people per account for the first 10 domains.
Write coverage.csv. Do not write to the CRM.
PROMPTFor volume, move the pull out of the chat. POST /v1/exports takes up to 50,000 rows a request and 500,000 a day. The Exports page in the app builds the same filter, picks columns, shows the record price and downloads a CSV. Bulk CSV export is not on the Free plan.
What you get
Step 2 gives real numbers. On 21 October 2026 the free company count for the example segment returned this.
{
"total": 6143,
"totalIsExact": true,
"facets": {
"hq_state": [
{ "value": "California", "count": 1681 },
{ "value": "New York", "count": 621 },
{ "value": "Texas", "count": 511 }
]
},
"credits": 0,
"unsupportedFilters": []
}That is 6,143 US software companies with 51-200 staff that have at least one mailable contact on file. The same day, the free people count in Step 2 (US-based VPs in Sales & Business Development, same industry and size) returned 1,649 mailable people across 1,125 employers. Without an email condition the same filters match 4,141 people.
Here is how the records add up.
| Step | Call | Records |
|---|---|---|
| 2 | Company count and people count | 0 |
| 3 | 10 accounts, up to 5 people each | 50 or fewer |
| 4 | Enrich 20 contacts by LinkedIn URL | 20 or fewer |
| 5 | Saved prompts | 0 |
The coverage file has one row per account. The row below uses placeholder values.
domain,people_found,has_vp_or_above,has_work_email,gap
acme.com,5,yes,yes,This is the response shape from the API reference for one enriched person, with placeholder values.
{
"success": true,
"data": {
"profile_data": { "profile_full_name": "Jane Doe" },
"contact_data": {
"has_email": true,
"email_status": "verified",
"contact_current_experiences": [
{ "job_title": "VP Sales", "company_name": "Acme", "company_domain": "acme.com" }
]
},
"resume_data": {
"experiences": [
{ "job_title": "Director of Sales", "company_name": "Example Corp" }
]
}
},
"meta": { "credits": 1 }
}Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing, wrong or revoked key | Re-copy the key from app.leadocean.io and re-export $LEADOCEAN_API_KEY. |
| 429 | Above the plan's rate limit (5 requests a second on Free, 200 on Agency) | Wait the Retry-After seconds. Add a short sleep to the shell loops. |
| 402 | Free plan: the 1,000 records are spent | Check GET /v1/account. Free records do not reset. See pricing. |
| 404 on enrich or company people | We hold nothing for that input | Nothing to fix. It costs no record. Mark the row unknown. |
| Empty results or a 400 | An enum value outside the list, such as industry: "Software" | Resolve it with leadocean_list_enum_values and pass the exact string. |
| 400 on an export | More than 50,000 rows in one request | Split by HQ state and run several exports. |
FAQ
Can Claude Code update my CRM directly?
Only if you connect a CRM tool to it yourself. This recipe stops at CSV files you review and import. LeadOcean has no CRM, sequencer or Chrome extension.
How many records does a RevOps run cost?
One record per person or company you receive. Counts are free. The example spends about 70. Paid plans replace the 1,000-record allowance with a fair-use pace: Solo is $97 a month, Agency is $497 a month for teams.
Why sample 10 accounts instead of all of them?
Test the prompt on a small batch first. Once the coverage file looks right, run the full list with an export rather than one call per domain.
Where do I go next?
Start with the B2B prospecting workflow with Claude Code. Then read Claude Code for revenue operations and the recruiting workflows with Claude. More recipes live in the blog hub.
Size your first territory in Claude Code today
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →