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

How-to guide

How to go from ICP to TAM (with the LeadOcean API)

A bottom-up TAM is two counts and a multiplication. Here are the calls, the output and the traps.

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

TL;DR

  • A bottom-up TAM is the number of companies that fit your ICP times your annual contract value. The API gives you the first number for free.
  • It takes about 15 minutes and spends 0 LeadOcean records. Counts are free. A 25-row sample pull is optional and costs 25.
  • Count companies first, then the buyers inside them. If the two numbers disagree wildly, your filters are wrong, not the market.

Prerequisites

  • A LeadOcean API key in $LEADOCEAN_API_KEY. The Free plan works: 1,000 records for life, no card, 5 requests a second.
  • curl and jq, or the LeadOcean MCP server in Claude if you prefer prompts to requests.
  • A written ICP: industry, headcount band, country, and the buyer's job function and level. Five lines is enough.

Step 1: Resolve your filter values

Filter values are exact strings, so look them up first. GET /v1/enums/{name} returns one enum and takes q to search it.

bash
curl -s -G "https://api.leadocean.io/v1/enums/industry" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "q=software"

Check the industry, the headcount band and the job level you plan to use. The headcount bands are 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000 and 10001+. Job levels are C-Team, VP, Director, Manager, Staff and Other. There are 534 industries, so search before you guess.

In Claude with the MCP server connected, the same lookup is one prompt:

text
Use leadocean_list_enum_values to find the exact industry value for "software".

Step 2: Count the companies

The company count is your account side of TAM. GET /v1/companies/count takes the company-search filters and returns an exact total with breakdowns. It is free.

bash
curl -s -G "https://api.leadocean.io/v1/companies/count" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  --data-urlencode "industry=Computer Software" \
  --data-urlencode "employeeRange=51-200,201-500" \
  --data-urlencode "hqCountry=US" | jq '.data.total'

Array filters on this GET take comma-separated values in one parameter, per the API reference.

The MCP tool leadocean_count_companies takes the same filters as JSON arrays:

json
{
  "industry": ["Computer Software"],
  "employeeRange": ["51-200", "201-500"],
  "hqCountry": ["US"]
}

The response also breaks the total down by headcount band, HQ state and NAICS code. Use that to find where the market is thin before you pick a go-to-market region.

Save the query next to the number. A TAM figure without its filters cannot be rerun, so paste the request into your planning doc with the date. When the total moves next quarter you can tell whether the market moved or your filters did.

Step 3: Count the buyers inside those companies

Companies are the TAM. People are the reachable TAM. Count the buyer roles with the people count, which is also free and also takes the company filters.

json
{
  "industry": ["Computer Software"],
  "employeeRange": ["51-200", "201-500"],
  "hqCountry": ["US"],
  "jobLevel": ["VP", "C-Team"],
  "jobFunction": ["Sales & Business Development"],
  "facets": false
}

Send that to leadocean_count_leads. The result carries distinctCompanies: how many employers those buyers span. Divide it by your company count from Step 2 to get your coverage, the share of accounts where you can name at least one buyer.

Two traps.

The default count only includes people with a verified, catch-all-valid or catch-all email, so it is a mailable count, not everyone. And do not pass fundingType, minFunding, minRevenue, maxRevenue, hqCity, hqState, investors, naics or sic to the people count. Those come back unsupported or as a fake round total.

Step 4: Do the multiplication

Write the formula down so someone can check it.

text
TAM  = companies x annual contract value
SAM  = companies you can reach and serve today
SOM  = the share of SAM you can win in 12 months

companies          = <Step 2 total>
ACV                = <your price x seats, from your own contracts>
TAM                = companies x ACV
accounts reachable = distinctCompanies from Step 3

The data supplies the counts. ACV comes from your own closed deals, not from us. If you have no deals yet, use your list price and say so in the deck.

A worked example with a placeholder price. Say Acme sells at $12,000 a year and your Step 2 count is 728 companies. Then TAM is 728 x $12,000 = $8,736,000 a year. If Step 3 shows buyers at 66 of those companies, the account base you can address by email today is 66 x $12,000 = $792,000 a year. The gap between the two numbers is your data-coverage problem. Widening the email status in Step 3 shows how much of it is a data gap and how much is a market gap.

Our TAM calculator does this arithmetic if you would rather not use a spreadsheet. The TAM sizing use case covers how teams run it every quarter.

Step 5: Slice it before you believe it

One total hides the shape of the market. Re-run Step 2 with one filter changed at a time and keep a table.

text
variant                                   companies
US, 51-500 employees, software            728
US, 51-200 only                           460
US, 201-500 only                          268
California only                           204

