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

How-to guide

How to Build Customer Success Intelligence Workflows (with Claude)

A champion check, a replacement search and a renewal brief, run monthly. Real requests, a real enum lookup and the response shape.

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

TL;DR

  • Three workflows cover most of the value: check that each champion still works at the customer, find a replacement when they do not, and brief every renewal from fresh company data.
  • Setup takes about 45 minutes. The example book of 40 accounts spends about 65 of your 1,000 free records.
  • The dataset refreshes monthly, so run the loop monthly. LeadOcean has no change webhooks. You find a move by re-enriching and comparing.

A champion who leaves is the clearest churn signal a CS team can get from public data. Crustdata's guide builds it on daily watchers that fire a webhook (September 2026). LeadOcean does not do that. This recipe polls instead, and it is honest about the lag: up to a month.

Claude does the reading and the writing. LeadOcean supplies the facts. You keep the ledger in a CSV, so there is nothing to host.

Prerequisites

  • A LeadOcean account and API key from app.leadocean.io. The free plan has no card and 1,000 records, one-off. Free keys get both the search and enrich scopes.
  • The key in your shell as $LEADOCEAN_API_KEY.
  • Claude Code installed, plus Python 3 with requests.
  • A CSV of your accounts: domain, renewal date, and one or two champions per account with a LinkedIn URL or a work email.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"
pip install requests
mkdir cs-intel && cd cs-intel

Step 1: Connect Claude and write the champion ledger

Add the LeadOcean MCP server to Claude Code, then sign in when it asks. The server uses OAuth 2.1, so you paste no key into the client. Claude Code's MCP docs describe the claude mcp add command for HTTP servers (September 2026).

bash
claude mcp add --transport http leadocean https://api.leadocean.io/mcp

Then write the ledger. One row per champion. Use placeholder-shaped data like this and replace it with your own.

text
account_domain,renewal_date,champion,linkedin_url,email
acme.com,2026-12-15,Jane Doe,https://www.linkedin.com/in/jane-doe,
globex.example,2027-01-31,John Roe,,john.roe@globex.example

Save it as champions.csv. Send one identifier per champion. Enrich accepts exactly one of linkedin_url, email, phone or person_id, and two is a 400.

Step 2: Check that each champion still works there

Enrich every champion once and compare the current employer to the account. A mismatch is a departure. This is the workflow that matters most, and it is a plain loop.

python
import csv, os, requests

API = "https://api.leadocean.io/v1/people/enrich"
HDR = {"x-api-key": os.environ["LEADOCEAN_API_KEY"], "content-type": "application/json"}

def current_role(row):
    body = {"linkedin_url": row["linkedin_url"]} if row["linkedin_url"] else {"email": row["email"]}
    r = requests.post(API, headers=HDR, json=body, timeout=30)
    if r.status_code == 404:
        return None, "miss"
    if r.status_code in (401, 402, 429):
        raise SystemExit(f"stop: {r.status_code} {r.text[:120]}")
    r.raise_for_status()
    exp = (r.json()["data"]["contact_data"].get("contact_current_experiences") or [{}])[0]
    return exp, "ok"

out = []
for row in csv.DictReader(open("champions.csv")):
    exp, state = current_role(row)
    if exp is not None and exp.get("company_domain") != row["account_domain"]:
        state = "moved"
    out.append({**row, "state": state,
                "now_company": (exp or {}).get("company_domain", ""),
                "now_title": (exp or {}).get("job_title", "")})

with open("status.csv", "w", newline="") as f:
    w = csv.DictWriter(f, fieldnames=list(out[0]))
    w.writeheader()
    w.writerows(out)
print({s: sum(o["state"] == s for o in out) for s in ("ok", "moved", "miss")})

A 404 means LeadOcean holds nothing for that person. It costs nothing, so the row is marked miss. Treat a miss as unknown, not as safe.

The current role sits in contact_data.contact_current_experiences[], and each experience carries company_domain and job_title (enrich docs, October 2026). Since October 2026 enrich also returns past roles in resume_data.experiences[], so a moved champion shows the old employer there.

Each person we hold costs one record. For 40 champions that is at most 40.

Step 3: Find the replacement at accounts that lost a champion

For each moved row, search the account's own domain for the people who now own the relationship. Filter by level and function. Cap the page at 5 so the cost stays small.

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": ["Customer/Client Service"],
    "limit": 5
  }'

The body is flat JSON and every filter is an array of strings. Enum values are exact strings. VP and Director are job levels, and Customer/Client Service is the job function that covers support and success roles. Check any value you are unsure of with the free leadocean_list_enum_values tool.

Each person returned is one record, so this call spends at most 5. If the account is small and returns nobody, widen jobLevel to include Manager and run it again.

