POST /v1/companies/enrich takes a company domain and returns its employee count and size band. It costs 1 record per company found. A 404 costs nothing.
There is no separate headcount endpoint. Headcount is the company_employees block inside the company record. This page is the developer reference. For what the field means and how fresh it is, read Company Headcount. Agents call the same lookup as 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.
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"}'GET works with the same fields as query parameters. No domain to hand? Send the LinkedIn company page as linkedin_url instead.
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)
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({ domain: "acme.com" }),
});
if (res.status === 404) {
console.log("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();
const emp = data.company_data.company_employees;
console.log(emp?.number_of_employees ?? emp?.number_of_employees_code ?? "no headcount held");
}Python (requests)
import os
import requests
r = requests.post(
"https://api.leadocean.io/v1/companies/enrich",
json={"domain": "acme.com"},
headers={"x-api-key": os.environ["LEADOCEAN_API_KEY"]},
timeout=10,
)
if r.status_code == 404:
print("Not in our data. Not billed.")
else:
r.raise_for_status()
emp = r.json()["data"]["company_data"].get("company_employees") or {}
print(emp.get("number_of_employees") or emp.get("number_of_employees_code") or "no headcount held")Request
Send one of the two inputs. The key needs the enrich scope.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
domain | string | One of the two | Website domain, for example acme.com. Preferred key. |
linkedin_url | string (URL) | One of the two | LinkedIn company page URL. |
There is no lookup by company name. If you only hold a name, search companies first, then send the domain you get back.
Response
Response shape from the API reference. Every value below is a placeholder.
{
"success": true,
"data": {
"company_data": {
"company_name": "Acme",
"company_domain": "acme.com",
"company_employees": {
"number_of_employees": 240,
"number_of_employees_code": "201-500"
}
},
"company_metrics": { "completion_score": 90, "marketability_score": 80 },
"meta": { "sources": ["own"], "fetched_at": "2026-09-01", "schema": "leadocean.company.v1" }
},
"meta": { "credits": 1, "source": "own" }
}| Field | Meaning |
|---|---|
company_data.company_employees.number_of_employees | Headcount as a number. null when we hold none. |
company_data.company_employees.number_of_employees_code | Size band: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000 or 10001+. |
company_data.company_employees min and max | Bounds of the band, so a range check works when the exact number is missing. |
data.meta.fetched_at | When the record was fetched. Read it before you trust the number. |
meta.credits | Records charged for this call. |
Unknown values come back as null, never guessed. The same response carries industry, funding, HQ and website technologies. Only the headcount fields are shown here.
Errors
Every failure is { "success": false, "error": { "message": "...", "details": ... } }. Status codes are from the limits docs, September 2026.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Validation failed. Neither domain nor linkedin_url sent, or a field is malformed. | Read details and fix the named field. |
| 401 | Missing, wrong or revoked key. | Check the x-api-key header. |
| 402 | Free plan: the 1,000 records are spent. They do not reset. | Upgrade. Not billed. |
| 403 | The key lacks the enrich scope, or the account is suspended. | Create a key with the scope. |
| 404 | We hold no company for that input. | Stop. It costs nothing. Try the other identifier. |
| 429 | Over 100 requests a second, or 1 a minute on a paid account past its records. | Wait for Retry-After, then retry. Not billed. |
| 503 | The store behind the lookup is unreachable (code: no_source). | Retry with backoff. Never billed. |
Rate limits and cost
One found company is 1 record, by domain or by LinkedIn URL. That holds even when the record carries no headcount, because you received a company. A 404, 429, 402 or 503 costs nothing.
The limit is 100 requests per second per key, on every plan, with Retry-After: 1 when you exceed it. 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.
Reading headcount from a found record takes no second call. Check records left before a big run: GET /v1/account is free.
Bulk
For a few hundred domains, loop this endpoint. For thousands of people at companies of a given size, use POST /v1/exports instead. It is a people export, so each row is one person, 1 record, with the employer's headcount beside them.
The headcount columns are current_company_employees, current_company_employees_range, current_company_employees_min and current_company_employees_max. Repeated blocks are numbered: email_N_address comes back as email_1_address, email_2_address and so on, and caps sets how many (default 3 emails).
curl -X POST https://api.leadocean.io/v1/exports \
-H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
-d '{
"name": "VP Sales at 201-500 staff companies",
"filters": { "title": ["VP Sales"], "country": ["US"], "employeeRange": ["201-500"] },
"limit": 5000,
"columns": ["person_id", "current_company_domain", "current_company_employees",
"current_company_employees_range", "email_N_address"],
"caps": { "emails": 1 }
}'The reply is a 202 with a job id. Poll GET /v1/exports/{id}, then fetch /v1/exports/{id}/download. An export takes up to 50,000 rows and needs the search scope plus enrich for columns from the full record. Prefer clicks? The Exports page at app.leadocean.io builds the same file.
FAQ
Is there a separate employee count endpoint?
No. Call the company lookup and read company_data.company_employees. That is the whole headcount API, and it is also where industry, funding and tech stack come from.
What does a call cost, and what does a miss cost?
A found company costs 1 record, even with null headcount. A company we hold nothing for is a 404 and costs nothing. Free is 1,000 records, one-off. Pro is $499 a month, flat.
Can I look up headcount from a company name?
Not directly. Search companies by name, take the domain from the row and send it here. For the related fields, see company enrichment APIs compared and the best company data APIs.
Get your company headcount API key free
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →