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

Integrations

LeadOcean + Zoho CRM: Enrich Records Automatically

A small nightly job reads Zoho leads with a LinkedIn URL, enriches them through LeadOcean and writes the email, phone and job title back. No Zoho add-on needed.

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

You get a nightly job that fills the gaps in Zoho CRM. It reads leads that have a LinkedIn URL, sends each to LeadOcean, and writes the work email, email status, phone and job title back through Zoho's upsert API. LeadOcean is a plain REST API, so any script that can call two HTTP endpoints does it. The free plan covers a first run of 1,000 records.

Related: the integrations hub, Retool, Notion, Folk and pricing.

How it works

The job has three parts: read from Zoho, enrich at LeadOcean, upsert back to Zoho. It runs as an external script, outside Zoho, using only Zoho's documented REST API for reads, upserts and limits.

  1. Get a LeadOcean key. Sign up at app.leadocean.io, open API keys and copy one.
  2. Add two custom fields in Zoho. Create LinkedIn_URL and Email_Status on the Leads module. Tick "Do not allow duplicate values" on LinkedIn_URL. That makes it a user-defined unique field, which Zoho's upsert can match on.
  3. Create a Zoho API client. Register a self-client in the Zoho API console and generate a token with scope ZohoCRM.modules.ALL (or the narrower leads scope). Zoho's docs describe web and self-client grants.
  4. Read leads. Call Get Records on Leads with the fields parameter and per_page=200. Page with page_token past 2,000 records.
  5. Enrich each lead. Call POST /v1/people/enrich with the linkedin_url and reveal_email: true. A person LeadOcean holds nothing for returns 404 and costs nothing.
  6. Upsert in batches of 100. Zoho allows at most 100 records per upsert call. Set duplicate_check_fields to ["LinkedIn_URL"].
  7. Schedule it. Run the script from cron or any scheduler once a night. Select only leads where Email is empty so each lead is enriched once. Leads with no match stay empty, so add a date field such as Enriched_On and skip rows checked in the last 30 days.

Configuration

The script below is the whole job. Set LEADOCEAN_API_KEY and ZOHO_TOKEN in the environment. Zoho access tokens expire, so refresh them with your refresh token before each run. The www.zohoapis.com host is for the US data centre; use your own region's API domain.

python
import os, requests

LO = "https://api.leadocean.io"
ZOHO = "https://www.zohoapis.com/crm/v8"
lo_headers = {"x-api-key": os.environ["LEADOCEAN_API_KEY"]}
zo_headers = {"Authorization": "Zoho-oauthtoken " + os.environ["ZOHO_TOKEN"]}

r = requests.get(f"{ZOHO}/Leads", headers=zo_headers, params={
    "fields": "id,Last_Name,Email,LinkedIn_URL", "per_page": 200})
leads = [l for l in r.json().get("data", [])
         if l.get("LinkedIn_URL") and not l.get("Email")]

batch = []
for lead in leads:
    e = requests.post(f"{LO}/v1/people/enrich", headers=lo_headers,
        json={"linkedin_url": lead["LinkedIn_URL"], "reveal_email": True})
    if e.status_code == 404:
        continue                      # nobody matched, nothing billed
    e.raise_for_status()
    d = e.json()["data"]
    emails = d["contact_data"].get("contact_emails") or []
    phones = d["contact_data"].get("contact_phones") or []
    batch.append({
        "LinkedIn_URL": lead["LinkedIn_URL"],
        "Email": emails[0]["email"] if emails else None,
        "Email_Status": emails[0]["status"] if emails else None,
        "Phone": phones[0]["phone"] if phones else None,
        "Designation": (d["contact_data"].get("contact_current_experiences")
                        or [{}])[0].get("job_title"),
    })

for i in range(0, len(batch), 100):
    requests.post(f"{ZOHO}/Leads/upsert", headers=zo_headers, json={
        "data": batch[i:i+100],
        "duplicate_check_fields": ["LinkedIn_URL"]}).raise_for_status()

Test the key first with one call:

