gtm.devdocs

Quickstart

gtm.dev is the GTM data graph exposed as typed tools. Your agent connects once over MCP and every tool appears in its toolbox — or call the same tools over REST.

  1. Get an API key. Sign in to the console (magic link, no password) — signup issues a LIVE starter key with 1,000 free credits, no card. Test-mode keys (realistic sample data, free forever) are a separate, clearly-labeled option for CI and demos.
  2. Connect your agent (recommended). One command for Claude Code:
    claude mcp add --transport http gtm https://mcp.gtm.dev \
      --header "Authorization: Bearer YOUR_API_KEY"
    Or drop this in any MCP-capable client (Cursor, Windsurf, Claude Desktop, OpenAI Agents SDK, LangChain):
    {
      "mcpServers": {
        "gtm": {
          "url": "https://mcp.gtm.dev",
          "headers": { "Authorization": "Bearer YOUR_API_KEY" }
        }
      }
    }
  3. Or call REST directly:
    curl -X POST https://api.gtm.dev/v1/tools/resolve_company \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"query": "stripe"}'
  4. Ask your agent something the graph can answer: “who’s hiring SDRs in the US right now? enrich the top three and tell me what tech they run.” The agent chains who_is_hiringenrich_company company_tech on its own.

Authentication

Every request carries an API key as a bearer token: Authorization: Bearer gtm_live_sk_…. Keys come in two modes — gtm_live_sk_ (real data, spends credits — your starter key is this kind) and gtm_test_sk_ (deterministic sample data, free forever — every test response carries "test_mode": true so nothing fake can pass as real). We store only a hash of your key: it is shown once at creation, so store it in a secret manager. Revoke and reissue anytime from the console.

MCP

The MCP endpoint is https://api.gtm.dev/mcp (streamable HTTP, JSON-RPC 2.0). Connect once and all tools appear via tools/list with full JSON-Schema inputs — your agent needs zero glue code. The same API key authorizes MCP and REST.

# what your client does under the hood
curl -X POST https://mcp.gtm.dev \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"who_is_hiring",
                 "arguments":{"role":"sdr","geo_country":"United States"}}}'

tool results come back as MCP content plus structuredContent — agents can read either.

REST API

Every tool is also POST {base}/v1/tools/{tool_name} with a JSON body matching the tool’s input schema; the raw result comes back as JSON. GET /v1/tools returns the machine-readable catalog.

statusmeaning
401 unauthorizedmissing, malformed, or revoked key
402 insufficient_creditslive balance is 0 — response includes your balance
429 rate_limitedper-key rate limit; back off and retry
400 invalid_inputbody doesn’t match the input schema
503 data_plane_unavailablegraph temporarily unreachable — test mode unaffected

Tools

Twenty tools across resolution, firmographic search, buyer signals, people search, semantic search, and research. Unsure of exact vocabulary (industries, size buckets, seniorities)? Call plan_targeting first — it turns a plain-language ICP into canonical filters the other tools accept. Verified email and phone finding are next; the catalog at GET /v1/tools is always the source of truth.

resolve_company

0.1 credits / call

Resolve a free-text company/brand name (or LinkedIn company URL, or bare domain) to its canonical LinkedIn company identity: org_id, canonical name, domain and confidence. Returns ranked candidates when the match is ambiguous. Call this first to get an org_id for the other tools.

paramtypedescription
query requiredstringCompany name, brand, LinkedIn company URL, or domain to resolve (e.g. "Stripe", "stripe.com").
curl -X POST https://api.gtm.dev/v1/tools/resolve_company \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"stripe"}'

enrich_company

1 credit / call

Fetch firmographics for a company: name, domain, industry, employee size range, HQ location, description, follower count and logo. Address the company by org_id (from resolve_company), domain, or name.

paramtypedescription
domainstringCompany website domain, e.g. "stripe.com".
namestringCompany name (exact-ish; use resolve_company first for fuzzy input).
org_idstringLinkedIn organization id (from resolve_company). Preferred.
curl -X POST https://api.gtm.dev/v1/tools/enrich_company \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"stripe.com"}'

who_is_advertising

1 credit / call

