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

How-to guide

How to enrich companies with an API (domain in, firmographics out)

Five steps: size a list for free, search it, enrich one domain, loop a batch. About 15 minutes and under 40 records.

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

Company enrichment turns a domain into a company record: headcount, industry, HQ, funding and website technologies. This guide runs it end to end against LeadOcean in five steps.

TL;DR

  • Send a domain to POST /v1/companies/enrich. You get one record back. A miss is a 404 and costs nothing.
  • Size the list first with the free count call, so you know what a batch will spend before you run it.
  • Total time is about 15 minutes. The sample run spends about 35 records, inside the 1,000 on the Free plan.

Prerequisites

  • A LeadOcean account on the Free plan: sign up. No card.
  • An API key from app.leadocean.io, exported as $LEADOCEAN_API_KEY.
  • curl and jq. Any HTTP client works the same way.
  • A list of domains. We use placeholders like acme.com.
bash
export LEADOCEAN_API_KEY="paste-your-key-here"

Step 1: Size the list for free

Count the companies that match your filters before you pull any. The count endpoint is free and returns an exact total with breakdowns.

bash
curl -s -X POST "https://api.leadocean.io/v1/companies/count" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"hqCountry":["US"],"employeeRange":["51-200"],"industry":["Software Development"]}' \
  | jq '.data | {total, totalIsExact}'

Filters are arrays of exact strings. If a value is rejected, list the allowed ones with GET /v1/enums, or call the leadocean_list_enum_values MCP tool. The same count is available to an agent as leadocean_count_companies.

Search returns companies that match filters, 1 record per company returned. Use it when you have a segment and no domains yet.

bash
curl -s -X POST "https://api.leadocean.io/v1/companies/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"hqCountry":["US"],"employeeRange":["51-200"],"industry":["Software Development"],"limit":25}' \
  | jq '.meta'

The body is flat JSON and limit runs 1 to 100. Page with the cursor value from the previous response. One search pages to 10,000 rows; past that, meta.depthCapped is true and there is no nextCursor, so narrow the filters instead.

Step 3: Enrich one domain

Enrichment takes a domain or a LinkedIn company URL and returns the full record. There is no lookup by company name: search first, then enrich the domain you get back.

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 '{"domain":"acme.com"}' | jq .

GET works too, with domain or linkedin_url as query parameters. A hit costs 1 record. A 404 means we hold nothing for that company and costs nothing.

Step 4: Loop a batch

There is no batch endpoint for company enrichment. Loop over your domains and keep the pace under your plan's rate limit: 5 requests a second on Free, 200 on Agency.

bash
while read -r d; do
  code=$(curl -s -o "out/$d.json" -w "%{http_code}" \
    -X POST "https://api.leadocean.io/v1/companies/enrich" \
    -H "x-api-key: $LEADOCEAN_API_KEY" \
    -H "content-type: application/json" \
    -d "{\"domain\":\"$d\"}")
  echo "$d $code"
  sleep 0.25
done < domains.txt

Create the out/ folder first. Log the status code per domain. A 404 is a miss, not a failure. On a 429, wait for the Retry-After header and retry.

Step 5: Flatten the output to a table

Keep the fields you will filter on and drop the rest. This jq pass turns the saved files into a CSV with one row per hit.

bash
jq -r '.data | [
  .company_data.company_domain,
  .company_data.company_name,
  .company_data.company_employees.number_of_employees,
  .company_data.company_primary_address.country_code,
  .company_metrics.marketability_score
] | @csv' out/*.json > companies.csv

Files for misses hold an error body, not a record, so jq prints nothing useful for them. Delete files whose status was 404 before you run it, or filter on .success.

What it costs at scale

If you enrich 10,000 domains and 9,200 are found, that is 9,200 records. The 800 misses are free. The Free plan covers the first 1,000 once. Paid plans have no per-record price. Solo is $97 a month and Agency is $497 a month, inside fair use. See pricing.

What you get

Step 1 returns an exact total. This is the free MCP count for the same filters, run on 21 October 2026:

json
{
  "total": 9261,
  "totalIsExact": true,
  "credits": 0,
  "unsupportedFilters": []
}

Step 3 returns the shape below. This is the response shape from the API reference, with placeholder values.

json
{
  "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_primary_address": { "city": "Austin", "country_code": "US" },
      "company_funding": { "last_round_type": "Series B" }
    },
    "company_detected_technologies": [
      { "technology_product": { "name": "Cloudflare" }, "technology_last_detected_date": "2026-08-21" }
    ],
    "company_metrics": { "completion_score": 94, "marketability_score": 81 },
    "meta": { "schema": "leadocean.company.v1", "credits": 1 }
  }
}

Unknown values come back as null, never guessed. Funding and revenue are thin for small private companies, so do not build a filter on them alone. Technology data covers about 7.8M crawled sites, so that array is empty for companies outside the set.

For comparison, Crustdata's docs list company enrich at 2 to 4 credits a call, and no public dollar price per credit (Crustdata docs, September 2026). On LeadOcean a hit is 1 record, and paid plans have a fair-use pace instead of credits.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerCheck $LEADOCEAN_API_KEY is exported and the header name is exact
404We hold nothing for that domainTreat it as a miss. It costs nothing. Try the LinkedIn company URL
429Above your plan's rate limit (5 a second on Free, 200 on Agency)Slow the loop and honor Retry-After
402The 1,000 Free records are spentUpgrade to Solo ($97 a month) or Agency ($497 a month)
Empty search resultsA filter value that is not an exact enum stringCheck spelling and case with /v1/enums
Search stops at 10,000 rowsThe depth cap, meta.depthCapped trueAdd filters and run several narrower searches

FAQ

Can I enrich a company by name?

No. Enrichment takes a domain or a linkedin_url. With only a name, run company search first and enrich the domain it returns.

How much does a miss cost?

Nothing. A 404, a count and an empty page are free. You pay 1 record for each company you receive.

How fresh is the data?

The dataset is refreshed monthly, and each record carries its own fetched_at date in meta. Check it before you act on a time-sensitive field.

Can I get the people at the company too?

Yes. GET /v1/companies/{domain}/people lists people we hold there, up to 10,000 rows, 1 record per person. See company headcount for the size fields.

Where do I go from here?

Compare vendors in best company data APIs and best contact enrichment APIs. Plans are on pricing. More guides are in the blog.

Enrich your first company free

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

Get your free API key →