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

Integration recipe

LeadOcean + Salesforce: search, enrich and send leads

Two LeadOcean calls and one Salesforce upsert. Runs on a schedule, creates each Lead once.

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

You get a job that searches LeadOcean for people who match your filter. It pulls a verified work email for each and creates them as Leads in Salesforce. It runs outside Salesforce, so it needs no package and no Apex. LeadOcean has no Salesforce app. This is two HTTP calls to https://api.leadocean.io and one to Salesforce. More recipes are on the integrations hub.

How it works

  1. Trigger. Run the script on a schedule: cron, a CI job or your workflow tool. Daily is enough for most lists.
  1. Size the list. Send the search with count=true as a query parameter and limit 1 first. It is free, so you see the number before you spend a record.
  1. Search. POST /v1/people/search with your filters and emailStatus: ["verified"]. Page with cursor, up to 100 per page. One search pages to 10,000 rows.
  1. Enrich. For each person_id, call POST /v1/people/enrich with reveal_email: true. A person with nothing on file returns a 404 and costs nothing.
  1. Upsert to Salesforce. Send batches of 200 to PATCH /services/data/vXX.X/composite/sobjects/Lead/LeadOcean_Person_Id__c. Salesforce creates the Lead if the external ID is new and updates it if not (Salesforce, September 2026).

Before step 5, create a text field on Lead named LeadOcean_Person_Id__c and mark it as an External ID. That field is your dedupe key. Run the first pass in a sandbox with limit set to 25.

Configuration

Three calls: search, enrich one result, upsert up to 200 Leads. Acme and Jane Doe are placeholders.

bash
curl -s https://api.leadocean.io/v1/people/search \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jobLevel": ["VP"],
    "jobFunction": ["Sales & Business Development"],
    "country": ["US"],
    "emailStatus": ["verified"],
    "limit": 25
  }'

curl -s 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_SEARCH", "reveal_email": true}'

curl -s -X PATCH \
  "https://MyDomainName.my.salesforce.com/services/data/v68.0/composite/sobjects/Lead/LeadOcean_Person_Id__c" \
  -H "Authorization: Bearer $SF_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "allOrNone": false,
    "records": [{
      "attributes": {"type": "Lead"},
      "LeadOcean_Person_Id__c": "PERSON_ID_FROM_SEARCH",
      "FirstName": "Jane",
      "LastName": "Doe",
      "Company": "Acme",
      "Email": "jane.doe@acme.com",
      "Title": "VP Sales",
      "LeadSource": "LeadOcean"
    }]
  }'

Enum values are exact strings. Check GET /v1/enums before changing a filter. Do not set id on the records: this call takes external IDs only. Send LastName and Company on every record. If your org requires other fields, Salesforce returns a per-record error naming them.

Field mapping

LeadOcean fieldSalesforce Lead fieldNote
meta.source_ids.person_idLeadOcean_Person_Id__cExternal ID. Stops duplicates on rerun.
profile_data.profile_first_name, profile_data.profile_last_nameFirstName, LastNameFall back to profile_full_name if one is empty.
contact_data.contact_emails[].emailEmailPick the entry whose type is work.
contact_data.email_statusDescription or a custom fieldKeep verified visible. No refund for bounces.
contact_data.contact_current_experiences[].job_titleTitleUse the first entry, the current role.
contact_data.contact_current_experiences[].company_nameCompanySend a value on every record.
a constantLeadSourceSet it to LeadOcean so you can report on it.

Cost at 10,000 rows

On LeadOcean, 10,000 Leads cost 20,000 records: one for each person returned by search and one for each enrich. Free holds 1,000 records for life, so it covers about 500 Leads. Use it to test the loop.

Solo is $97 a month and allows 10k enrichments every 5 hours, so 10,000 rows fit in one window. Agency is $497 a month if a team shares the pace. There are no credits and no overage invoice. Plans are on /pricing.

On Salesforce, 10,000 Leads is 50 collection calls of 200 records. API calls count toward the org's daily total, which for Enterprise Edition is 100,000 plus per-license calls plus add-ons (Salesforce, September 2026). Fifty calls is a rounding error against that.

Troubleshooting

SymptomCauseFix
404 on enrichNothing held for that personSkip the row. It costs nothing.
402 from LeadOceanFree records spentMove to Solo. Free does not renew.
429 from LeadOceanOver the plan rate: 5 a second on Free, 50 on SoloWait the Retry-After seconds.
Empty searchEnum value is not an exact stringCheck GET /v1/enums.
300 from SalesforceThe external ID matched more than one LeadRemove the duplicates, then rerun (Salesforce, September 2026).
Some records fail, others passallOrNone is false, so errors are per recordRead the errors array in the response.

FAQ

Does LeadOcean have a Salesforce app?

No. It is a REST API and an MCP server. This recipe calls the REST API from a script.

Why upsert instead of insert?

An upsert on an external ID creates a Lead once and updates it on later runs. A plain insert makes a duplicate each time the job sees the same person.

Can I enrich Leads already in Salesforce?

Yes. Use the Salesforce enrichment recipe, which updates existing records by Id.

Can I send the emails too?

LeadOcean does not send mail. Pair this with a sender, such as Smartlead. The email version of this recipe skips the CRM, and enrich leads shows the same flow as a prompt.

Send your first LeadOcean leads to Salesforce on the free plan

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

Get your free API key →