Find companies running ads in a country (LinkedIn Ads + Meta Ad Library), ranked by impressions then ad count. Optional keyword narrows to ads whose copy or landing pages mention it. Returns advertiser company identity, ad counts and platforms, paginated with limit/offset.

paramtypedescription
country requiredstringISO-2 country code where the ads ran (e.g. "US", "IN").
keywordstringKeyword to match in ad copy / advertiser name / landing URLs (e.g. "crm", "hubspot"). Empty = all advertisers in the country.
limitintegerAdvertisers per page (default 25, max 100).
offsetintegerRows to skip for pagination (default 0; offset+limit must not exceed 5000).
platformstring: linkedin | metaRestrict to one ad library.
curl -X POST https://api.gtm.dev/v1/tools/who_is_advertising \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"crm","country":"US"}'

who_is_hiring

1 credit / call

Find companies actively hiring for a role (e.g. "sales development", "machine learning engineer"), ranked by open-role count. Optionally filter by country and minimum number of openings, and paginate with limit/offset. Data is a weekly-refreshed index of LinkedIn + Indeed job postings.

paramtypedescription
role requiredstringRole or function keyword to match against the hiring index (e.g. "sdr", "data engineer", "marketing").
geo_countrystringCountry where the roles are located (e.g. "United States", "India"). Optional.
limitintegerCompanies per page (default 25, max 100).
min_openingsintegerOnly return companies with at least this many matching openings. Optional.
offsetintegerRows to skip for pagination (default 0; offset+limit must not exceed 5000).
curl -X POST https://api.gtm.dev/v1/tools/who_is_hiring \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role":"sdr","geo_country":"United States","min_openings":5}'

find_funded

1 credit / call

Find recently funded companies, newest round first. Filter by funding stage (e.g. "series_a", "seed"), lookback window in months (default 12), and minimum total funding in USD. Paginate with limit/offset.

paramtypedescription
limitintegerCompanies per page (default 25, max 100).
min_amountnumberMinimum total funding raised (USD). Optional.
monthsintegerLookback window: only rounds within the last N months (default 12).
offsetintegerRows to skip for pagination (default 0; offset+limit must not exceed 5000).
stagestringFunding stage of the LAST round, e.g. "seed", "series_a", "series_b". Optional.
curl -X POST https://api.gtm.dev/v1/tools/find_funded \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stage":"series_a","months":6}'

company_tech

1 credit / call

List the technologies detected on a company's website (CRM, analytics, marketing automation, infrastructure, ...), grouped by category. Address the company by org_id (from resolve_company) or domain.

paramtypedescription
domainstringCompany website domain, e.g. "stripe.com".
org_idstringLinkedIn organization id (from resolve_company). Preferred.
curl -X POST https://api.gtm.dev/v1/tools/company_tech \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"rippling.com"}'

build_list

2 credits / call

Describe the list you want in plain language and get the executed company list back in ONE call — we extract the criteria, choose between taxonomy filters and semantic search, canonicalize every value against the graph's real vocabularies, run the search, and return the rows plus the exact plan applied (in the same shapes search_companies / concept_search accept, so you can iterate deterministically). Supports excludes ("...but not staffing agencies"). When the description names people (titles/roles), the response includes a ready-made find_people follow-up. Companies only — chain find_people for the humans.

paramtypedescription
description requiredstringWhat you want, in plain language, e.g. "US payroll and HR software companies, 200+ employees, not staffing agencies" or "companies that feel like Stripe but for logistics".
limitintegerRows to return (default 25, max 50 in semantic mode / 100 in filter mode).
offsetintegerRows to skip for pagination. Mode-specific caps apply (semantic ~200 deep, filter 5000).
curl -X POST https://api.gtm.dev/v1/tools/build_list \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"description":"US payroll and HR software companies, 200+ employees, not staffing agencies","limit":25}'

company_ad_activity

1 credit / call

One company's advertising footprint across the public LinkedIn and Meta ad libraries: per-platform ad counts, impression floors where available, first/last seen dates, and up to 10 recent ads with copy snippets and landing domains. Address the company by org_id (from resolve_company), domain, or name.

paramtypedescription
domainstringCompany website domain, e.g. "stripe.com".
namestringCompany name (exact-ish; use resolve_company first for fuzzy input).
org_idstringLinkedIn organization id (from resolve_company). Preferred.
curl -X POST https://api.gtm.dev/v1/tools/company_ad_activity \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"hubspot.com"}'

