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

HubSpot integration

LeadOcean + HubSpot: enrich records automatically

A workflow that calls the LeadOcean API on every new contact and writes job title, phone and email status back to HubSpot.

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

You get a HubSpot workflow that fires on a new contact and sends the email to LeadOcean. It writes job title, company domain, phone and email status back. It uses one custom code action, not a marketplace app. LeadOcean has no HubSpot listing, so the call is a plain HTTP request to https://api.leadocean.io.

How it works

The workflow has four parts: an enrollment trigger, a custom code action, property updates and a guard so a record is never enriched twice. HubSpot says custom code actions need a Data Hub Professional or Enterprise account (HubSpot docs, October 2026). No Data Hub? Use the script route at the end of this section.

  1. Create a LeadOcean key. Sign up at app.leadocean.io/register. The free plan needs no card and gives 1,000 records.
  2. Store the key as a secret. In the custom code action, click Add secret and paste the value of $LEADOCEAN_API_KEY. HubSpot exposes it to the code as process.env.<secret name> (HubSpot docs, October 2026).
  3. Create a contact-based workflow. Enroll contacts when Email is known and a custom property leadocean_enriched_at is unknown. This is the dedupe guard.
  4. Add a Custom code action. Language Node.js. Add email as an input property. Paste the code from the next section.
  5. Add Edit records actions. Map each code output to a contact property (see the table below). HubSpot documents code outputs as inputs to Edit records. Set leadocean_enriched_at last, to today's date.
  6. Test on a dedicated record, then turn the workflow on. HubSpot applies a test to the selected record, so make a throwaway contact first (HubSpot docs, October 2026). The test spends one LeadOcean record.

The script route skips workflows. Search contacts with no job title, enrich each email, then call POST /crm/v3/objects/contacts/batch/update with up to 100 contacts per request (HubSpot docs, October 2026). It costs no Data Hub seat. You run it yourself from cron or a CI job.

For a one-off list, use the Exports page in the LeadOcean app. Build filters, pick columns, see the record price, download a CSV and import it into HubSpot.

Configuration

The code below runs inside the custom code action. HubSpot lists axios as a supported Node.js library (HubSpot docs, October 2026). Replace LEADOCEAN_API_KEY with your secret name.

javascript
const axios = require('axios');

exports.main = async (event, callback) => {
  const email = event.inputFields['email'];
  let out = { leadocean_status: 'not_found' };

  try {
    const res = await axios.post(
      'https://api.leadocean.io/v1/people/enrich',
      { email: email, reveal_email: true },
      { headers: { 'x-api-key': process.env.LEADOCEAN_API_KEY } }
    );
    const c = res.data.data.contact_data || {};
    const job = (c.contact_current_experiences || [])[0] || {};
    const phone = (c.contact_phones || [])[0] || {};
    const mail = (c.contact_emails || [])[0] || {};
    out = {
      leadocean_status: 'found',
      job_title: job.job_title || '',
      company_domain: job.company_domain || '',
      phone: phone.phone || '',
      email_status: mail.status || ''
    };
  } catch (e) {
    if (!e.response || e.response.status !== 404) throw e;
  }
  callback({ outputFields: out });
};

Test the same call outside HubSpot first:

bash
curl -X POST "https://api.leadocean.io/v1/people/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"email":"jane@example.com","reveal_email":true}'

Send exactly one identifier per call: email, linkedin_url, phone or person_id (LeadOcean docs, September 2026). A person LeadOcean holds nothing for is a 404 and costs nothing, which is why the code catches it and moves on. reveal_email costs no extra record.

Field mapping

The response is one leadocean.person.v1 object under a data key. The fields below sit under data.contact_data (LeadOcean docs, October 2026).

LeadOcean fieldHubSpot propertyNote
contact_data.contact_current_experiences[].job_titlejobtitleCurrent role. Overwrite only when empty.
contact_data.contact_current_experiences[].company_domainwebsiteOverwrite only when empty.
contact_data.contact_phones[].phonephoneOnly returned when reveal_email is true.
contact_data.contact_emails[].statuscustom leadocean_email_statusValues include verified, catch_all_valid and risky. Branch on it before any send.
run datecustom leadocean_enriched_atDedupe guard. Create it as a date property first.

HubSpot treats email as the primary unique identifier for contacts, so match on email and never create contacts from this workflow (HubSpot docs, October 2026). Use Update, not create. Run the enrich step once per record and let the date property block repeats, so a re-saved contact never spends a second LeadOcean record. LeadOcean does not refund bounced emails, so filter on leadocean_email_status first.

Cost at 10,000 rows

10,000 rows cost $97 on LeadOcean Solo, plus HubSpot Data Hub Professional if you use the workflow route. Solo allows 10k enrichments every 5 hours and 50k a week, so 10,000 fits one window. The first 1,000 run free on the Free plan.

LeadOceanHubSpot
PlanSolo, $97 a month, flatData Hub Professional, starts at $800 a month, 1 seat included
Per-record priceNone. A fair-use pace, no overage invoiceNot applicable
Workflow route total$97$800
Script route total$97$0 extra, but API limits apply

HubSpot's list price comes from its Data Hub page, which shows one "starts at" figure and no separate yearly rate (HubSpot, October 2026). The workflow route totals $897 a month. The script route drops the $800. HubSpot API limits are 100 requests per 10 seconds per app on Free and Starter, and 190 on Professional. A daily cap applies per account (HubSpot docs, October 2026). Batching 100 contacts per update keeps 10,000 rows near 100 write calls.

Teams enriching more than 50k rows a week, Solo's weekly pace, should look at Agency at $497 a month. See pricing.

Troubleshooting

SymptomCauseFix
401 in the action logKey missing or wrong secret nameCheck the secret is added to this action and the name matches process.env.
400 from LeadOceanTwo identifiers sent, or empty emailSend only email. Add a trigger filter that requires Email is known.
402 from LeadOceanThe free 1,000 records are spentMove to Solo. Free records do not renew.
429 from LeadOceanOver the rate limit5 requests a second on Free, 50 on Solo (LeadOcean docs, October 2026). Turn on the action's rate limit in the workflow.
Workflow pauses mid-runAction rate limit reachedHubSpot logs that the action resumes at a set time. Raise the limit or wait (HubSpot docs, October 2026).
HubSpot 429 on the script routeHit the 10-second or daily capThrottle requests and batch 100 contacts per update (HubSpot docs, October 2026).
Output not available in later actionsOutput field not declaredAdd each output in the Data outputs section of the action (HubSpot docs, October 2026).

FAQ

Does LeadOcean have a native HubSpot app?

No. Use a custom code action or a script that calls the REST API. You get every endpoint, including GET /v2/people/phone for a direct phone lookup.

Do I need a paid HubSpot plan?

For the workflow route, yes: custom code actions need Data Hub Professional or Enterprise. The script route works on any plan with a private app token and API access.

Will it overwrite data my reps typed in?

Not if you map with care. Use a branch that checks the property is empty before each Edit records action, and keep leadocean_enriched_at so a record is enriched once.

How do I get phone numbers?

Set reveal_email to true and read contact_data.contact_phones[].phone. A second call to GET /v2/people/phone costs one record per call, including a call that finds nothing.

See also Retool, Notion and Folk, or go back to the integrations hub.

Enrich your HubSpot contacts with a free LeadOcean key.

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

Get your free API key →