To get a work email for the person you pick, enrich by person_id. The search row carries it at meta.source_ids.person_id.

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": "123456789", "reveal_email": true}'

Reading email_status before you send matters. There is no refund for a bounced address.

Step 4: Brief the renewal with Claude

Sixty days before each renewal date, pull the company record and hand it to Claude with last month's snapshot. Company enrich takes a domain and returns company_data, company_metrics and detected technologies.

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"}' > snapshots/acme.com-2026-10.json   # mkdir snapshots first

Save one snapshot per account per month. A single record tells you where the company stands. Two records tell you what moved. Then give Claude Code this prompt.

text
Read snapshots/acme.com-2026-10.json and, if it exists, snapshots/acme.com-2026-09.json.
Write a 10-line renewal brief for the CSM:
1. Headcount, funding and technology changes between the two snapshots.
2. Whether the champion in status.csv is ok, moved or miss.
3. If moved, the replacement candidates from replacements/acme.com.json.
4. One risk and one expansion angle, each tied to a field you read.
Quote the field name for every claim. If a field is missing, say so. Do not guess.

The last three lines of that prompt do the real work. Without them Claude fills gaps with plausible filler. With them it reports only what the record shows.

Company enrich costs one record per company. Ten renewals a month is ten records.

Step 5: Run it monthly

Run the loop once a month. Faster runs return the same record and spend another one. Every record also carries its own fetched_at date, so you can see how old each answer is.

text
0 6 2 * * cd /srv/cs-intel && python3 check_champions.py >> check.log 2>&1

Tune the cadence by risk. Check champions on accounts renewing inside 90 days every month. Check the rest every 90 days. That keeps the spend near 65 records on the example book instead of 120 or more.

Do a dry run first on 10 champions. Confirm that the moved rows are real moves before anyone gets an alert.

What you get

The free enum lookup resolved the job function for this recipe on 2026-10-21. leadocean_list_enum_values with name: job_function and q: Customer returned this.

json
{"name":"job_function","total":22,"matched":1,"values":["Customer/Client Service"],"truncated":false}

A free leadocean_count_leads run on 2026-10-21 sized the replacement pool: job function Customer/Client Service, job level VP or Director, in the US. It returned 30,272 mailable people out of 66,177, at 16,396 employers. Mailable is the tool's default: verified, catch_all_valid or catch_all email. It spent 0 records.

The enrich response shape from the API reference follows, with placeholder values.

json
{
  "success": true,
  "data": {
    "profile_data": { "profile_full_name": "Jane Doe" },
    "contact_data": {
      "has_email": true,
      "email_status": "verified",
      "email_type": "work",
      "contact_current_experiences": [
        { "company_name": "Globex", "company_domain": "globex.example", "job_title": "VP Operations" }
      ]
    }
  },
  "meta": { "schema": "leadocean.person.v1", "credits": 1 }
}

Your status.csv is the output you read each month. This is the format, with placeholder values.

text
account_domain,renewal_date,champion,state,now_company,now_title
acme.com,2026-12-15,Jane Doe,moved,globex.example,VP Operations
globex.example,2027-01-31,John Roe,ok,globex.example,Head of Support

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key.Re-export $LEADOCEAN_API_KEY from app.leadocean.io and rerun.
402Out of records. On Free this is a refusal after your 1,000.Check GET /v1/account, trim the champion list, or move to Solo ($97 a month).
429Above the plan's rate limit (5 requests a second on Free, 200 on Agency).Wait for the Retry-After header. The sequential loop in Step 2 will not hit it.
400Two identifiers in one enrich call.Send exactly one of linkedin_url, email, phone or person_id.
404We hold nothing for that person.Not billed. Mark the row miss and retry next month.
Empty resultsAn enum filter holds a wrong string, such as vp for jobLevel.Look the value up with leadocean_list_enum_values. Use VP, not vp.

FAQ

How fast does this catch a champion leaving?

Within about a month. The dataset refreshes monthly, so a move shows up after the next refresh and your next run. If you need daily alerts, this is the wrong tool.

Does LeadOcean send a webhook when a contact changes jobs?

No. LeadOcean has no change webhooks or watchers. You re-enrich the champion and compare the employer, as in Step 2.

Can Claude run the whole loop for me?

Yes for Steps 3 and 4. Claude Code can call the MCP search and company tools and write the brief. Keep Step 2 as a script, because it is a fixed loop that should cost the same each month.

What does this cost?

The free plan holds 1,000 records, one-off, so the example book fits in the first run. Solo is $97 a month and Agency is $497 a month, both on a fair-use pace with no per-record price. See pricing.

Where do I go for more Claude workflows?

Catch the next champion move before the renewal call

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

Get your free API key →