company_funding

1 credit / call

Fetch one company's funding profile from the funding index: total raised, number of rounds, last round type and date, investor names, IPO / operating status, stock symbol and founded date. Address the company by org_id (from resolve_company), domain, or name. has_funding_data is false when the company has no profile in the funding index (~40% coverage of the company index).

paramtypedescription
domainstringCompany website domain, e.g. "stripe.com".
namestringCompany name (exact-ish; use resolve_company first for fuzzy input).
org_idstringLinkedIn organization id (from resolve_company). Preferred.
curl -X POST https://api.gtm.dev/v1/tools/company_funding \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"hubspot.com"}'

company_hiring

1 credit / call

One company's active hiring breakdown from the hiring index (weekly-refreshed LinkedIn + Indeed job postings, last 60 days): open-role counts per role/function and country, plus totals. Address the company by org_id (from resolve_company) or domain. Empty roles means no recent postings on record.

paramtypedescription
domainstringCompany website domain, e.g. "stripe.com".
org_idstringLinkedIn organization id (from resolve_company). Preferred.
curl -X POST https://api.gtm.dev/v1/tools/company_hiring \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"hubspot.com"}'

find_people

1 credit / call

Find people at a company from the people graph. Anchor on one company (org_id, domain, or name), then filter by titles, seniority, function, or location. Returns names, titles, locations and LinkedIn profile URLs — no contact details. Pagination: limit only (no offset yet — the people graph pages by internal cursor, not row offset); total_matching and page.has_more tell you when a company has more matching people than one call returns.

paramtypedescription
company requiredstringThe company to search at: org_id (from resolve_company), domain, or company name.
functionstringBusiness function (e.g. "sales", "marketing", "engineering", "finance", "product"). Optional.
geostringLocation filter — city, region, or country (e.g. "California", "Bengaluru", "United States"). Optional.
limitintegerMax people to return (default 25, max 100). No offset yet — narrow with titles/seniority/function instead of paging.
senioritystringSeniority level: "c-level", "vp", "director", "manager", or "ic". Optional.
titlesarrayJob titles to match (e.g. ["VP Sales", "Head of Growth"]). Optional.
curl -X POST https://api.gtm.dev/v1/tools/find_people \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"company":"rippling.com","function":"sales","seniority":"vp"}'

lookalikes

1 credit / call

Find the companies most similar to a seed company by embedding similarity over the company graph. Give one seed (org_id, domain, or name) and get its nearest neighbors — ideal for expanding a target list from your best accounts. Paginate with limit/offset (the similarity neighborhood is bounded: match quality degrades past the first ~200 rows, so offset+limit is capped at 200).

paramtypedescription
seed requiredstringThe seed company: org_id (from resolve_company), domain (e.g. "rippling.com"), or company name.
limitintegerNeighbors per page (default 25, max 50).
offsetintegerRows to skip for pagination (default 0). offset+limit is capped at 200 — similarity quality degrades deep in the neighborhood, so page depth is deliberately bounded.
curl -X POST https://api.gtm.dev/v1/tools/lookalikes \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"seed":"rippling.com"}'

normalize_title

0.1 credits / call

Normalize a free-text job title ("sdr", "head of eng", "vp sales") into canonical title strings plus a seniority and function guess. Titles resolve against the live title vocabulary (abbreviation-aware, typo-tolerant) layered over a curated shorthand map. Seniority values: owner, cxo, vp, director, manager, senior, entry, training. Functions follow LinkedIn's function vocabulary (sales, marketing, engineering, ...).

paramtypedescription
title requiredstringJob title text to normalize, e.g. "sdr", "head of eng", "growth marketer".
curl -X POST https://api.gtm.dev/v1/tools/normalize_title \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"head of eng"}'

plan_targeting

1 credit / call

Turn a plain-language targeting description (ICP, persona, market) into canonical, ready-to-use filters — the recommended FIRST call when you are unsure of exact vocabulary. Returns company filters (for search_companies / size_tam), people filters (for find_people), a concept_query (for concept_search when meaning matters more than filters), a filters-vs-semantic strategy recommendation, and suggested next tool calls. Resolution runs against the graph's real vocabularies, so returned values always match what the search tools accept.

