Enrichment API

LinkedIn Company URL to Domain API

POST /v1/companies/enrich. One LinkedIn company URL in, the website domain and company record out. 1 record per company found, a 404 is free.

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

POST /v1/companies/enrich takes one LinkedIn company URL and returns the company record, with the website domain at data.company_data.company_domain. It costs 1 record per company found. A 404 costs nothing.

There is no separate "domain" endpoint. The domain is one field of the company record, leadocean.company.v1. This page is the developer reference. For what the data is, read LinkedIn company URL to domain. The same lookup is the leadocean_get_company tool over MCP.

Quick start (curl)

Create a free account, copy a key with the enrich scope and export it as LEADOCEAN_API_KEY.

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 '{"linkedin_url":"https://www.linkedin.com/company/acme"}'

The endpoint also answers GET with query parameters:

bash
curl -s -G "https://api.leadocean.io/v1/companies/enrich" \
  --data-urlencode "linkedin_url=https://www.linkedin.com/company/acme" \
  -H "x-api-key: $LEADOCEAN_API_KEY"

Node.js (fetch)

js
const res = await fetch("https://api.leadocean.io/v1/companies/enrich", {
  method: "POST",
  headers: {
    "x-api-key": process.env.LEADOCEAN_API_KEY,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    linkedin_url: "https://www.linkedin.com/company/acme",
  }),
});

if (res.status === 404) {
  console.log("Company not in our data. Not billed.");
} else if (!res.ok) {
  throw new Error(`${res.status} ${(await res.json()).error?.message}`);
} else {
  const { data } = await res.json();
  console.log(data.company_data?.company_domain ?? "Company found, no domain held");
}

Python (requests)

python
import os
import requests

r = requests.post(
    "https://api.leadocean.io/v1/companies/enrich",
    json={"linkedin_url": "https://www.linkedin.com/company/acme"},
    headers={"x-api-key": os.environ["LEADOCEAN_API_KEY"]},
    timeout=10,
)

if r.status_code == 404:
    print("Company not in our data. Not billed.")
else:
    r.raise_for_status()
    company = r.json()["data"]["company_data"]
    print(company.get("company_domain") or "Company found, no domain held")

Request

Send linkedin_url or domain. The key needs the enrich scope. There is no lookup by company name.

ParameterTypeRequiredMeaning
linkedin_urlstring (URL)One of the twoLinkedIn company page URL, for example https://www.linkedin.com/company/acme.
domainstringOne of the twoWebsite domain, for example acme.com. Use it when you already have the domain and want the rest of the record.

POST takes these as a JSON body. GET takes them as query parameters. POST /v1/companies/enrich is an older alias, so use the path above.

Response

Response shape from the API reference. Every value below is a placeholder, and fields we hold nothing for are left out for brevity.

json
{
  "success": true,
  "data": {
    "company_data": {
      "company_name": "Acme",
      "company_domain": "acme.com",
      "company_social_links": {
        "linkedin": { "url": "https://www.linkedin.com/company/acme" }
      },
      "company_employees": {
        "number_of_employees": 240,
        "number_of_employees_code": "201-500"
      },
      "company_primary_address": {
        "city": "Austin",
        "country_code": "US"
      }
    },
    "company_detected_technologies": [
      {
        "technology_product": { "name": "Cloudflare" },
        "technology_last_detected_date": "2026-08-21"
      }
    ],
    "company_metrics": { "completion_score": 94, "marketability_score": 81 },
    "meta": { "sources": ["own"], "schema": "leadocean.company.v1" }
  },
  "meta": { "credits": 1, "source": "own" }
}
FieldMeaning
data.company_data.company_domainThe website domain. The field you came for.
data.company_data.company_nameCompany name.
data.company_data.company_social_linksSocial links, including the LinkedIn page.
data.company_data.company_employeesHeadcount and a banded size code.
data.company_detected_technologies[]Technology found on the company website, with a last detected date.
data.company_metricscompletion_score and marketability_score.
meta.creditsRecords counted for this call.

Unknown values are null, never guessed. Check company_domain before you write it anywhere. Each record also carries meta.fetched_at, and the dataset is refreshed monthly.

Errors

Every failure is { "success": false, "error": { "message": "...", "details": ... } }. Status codes are from the limits docs, September 2026.

StatusMeaningWhat to do
400Validation failed. details names the wrong fields.Send linkedin_url or domain. Not billed.
401Missing, wrong or revoked key.Check the x-api-key header.
402Free plan: the 1,000 records are spent. They do not reset.Upgrade. Not billed.
403The key lacks the enrich scope, or the account is suspended.Create a key with the scope.
404Not in our data.Stop. It costs nothing. Log the URL and move on.
429Over 100 requests a second, or 1 a minute on a paid account past its records.Wait for Retry-After, then retry. Not billed.
503The store behind the lookup is unreachable (code: no_source).Retry with backoff. Never billed.

Rate limits and cost

One company found is 1 record. A 404, 400, 401, 402, 403, 429 or 503 costs nothing. A 200 with company_domain set to null still costs 1 record, because we returned a company.

The limit is 100 requests per second per key, on every plan. Free is 1,000 records, one-off, no card. Pro is $499 a month, flat, with no per-record price inside fair use. See pricing.

Worked example: 10,000 company URLs and 8,700 found is 8,700 records. The 1,300 misses are free. The docs give no hit rate, so test a sample of your own list first.

Bulk

A list of company URLs has no export. POST /v1/exports exports people, not companies, so loop this endpoint once per URL. At 100 requests per second, 10,000 URLs fit in a couple of minutes.

If you are starting from people, the export already carries each employer. The column picker includes current_company_domain, current_company_linkedin_url and current_company_name, next to the numbered contact columns email_N_address and email_N_status. They come back as email_1_address, email_1_status, email_2_address and so on. caps sets how many (default 3 emails).

bash
curl -X POST https://api.leadocean.io/v1/exports \
  -H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
  -d '{
    "name": "VPs with employer domain",
    "filters": { "jobLevel": ["VP"], "country": ["US"] },
    "limit": 5000,
    "columns": ["person_id", "profile_full_name", "current_company_domain", "current_company_linkedin_url", "email_N_address", "email_N_status"],
    "caps": { "emails": 1 }
  }'

The reply is a 202 with a job id. Poll GET /v1/exports/{id}, then fetch /v1/exports/{id}/download. One export row is 1 record whatever the columns. Contact columns need the enrich scope too.

FAQ

Does a LinkedIn URL we cannot match cost a record?

No. A 404 costs nothing. You pay 1 record for each company returned.

Can I look up a domain by company name?

No. Send a LinkedIn company URL or a domain. With only a name, search companies first, then enrich the domain you get back. See company enrichment over the API.

Can an agent call it without an API key?

Yes. The MCP server at https://api.leadocean.io/mcp signs in with OAuth 2.1, so no key is pasted. The tool is leadocean_get_company, 1 record. Setup is on the MCP page.

Get your LinkedIn company to domain API key free

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

Get your free API key →