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

How-to guide

How to Build the Ideal GTM Tech Stack (and Cut the Rest)

Four layers, one data source, three tools you can skip. Size the market for free, test the data on five rows, then export.

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

TL;DR

  • The ideal GTM stack has four layers: data, system of record, sending and orchestration. Anything else has to earn its seat with a number.
  • It takes about 45 minutes and spends about 106 LeadOcean records. Sizing is free. On Free, swap the bulk export for a 100-row search pull.
  • Buy the data layer first. Every other tool is only as good as the rows you feed it.

Prerequisites

  • A LeadOcean API key from app.leadocean.io/register. The free plan has 1,000 records, one-off, no card, 5 requests a second.
  • The key in your shell: export LEADOCEAN_API_KEY=your_key_here.
  • curl and jq.
  • A CRM and a sending tool you already use, or none yet. This guide does not need either to run.
  • Optional: an MCP client, to size markets by chat.

Step 1: Write the stack down as four layers

A stack is a list of jobs, not a list of logos. Write one line per job and name the tool that does it. If two tools do the same job, cut one.

yaml
data:          # who to contact, and how
  source: LeadOcean API
  job: search, enrich, verify email status, export
record:        # where deals live
  source: your CRM
  job: accounts, contacts, deals, one owner per account
sending:       # how messages leave
  source: your email or sequencing tool
  job: mailboxes, sequences, replies
orchestration: # how the other three talk
  source: n8n, a script, or an MCP client
  job: move rows from data to record to sending

Apply one test to every tool already in your stack. Name the weekly action it triggers and the number that moves. If you cannot, pause the renewal for a month and see who notices.

Three things do not need a seat on day one. A dialer, if you do not cold call. An intent feed, until you can name one action it triggers. A second enrichment vendor, until the first one's miss rate is measured.

LeadOcean covers the data layer only. It has an app with an Exports page, but no sequencer, dialer, CRM or Chrome extension. Pair it with the tools you already run.

Step 2: Size the market before you buy anything

Count the accounts and the buyers, free, before you commit to a stack. If the list is 400 people, you need a spreadsheet. If it is 10,000, you need the four layers.

Company count first. GET /v1/companies/count takes the company-search filters and returns an exact total.

bash
curl -s "https://api.leadocean.io/v1/companies/count?hqCountry=US&employeeRange=51-200,201-500&technologies=HubSpot" \
  -H "x-api-key: $LEADOCEAN_API_KEY" | jq '.data | {total, totalIsExact}'

Array filters in a query string are comma-separated. Then people. Add count=true and limit=1 as query parameters. No records are spent.

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"],
    "employeeRange": ["51-200", "201-500"],
    "technologies": ["HubSpot"],
    "jobFunction": ["Sales & Business Development"],
    "jobLevel": ["VP"],
    "emailStatus": ["verified", "catch_all_valid", "catch_all"]
  }' | jq '.meta | {total, totalIsExact, distinctCompanies}'

count=true goes in the query string. The JSON body rejects unknown fields. Enum values are exact strings, so look them up with GET /v1/enums/{name} before you guess.

Step 3: Test the data layer on five rows

Spend 5 records, not 500. Remove count, set limit to 5, and read what comes back.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/search" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "limit": 5,
    "hqCountry": ["US"],
    "employeeRange": ["51-200", "201-500"],
    "technologies": ["HubSpot"],
    "jobFunction": ["Sales & Business Development"],
    "jobLevel": ["VP"],
    "emailStatus": ["verified", "catch_all_valid", "catch_all"]
  }' | jq '.data[] | {has_email: .contact_data.has_email, email_status: .contact_data.email_status}'

Search rows carry flags, not addresses. You see whether a deliverable email exists before you reveal it. Check each row against the person's real profile. If three of five are wrong, change the data source, not the sequencer.

Step 4: Enrich at the point of use

Do not enrich the whole database into your CRM. Enrich the person when a rep or an agent needs the address. POST /v1/people/enrich takes exactly one of linkedin_url, email, phone or person_id. Set reveal_email to true to get the address.

bash
curl -s -X POST "https://api.leadocean.io/v1/people/enrich" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"person_id": "<person_id from a search row>", "reveal_email": true}'

A person we hold nothing for returns 404 and costs nothing. Since 17 October 2026 the response also carries career history: past roles, education and certifications, each when held. Past employers carry no company_id yet.

Step 5: Export to the sending layer

Pick the list you tested and export it. POST /v1/exports takes the same filters inside a filters object, plus a row limit. One export runs up to 50,000 rows, and the daily ceiling is 500,000 rows.