paramtypedescription
description requiredstringPlain-language targeting, e.g. "VP+ finance leaders at mid-market US SaaS companies that feel API-first".
targetstring: companies | people | bothWhat the plan is for. Default "both".
curl -X POST https://api.gtm.dev/v1/tools/plan_targeting \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"description":"VP+ finance leaders at mid-market US SaaS companies that feel API-first"}'

research_company

5 credits / call

Build a structured research brief for one company: what they do, recent signals (funding, launches, hiring, expansion), concrete outreach hooks, and sources. Combines the company graph with live web research. Optionally steer it with a focus (e.g. "why would they buy sales tooling").

paramtypedescription
company requiredstringThe company to research: org_id (from resolve_company), domain, or company name.
focusstringOptional angle for the brief, e.g. "why would they buy sales tooling".
curl -X POST https://api.gtm.dev/v1/tools/research_company \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"company":"rippling.com","focus":"why would they buy sales tooling"}'

resolve_geo

0.1 credits / call

Canonicalize a free-text place — a country code or name ("US", "United Kingdom"), a city ("Bengaluru"), or a state/region ("Karnataka") — to the canonical geo labels used across the company and hiring indexes. Returns the country (with ISO-2 code), a [city, region, country] hierarchy when uniquely resolvable, and candidates[] when the name is ambiguous (e.g. "Springfield").

paramtypedescription
query requiredstringPlace to resolve, e.g. "Bengaluru", "US", "United Kingdom", "Karnataka".
curl -X POST https://api.gtm.dev/v1/tools/resolve_geo \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"Bengaluru"}'

search_companies

1 credit / call

Firmographic company search over the company index (~9M companies), ranked by LinkedIn follower count. Supports complex targeting: combine multiple industries/categories to INCLUDE (they OR together — a company matching any of them qualifies) with industries_exclude/categories_exclude to SUBTRACT, plus employee size range, HQ country/region/city, a name substring, or has_domain. At least one filter is required. Paginate with limit/offset (default 25 per page); the filters echo shows the canonical labels actually applied and the page object tells you if more rows exist. Use size_tam with the same filters to count the full matching universe.

paramtypedescription
categoriesarrayCategory keywords to INCLUDE — fuzzy-resolved against the granular category vocabulary and OR-combined with any industries. Categories cover the subset of companies carrying category tags. Optional.
categories_excludearrayCategory keywords to EXCLUDE — fuzzy-resolved against the category vocabulary; companies tagged with a matching category are always subtracted (companies without category tags are dropped too, matching product semantics). Optional.
citystringHQ city (e.g. "Bengaluru", "Austin"). Optional.
countrystringHQ country — name or ISO-2 code (e.g. "India", "US"). Optional.
has_domainbooleanOnly companies with a known website domain. Optional.
industriesarrayIndustry keywords to INCLUDE. Each entry fuzzy-resolves against BOTH the broad industry vocabulary and the granular category vocabulary; all matches OR together into one include group (a company matching any qualifies). Example: ["payroll", "hr software"]. Optional.
industries_excludearrayIndustry keywords to EXCLUDE. Each entry fuzzy-resolves against the industry vocabulary; matching companies are always subtracted from the results (companies with no industry on file are kept). Optional.
industrystringSingle industry keyword — shorthand for industries: [..]. Matched against BOTH the broad industry vocabulary and the more granular category vocabulary (e.g. "software", "payroll", "warehouse automation") — companies match on either. Optional.
limitintegerCompanies per page (default 25, max 100).
name_containsstringSubstring of the company name (e.g. "labs"). Optional.
offsetintegerRows to skip for pagination (default 0; offset+limit must not exceed 5000).
regionstringHQ state/region as stored on the company index (e.g. "California", "Karnataka"). Optional.
size_rangestringEmployee size bucket, exact values: "1 employee", "2-10 employees", "11-50 employees", "51-200 employees", "201-500 employees", "501-1,000 employees", "1,001-5,000 employees", "5,001-10,000 employees", "10,001+ employees". Compact forms like "51-200" or "1001-5000" are normalized. Optional.
curl -X POST https://api.gtm.dev/v1/tools/search_companies \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"industries":["payroll","hr software"],"industries_exclude":["staffing"],"country":"US","limit":50}'