bash
curl -X POST https://api.leadocean.io/v1/people/enrich \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"linkedin_url": "https://www.linkedin.com/in/jane-doe", "reveal_email": true}'

Send exactly one identifier per call: linkedin_url, email, phone or person_id. reveal_email: true costs no extra record. The script needs a Last_Name on each lead only if you create new ones.

Field mapping

The enrich response has success, data and meta. Emails, phones and current roles are arrays, so the script takes the first item. Field paths are from the enrich docs, October 2026. Designation is the API name of the Title field on Zoho Leads.

LeadOcean fieldZoho fieldNote
data.contact_data.contact_emails[0].emailEmailOnly returned with reveal_email: true.
data.contact_data.contact_emails[0].statusEmail_Status (custom)Email status has 13 values. Mail only verified and catch_all_valid.
data.contact_data.contact_phones[0].phonePhoneOnly returned with reveal_email: true.
data.contact_data.contact_current_experiences[0].job_titleDesignation (Title)Current role only.
data.profile_data.profile_full_nameNot mappedZoho already holds first and last name.
LinkedIn_URL (input)LinkedIn_URL (custom, unique)The dedupe key for the upsert.

Cost at 10,000 rows

Enriching 10,000 Zoho leads costs LeadOcean one Solo month at $97, and about 1,050 of Zoho's daily API credits. The Free plan covers the first 1,000 records, once.

ItemFreeSolo ($97 a month)
LeadOcean records1,000 for lifeFair-use pace: 10k enrichments every 5 hours, 50k a week
Rate limit5 requests a second50 requests a second
10,000 rowsCovers the first 1,000One run fits the pace

Rows with no match are 404s and cost nothing, so 10,000 is a ceiling. Paid plans have no credits and no overage invoice. Agency at $497 a month suits teams that enrich across many sellers.

Zoho's side is its own credit system (Source: Zoho API limits, September 2026). Each API call costs 1 credit. Upsert costs 1 credit per 10 records. So reading 10,000 leads at 200 a page is 50 credits, and upserting them is 1,000 credits. The Free edition allows 5,000 credits in a 24-hour window, so one night's run fits.

Zoho seats are the larger bill, and this job does not add any. Zoho lists a Free edition for 3 users and paid editions priced per user a month (Zoho pricing, October 2026). Paid editions also get more API credits: Standard starts at 50,000 a day plus 250 per user license (Zoho API limits, October 2026).

Troubleshooting

SymptomCauseFix
Upsert inserts a duplicateLinkedIn_URL is not marked "Do not allow duplicate values".Mark the field unique, then list it in duplicate_check_fields.
Upsert rejects the callMore than 100 records in data.Chunk the batch at 100.
INVALID_DATA errorA value is longer than the Zoho field allows.Raise the field length or trim the title.
400 from LeadOceanTwo identifiers or none in the body.Send only linkedin_url.
401 from ZohoThe access token expired.Refresh it with your refresh token before each run.
404 from LeadOceanLeadOcean holds nothing for that person.Skip the row. It was not billed.
429 from LeadOceanYou went over your plan's request rate.Back off for the Retry-After seconds.
Only 2,000 leads readPage numbers stop at 2,000 records.Use page_token from next_page_token.

FAQ

Does LeadOcean have a Zoho CRM app?

No. LeadOcean is a REST API with an x-api-key header. There is no listing in Zoho's marketplace, so you call it from a script or a scheduler that can reach both APIs.

Can I enrich by email instead of LinkedIn URL?

Yes. Send email instead of linkedin_url. There is no name plus domain lookup. For that, search by domain first with POST /v1/people/search, then enrich by person_id.

Does enrich return past roles?

Yes. Since October 2026 the same call returns resume_data: past roles, education and certifications when LeadOcean holds them. Past employers carry no company id yet. Map them to a Zoho multi-line field if your reps want the history.

Can I get phones on their own?

Yes. GET /v2/people/phone returns numbers and costs one record per call. For a one-off list, the Exports page in the LeadOcean app does the same with a CSV download, which you can import into Zoho.

Enrich your first Zoho CRM leads with a free LeadOcean key

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

Get your free API key →