bash
curl -s -X POST "https://api.leadocean.io/v1/exports" \
  -H "x-api-key: $LEADOCEAN_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "name": "HubSpot shops, VP Sales, US, 51-500",
    "filters": {
      "hqCountry": ["US"],
      "employeeRange": ["51-200", "201-500"],
      "technologies": ["HubSpot"],
      "jobFunction": ["Sales & Business Development"],
      "jobLevel": ["VP"],
      "emailStatus": ["verified", "catch_all_valid", "catch_all"]
    },
    "limit": 100,
    "preset": "full"
  }'

The API answers 202 with an export id. Poll GET /v1/exports/{id} until status is done, then read the signed downloadUrl. This export spends at most 100 records. Bulk CSV export is not on the Free plan, so a free key reaches the same step through the Exports page in the LeadOcean app or a smaller search pull.

Check email_status on every column before the import. Send to verified and catch_all_valid first, and treat catch_all as a smaller test batch. LeadOcean gives no refund for bounces, so the status column is your only protection.

Import the CSV into your CRM, then into the sequencer. That is the whole orchestration layer for a team of one. Add n8n or a script once you repeat this weekly.

Step 6: Give an agent the same data

If an AI client belongs in the orchestration layer, connect it to the hosted MCP server at https://api.leadocean.io/mcp. It signs in with OAuth, so no key is pasted. The server has 13 tools. Three of the free ones do the sizing and lookups above: leadocean_count_leads, leadocean_count_companies and leadocean_list_enum_values.

Start every agent session with a count. A prompt that works:

text
Use LeadOcean. Count mailable VPs of Sales at US companies with 51-500
employees that run HubSpot. Do not search yet. Tell me the total and
how many distinct companies it spans.

For one account at a time, the tech stack qualifier skill checks a company against a technology rule. To see what a site runs without an account, use the free tech stack checker.

What you get

These numbers come from the free MCP tools on 2026-10-21. Filters: US headquarters, 51-200 and 201-500 employees, technologies: HubSpot.

QuestionToolResult
Companies that matchleadocean_count_companies29,037 (exact)
Mailable VPs of Sales at themleadocean_count_leads10,023 people
Companies those people spandistinctCompanies4,993
Same people, any email statustotalAll29,167

Both calls reported credits: 0. The people count covers verified, catch_all_valid and catch_all emails only. The gap between 10,023 and 29,167 is the people you cannot mail yet.

Read the stack decision from the numbers. About 5,000 reachable accounts is too many for a spreadsheet and enough to justify a sequencer. A list of 400 would not be.

A search row looks like this. This is the response shape from the API reference, with placeholder values.

json
{
  "success": true,
  "data": [
    {
      "profile_data": { "...": "identity and headline fields" },
      "contact_data": {
        "has_email": true,
        "has_phone": false,
        "email_status": "verified",
        "email_type": "work"
      },
      "meta": { "...": "person_id and source fields" }
    }
  ],
  "meta": { "count": 1, "limit": 5, "credits": 1, "nextCursor": "<opaque string>" }
}

One search pages to 10,000 rows. If meta.depthCapped is true, narrow the filters or use an export.

Troubleshooting

ErrorCauseFix
401Missing, wrong or revoked keyCheck the x-api-key header and that $LEADOCEAN_API_KEY is set in this shell.
429More requests a second than the plan allows (5 on Free, 200 on Agency)Wait for Retry-After, then retry. Slow the loop or move to a higher plan.
402The free 1,000 records are spentThey are a one-off and do not reset. Pick a paid plan on the pricing page.
400 or empty resultsA filter value is not an exact enum stringLook it up with GET /v1/enums/{name} or leadocean_list_enum_values.
404 on enrichNobody matched the inputCosts nothing. Try another identifier, such as linkedin_url.
Export refusedOver 50,000 rows a request or 500,000 a daySplit the list into smaller exports, or wait for the reset.

FAQ

What is the minimum GTM tech stack?

Data, a system of record, a way to send and something that moves rows between them. For a team of one, the last layer is a CSV import. Add tools only when a measured number forces it.

Which tool should I buy first?

The data source. A sequencer sends whatever you give it, and a CRM stores it. Test the data on five rows before you pay for anything downstream.

Do I need an intent or technographic feed?

Only if a signal changes what you send. LeadOcean has a technologies filter, built from about 7.8M crawled company websites, which is a fraction of the database. It tells you a tool is on the site. It does not tell you the buyer is unhappy with it.

What does this guide cost on the free plan?

Sizing costs nothing. The five-row test costs 5 records, one enrichment costs 1 and a 100-row export costs 100. That leaves about 894 of your 1,000. On Free, make the 100 a search pull, because bulk export needs a paid plan.

Does LeadOcean replace my CRM or sequencer?

No. It is the data layer, with an API, an MCP server and an Exports page in the app. It has no rep workspace, sequencer, dialer or CRM.

Test the data layer of your stack free

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

Get your free API key →