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. curlandjq, 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.
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:
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.
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:
{
"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.
{
"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.
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 3The 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.
variant companies
US, 51-500 employees, software 728
US, 51-200 only 460
US, 201-500 only 268
California only 204The 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.
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.
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: 66Read 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:
{
"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
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key header | Re-export $LEADOCEAN_API_KEY and send it in the x-api-key header, not as a bearer token. |
| 429 | Above your plan's rate limit (5 a second on Free, 200 on Agency) | Honor the Retry-After header. Loop over filters sequentially on Free. |
| 402 | Out of records | Only the Step 6 pull spends records. Counts stay free, so size with counts and upgrade only when you need rows. |
| Total is 0 | A filter value is misspelled or in the wrong case | Look it up with leadocean_list_enum_values or GET /v1/enums/{name} and copy the exact string. |
| People count looks low | The default counts only verified, catch-all-valid and catch-all emails | Compare it with totalAll, or pass emailStatus yourself. Label which one you quote. |
| Search stops at 10,000 rows | The depth cap, shown as meta.depthCapped | Narrow 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 →