size_tam

1 credit / call

Count how many companies in the company index (~9M companies) match a firmographic filter set — the TAM behind a search_companies page. Takes the same filters as search_companies (at least one required), including the multi include/exclude industry and category lists (includes OR together, excludes always subtract), and returns {count, filters} with the canonical filters actually applied.

paramtypedescription
categoriesarrayCategory keywords to INCLUDE — fuzzy-resolved against the granular category vocabulary and OR-combined with any industries. Categories cover the subset of companies carrying category tags. Optional.
categories_excludearrayCategory keywords to EXCLUDE — fuzzy-resolved against the category vocabulary; companies tagged with a matching category are always subtracted (companies without category tags are dropped too, matching product semantics). Optional.
citystringHQ city (e.g. "Bengaluru", "Austin"). Optional.
countrystringHQ country — name or ISO-2 code (e.g. "India", "US"). Optional.
has_domainbooleanOnly companies with a known website domain. Optional.
industriesarrayIndustry keywords to INCLUDE. Each entry fuzzy-resolves against BOTH the broad industry vocabulary and the granular category vocabulary; all matches OR together into one include group (a company matching any qualifies). Example: ["payroll", "hr software"]. Optional.
industries_excludearrayIndustry keywords to EXCLUDE. Each entry fuzzy-resolves against the industry vocabulary; matching companies are always subtracted from the count (companies with no industry on file are kept). Optional.
industrystringSingle industry keyword — shorthand for industries: [..]. Matched against BOTH the broad industry vocabulary and the more granular category vocabulary (e.g. "software", "payroll", "warehouse automation") — companies match on either. Optional.
name_containsstringSubstring of the company name (e.g. "labs"). Optional.
regionstringHQ state/region as stored on the company index (e.g. "California", "Karnataka"). Optional.
size_rangestringEmployee size bucket, exact values: "1 employee", "2-10 employees", "11-50 employees", "51-200 employees", "201-500 employees", "501-1,000 employees", "1,001-5,000 employees", "5,001-10,000 employees", "10,001+ employees". Compact forms like "51-200" or "1001-5000" are normalized. Optional.
curl -X POST https://api.gtm.dev/v1/tools/size_tam \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"industry":"software","country":"IN","size_range":"51-200"}'

who_uses_tech

1 credit / call

Find companies detected running a technology (e.g. "hubspot", "salesforce", "segment") via website tech-stack scans, ranked by detection confidence. Optionally filter by HQ country and employee size range, and paginate with limit/offset. The tool input is matched against the scanner's tool vocabulary (exact name preferred, fuzzy fallback); matched_tools echoes what was searched.

paramtypedescription
tool requiredstringTechnology name to look for, e.g. "hubspot", "salesforce", "google-analytics". Required.
countrystringHQ country — name or ISO-2 code (e.g. "India", "US"). Optional.
limitintegerCompanies per page (default 25, max 100).
offsetintegerRows to skip for pagination (default 0; offset+limit must not exceed 5000).
size_rangestringEmployee size bucket, exact values: "1 employee", "2-10 employees", "11-50 employees", "51-200 employees", "201-500 employees", "501-1,000 employees", "1,001-5,000 employees", "5,001-10,000 employees", "10,001+ employees". Compact forms like "51-200" or "1001-5000" are normalized. Optional.
curl -X POST https://api.gtm.dev/v1/tools/who_uses_tech \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tool":"hubspot","country":"IN","size_range":"51-200"}'

Credits & modes

Usage-priced, metered per call. Signup includes 1,000 live credits — no card. Test-mode keys never spend credits and never touch the live graph. Live calls that error are not billed.

tool classtoolsper call
resolveresolve_company · resolve_geo · normalize_title0.1 credit
search, enrich & signalssearch_companies · size_tam · concept_search · lookalikes · find_people · plan_targeting · enrich_company · who_is_advertising · who_is_hiring · find_funded · company_tech · company_* signal mirrors · who_uses_tech1 credit
researchresearch_company5 credits

balance and per-tool usage are live in the console. need more credits? — usage-priced packs are coming; until then, reply to your signup email.