The first row is the TAM. The rows below it are your candidate segments. A segment worth a sales motion is big enough to fill a quarter of pipeline and small enough to name. If one state holds 28% of the total, as California does here (204 of 728), start there.

The breakdowns come back in the same free call, so you do not need one request per segment. Use separate requests only when you change a filter that is not in the breakdown, such as technologyCategories or a keyword.

Step 6: Spot-check with a small pull (optional)

Counts can be right and still describe the wrong companies. Pull 25 rows and read them before you put the number in a deck.

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 '{
    "industry": ["Computer Software"],
    "employeeRange": ["51-200", "201-500"],
    "hqCountry": ["US"],
    "limit": 25
  }' | jq '.data | length'

This is the only step that spends records: 25, one per company returned. Read the names. If a third of them are not your ICP, tighten the filters and recount. One search pages to 10,000 rows, so narrow the filters instead of walking the index.

What you get

On 2026-10-21 we ran the Step 2 and Step 3 counts through the LeadOcean MCP tools. Both are free.

text
leadocean_count_companies
  industry: Computer Software | employeeRange: 51-200, 201-500 | hqCountry: US
  total: 728 (exact)
  employee_range: 51-200 = 460, 201-500 = 268
  hq_state: California 204, Massachusetts 51, New York 51, Texas 44, Florida 37

leadocean_count_leads
  same company filters + jobLevel: VP, C-Team | jobFunction: Sales & Business Development
  total: 145 (mailable: verified, catch_all_valid or catch_all)
  totalAll: 681 (same filters, no email condition)
  distinctCompanies: 66

Read it like this: 728 companies fit the account filter. Of those, 66 have a VP or C-level sales buyer with a mailable address in our data. That is 9% coverage on the mailable count, and 681 buyers with no email condition.

The company record shape from the API reference, with placeholder values:

json
{
  "company_data": {
    "company_name": "Acme",
    "company_domain": "acme.com",
    "company_industries": [{ "name2": "Computer Software", "priority": 1 }],
    "company_employees": {
      "number_of_employees": 120,
      "number_of_employees_code": "51-200"
    },
    "company_primary_address": { "country_code": "US" }
  },
  "meta": { "schema": "leadocean.company.v1" }
}

That block is the response shape from the API reference with placeholder values, not a real record. The 9% is our arithmetic on the two counts above, not a field the API returns.

Three habits keep the number honest. Quote the date of every count. Say whether a people figure is mailable or total. Keep the filter list in the same cell as the result.

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-key headerRe-export $LEADOCEAN_API_KEY and send it in the x-api-key header, not as a bearer token.
429Above your plan's rate limit (5 a second on Free, 200 on Agency)Honor the Retry-After header. Loop over filters sequentially on Free.
402Out of recordsOnly the Step 6 pull spends records. Counts stay free, so size with counts and upgrade only when you need rows.
Total is 0A filter value is misspelled or in the wrong caseLook it up with leadocean_list_enum_values or GET /v1/enums/{name} and copy the exact string.
People count looks lowThe default counts only verified, catch-all-valid and catch-all emailsCompare it with totalAll, or pass emailStatus yourself. Label which one you quote.
Search stops at 10,000 rowsThe depth cap, shown as meta.depthCappedNarrow the filters or export. Exports take up to 50,000 rows a request and 500,000 a day, and bulk CSV is not on Free.

FAQ

Is a bottom-up TAM better than a top-down one?

Yes, for a technical buyer. Top-down starts from an analyst report and a guessed percentage. Bottom-up starts from a count of real companies you can inspect, so you can defend every number.

Does counting cost records?

No. Company counts, people counts and enum lookups are free, however many times you run them. Only returned rows cost records: one per person or company.

Why do I get fewer people than I expected?

The people count defaults to mailable addresses. The totalAll field shows the same filters with no email condition, so you can see the gap.

Can I do this from Claude instead of curl?

Yes. The hosted MCP server at https://api.leadocean.io/mcp exposes leadocean_count_companies, leadocean_count_leads and leadocean_list_enum_values, all free. Sign in with OAuth, no key to paste.

Do I need the API, or is the app enough?

The app at app.leadocean.io has an Exports page with a filter builder and a price preview, which suits one-off lists. The API and MCP tools suit repeatable sizing, because the same saved query reruns the same way every quarter.

How often should I refresh the number?

Quarterly is enough for planning. The dataset is refreshed monthly and each record carries its own fetched_at date. Rerun the same saved queries and compare totals, so a change in method does not look like a change in the market.

Where do I go from the TAM number?

Turn it into a working list with the TAM sourcing guide, and see what each plan allows on the pricing page.

Size your own TAM in 15 minutes, free.

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

Get your free API key →