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

How-to guide

How to run a TAM analysis (with a company count API)

Four steps, about 20 minutes, zero records spent on the sizing itself.

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

A TAM analysis is a count of the companies you could sell to, multiplied by what each is worth. The count is the hard part. This guide gets it from a free API call instead of a guess.

TL;DR

  • Count target companies with GET /v1/companies/count, then multiply by your average contract value (ACV).
  • It takes about 20 minutes and spends 0 records. The optional sample pull in Step 4 spends 25.
  • Narrow in three layers: TAM (all fits), SAM (the part you can serve), SOM (the part you can win this year).

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. A spreadsheet for the multiplication.
  • An ideal customer profile: industry, headcount band, country. One sentence is enough.
  • Your average ACV. Use closed-won data, not a list price.

Step 1: Write the profile as filters

Turn the sentence into filter values before you count anything. Enum values are exact strings, so resolve them first.

bash
curl -s "https://api.leadocean.io/v1/enums/industry?q=software" \
  -H "x-api-key: $LEADOCEAN_API_KEY" | jq '.data.values[:5]'

Our worked example: US software companies with 51 to 500 employees. That is industry: Computer Software, hqCountry: US, employeeRange: 51-200, 201-500. Lookups are free.

Step 2: Count companies (TAM)

Call the company count endpoint with the same filters you would send to company search. It is free and returns an exact total with breakdowns.

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 "hqCountry=US" \
  --data-urlencode "employeeRange=51-200,201-500" | jq '{total: .data.total}'

The same call is the MCP tool leadocean_count_companies, so an agent can do it in chat. Do not use the people count for this: it counts people, not companies. Array filters go in the query string as one comma-separated value, such as employeeRange=51-200,201-500 (LeadOcean OpenAPI, October 2026).

Step 3: Narrow to SAM and SOM

SAM is the slice you can actually serve today. Add hasMailableContacts: true to keep only companies with at least one person you can email.

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 "hqCountry=US" \
  --data-urlencode "employeeRange=51-200,201-500" \
  --data-urlencode "hasMailableContacts=true" | jq '{total: .data.total}'

SOM is a judgment, not a query. Take your SAM and apply the share you can win in 12 months, based on your pipeline capacity. Write that number down with its assumption.

Add a buyer count too. POST /v1/people/search with count=true as a query parameter and limit=1 is free. It returns meta.total (capped at 100,000) and meta.distinctCompanies.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search?count=true&limit=1" \
  -H "x-api-key: $LEADOCEAN_API_KEY" -H "content-type: application/json" \
  -d '{"hqCountry":["US"],"industry":["Computer Software"],
       "employeeRange":["51-200","201-500"],
       "jobLevel":["VP","C-Team"],
       "jobFunction":["Sales & Business Development"]}' | jq '.meta'

Step 4: Multiply and sanity-check

Revenue TAM is company count times ACV. Use the SAM count for the serviceable figure.

text
TAM (companies)   728
SAM (mailable)    476
ACV               $24,000   (your number, not ours)
TAM revenue       728 x $24,000 = $17,472,000
SAM revenue       476 x $24,000 = $11,424,000

Then sanity-check with a small pull. Search 25 companies and read them. If half are not your buyer, your filters are wrong, and the count is wrong with them.

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"],"industry":["Computer Software"],
       "employeeRange":["51-200","201-500"],"limit":25}'

That call spends 25 records. One search pages to 10,000 rows (meta.depthCapped tells you), so narrow the filters rather than walking the index.

Step 5: Cut the TAM by region and sector

The count response also breaks the total down by industry, headcount band, HQ country, HQ state and NAICS. Use it to find where the market is concentrated, then decide which slice to enter first.

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 "hqCountry=US" \
  --data-urlencode "employeeRange=51-200,201-500" | jq '.data.facets.hq_state[:4]'

In our example California holds 204 of 728 companies, about 28%. A team that covers one state first sizes its SOM from that row, not from the national total. Re-run the count per slice. Each call is free, so ten slices cost nothing.

Write down every filter next to every number. A TAM figure without its filters cannot be reproduced next quarter, and nobody can challenge it.

What you get

Real output from the free MCP tools on 2026-10-21. These are company counts, not mailable-person counts.

Filter setCompanies
US, Computer Software, 51-200 or 201-500 employees728
Same, with hasMailableContacts: true476

The 728 split into 460 at 51-200 and 268 at 201-500. The largest HQ states were California (204), Massachusetts (51), New York (51) and Texas (44).

The people count covered VP and C-Team in Sales & Business Development at those companies. It returned 145 people across 66 companies, counting only verified, catch_all_valid or catch_all emails. With no email condition it returned 681. Treat 145 as mailable buyers, not everyone in the role.

Response shape from the API reference for a company search row, placeholder values:

json
{
  "success": true,
  "data": [{ "company_data": { "company_name": "Acme", "company_domain": "acme.com" } }],
  "meta": { "count": 25, "limit": 25, "credits": 25, "total": 728, "nextCursor": "<cursor>" }
}

Troubleshooting

ErrorCauseFix
401Missing or wrong x-api-keySend the key in the x-api-key header. Create one in app.leadocean.io.
429Above the plan rate limit (5 a second on Free, 200 on Agency)Honor Retry-After, then slow the loop.
402The 1,000 Free records are spentCounts stay free. Move to a paid plan for sample pulls.
Empty or zero totalEnum value not an exact stringResolve it through GET /v1/enums/industry?q=... first. Software is not Computer Software.
unsupportedFilters in the replyA filter that count cannot applyThe total is withheld, not wrong. Drop the filter and say so in your write-up.
Export refusedOver 50,000 rows a request or 500,000 a daySplit the export by country or headcount band.

FAQ

What is the difference between TAM, SAM and SOM?

TAM is every company that fits your profile. SAM is the part you can serve and reach. SOM is the part you can win in a set period. Definitions are in the TAM glossary entry.

Top-down or bottom-up?

Bottom-up. A count of real companies beats a market-research percentage you cannot audit. Use top-down only as a cross-check.

How often should I redo it?

Quarterly. The dataset is refreshed monthly, and every record carries its own fetched_at date.

Can I monitor the TAM over time?

Yes. Save the count call and run it on a schedule. See monitoring your total addressable market and turning a TAM into a list.

More guides are in the blog. Plans are on pricing.

Size your own market in 20 minutes, for free

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

Get your free API key →