POST/v1/find_leads0.2 CR / LEAD RETURNED

find_leads

Search 200M+ B2B contacts with structured filters. Returned leads carry full profiles with masked emails — chain each into enrich to reveal the verified address. Charged only for leads actually returned, capped at your requested limit. Zero results settles as a free miss.

Request body
audiencestring · 3–2000REQUIRED

Plain-language audience description. Steers your agent's filter choices; the search itself uses the structured filters below.

titlesstring[] · ≤25

Job titles, contains-matched.

industriesstring[] · ≤25

LinkedIn industry taxonomy, e.g. "Hospitals and Health Care".

locationsstring[] · ≤25

Countries or cities.

company_headcount{min?, max?}

Employee-count range.

limitint · 1–200 · default 25

Maximum leads to return.

Request · curl
curl https://api.gtmrouter.dev/v1/find_leads \
  -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \
  -d '{
    "audience": "healthcare executives",
    "titles": ["Chief Executive Officer"],
    "industries": ["Hospitals and Health Care"],
    "limit": 50
  }'
Response · 200
{
  "result": {
    "leads": [{
      "fingerprint": "fp1:2d367ac5…",
      "full_name": "Benjamin Swift",
      "title": "Chief Executive Officer",
      "company_name": "Unified Imaging",
      "company_domain": "unified-imaging.com",
      "work_email": null,   // masked — use enrich
      "linkedin_url": "https://linkedin.com/in/…",
      "location": "Cary, North Carolina, US"
    }, … 49 more],
    "total_found": 10828
  },
  "gtmrouter": {
    "request_id": "c4126c30-…",
    "credits_charged": "10",
    "credits_available": "8672.4"
  }
}
The envelope is the invoice. Every verb returns gtmrouter.credits_charged — exact, per call, misses free.
POST/v1/enrich5 CR / HIT · MISSES FREE

enrich

Reveal a person's verified work email and profile — the only verb that can also return a mobile number. Provide an email, a LinkedIn URL, or a name + company domain. Fresh results are cached in your workspace for 90 days; repeats return from_cache: true.

Request body
personobjectREQUIRED

Identity handles: full_name or first_name+last_name, plus company_domain; or linkedin_url; or email. At least one identifiable combination.

wantenum[] · default ["work_email"]

work_email · mobile_phone · profile

max_creditscredit string · optional

Spend ceiling for this call.

work_email_status in the result: valid · catch_all · unknown · not_found. A stale or unverified source degrades to unknown — run verify_email before gating sends on it.

Request · curl
curl https://api.gtmrouter.dev/v1/enrich \
  -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \
  -d '{
    "person": {
      "full_name": "Benjamin Swift",
      "company_domain": "unified-imaging.com"
    },
    "want": ["work_email", "mobile_phone"]
  }'
Response · 200
{
  "result": {
    "outcome": "hit",
    "contact": {
      "work_email": "bswift@unified-imaging.com",
      "work_email_status": "valid",
      "mobile_phone": "+1 …",
      "title": "Chief Executive Officer"
    },
    "from_cache": false
  },
  "gtmrouter": { "credits_charged": "5" }
}
POST/v1/verify_email1 CR / CALL

verify_email

Two-stage deliverability check with real catch-all analysis. The six statuses actually mean something:

Statuses
valid

Mailbox confirmed. Safe to send.

invalid

Rejected or disposable. Do not send.

catch_all_valid

Domain accepts everything, and our specialist confirmed this mailbox is deliverable. Safe to send.

catch_all_unknown

Catch-all domain, deliverability unconfirmed. Send at your own bounce-risk.

risky

Deliverable but flagged (e.g. quality signals). Use judgment.

unknown

No provider could answer. The call settles as a free miss.

Request body: {"email": "…"}. Response also carries is_catch_all_domain and checked_at.

Request · curl
curl https://api.gtmrouter.dev/v1/verify_email \
  -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \
  -d '{"email": "bswift@unified-imaging.com"}'
Response · 200
{
  "result": {
    "email": "bswift@unified-imaging.com",
    "status": "catch_all_valid",
    "is_catch_all_domain": true,
    "checked_at": "2026-09-02T…"
  },
  "gtmrouter": { "credits_charged": "1" }
}
POST/v1/find_intent10 CR / SIGNAL COMPANY + 0.5 CR / SCANNED

find_intent

Buying-intent signals for company domains. Each scanned company costs 0.5 credits; companies that actually return signals cost 10. A 100-company sweep with 8 signal hits charges 126 credits total. Signals carry evidence URLs where the source provides them.

Request body
company_domainsstring[] · 1–100REQUIRED
signalsenum[] · default ["hiring","funding"]

hiring (live job posts) · funding · news · job_change · technology

Request · curl
curl https://api.gtmrouter.dev/v1/find_intent \
  -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \
  -d '{"company_domains": ["stripe.com"], "signals": ["hiring","funding"]}'
Response · 200
{
  "result": { "signals": [{
    "company_domain": "stripe.com",
    "signal": "hiring",
    "summary": "Hiring: UX Research Manager, Payments at Stripe",
    "observed_at": "2026-09-01",
    "evidence_url": "https://www.linkedin.com/jobs/view/…"
  }] },
  "gtmrouter": { "credits_charged": "5" }
}
POST/v1/setup_sendingQUOTE FREE · 1,500 CR/DOMAIN + 750 CR/MAILBOX/MO

setup_sending

Provision warmed sending capacity — domains, mailboxes, DNS and warmup handled end to end. This is a quote → human approval → purchase verb: without a token you get a free quote and a single-use confirmation_token (15-minute expiry); a human approves it in the console; the same call with the token executes. Requires the assets:purchase scope and an Idempotency-Key header.

Request body
emails_per_weekint · 50–50000REQUIRED

Desired steady-state capacity. Sizing: ~25 sends/day per mailbox, 5 mailboxes per domain.

brand_hintstring · optional

Brand word used to derive sending-domain candidates (e.g. acme → getacme.com).

sender{first_name, last_name} · optional

Identity stamped on provisioned mailboxes.

confirmation_tokenstring · optional

Absent → quote. Present + console-approved → purchase.

Purchase returns an operation_id — provisioning completes asynchronously (typically up to 48h for mailboxes to go live); poll GET /v1/operations/:id. Monthly upkeep is billed automatically per active mailbox as disclosed in the quote.

Step 1 · Quote (free)
{
  "result": {
    "status": "quote",
    "quote": {
      "domains": 2, "mailboxes": 4,
      "setup_credits": "1000",
      "upkeep_credits_per_month": "3000",
      "renewal_cadence": "monthly",
      "ready_estimate": "days",
      "quote_expires_at": "…"
    },
    "confirmation_token": "69e36400-…"
  }
}
Step 2 · a human approves in the console
Step 3 · Same call + token → purchased
{
  "result": {
    "status": "purchased",
    "operation_id": "72bec6ce-…",
    "domains": ["getacme.com"]
  },
  "gtmrouter": { "credits_charged": "4000" }
}
POST/v1/campaignsFREE

create_campaign

Create a draft campaign — drafts never send. Suppressed and invalid addresses are filtered automatically before anything reaches sending infrastructure, and the counts are reported back. Requires campaign:write scope and an Idempotency-Key header.

Request body
namestring · ≤120REQUIRED
leadsobject[] · 1–5000REQUIRED

{email, first_name?, last_name?, company_name?, custom?}

stepsobject[] · 1–8REQUIRED

{subject?, body, wait_days} — bodies support variables like {{first_name}} and {{company_name}}. A step without a subject continues the thread.

sending_windowobject · optional

{timezone, days, start_hour, end_hour} — IANA timezone (e.g. America/Chicago), default weekdays 9–17.

stop_on_replytrue · always

Replies always stop the sequence for that lead. Not configurable.

Response · 200
{
  "result": {
    "campaign_id": "883c0efe-…",
    "name": "Healthcare exec outreach",
    "state": "draft",
    "leads_accepted": 48,
    "leads_suppressed": 2,
    "suppressed_reasons": { "unsubscribed": 2 },
    "created_at": "…"
  },
  "gtmrouter": { "credits_charged": "0" }
}
Drafts are inert. Nothing is contacted until launch_campaign passes human approval.
POST/v1/launch_campaignFREE · HUMAN-APPROVED

launch_campaign

Real emails will send. Same two-step shape as purchases: call without a token for a launch preview (active mailboxes, lead count) + a single-use confirmation_token; a human approves in the console; call again with the token to launch. Requires the campaign:launch scope, an Idempotency-Key header, and active sending capacity from setup_sending.

At launch, suppression is re-checked: any lead suppressed since drafting is removed before activation. If a removal cannot be confirmed, the launch aborts — the campaign stays a draft. GTMRouter fails closed on suppression, always.

Request body
campaign_iduuidREQUIRED
confirmation_tokenstring · optional

Absent → preview. Present + approved → launch.

Response · launched
{
  "result": {
    "status": "launched",
    "campaign_id": "883c0efe-…",
    "mailboxes_attached": 4,
    "leads_active": 47,
    "leads_suppressed_at_launch": 1
  }
}
POST/v1/get_repliesFREE

get_replies

Read campaign replies, newest first. Repliers are automatically suppressed from all future contact — reading is how your agent decides what happens next.

Request body
campaign_idstring · optional
sinceISO timestamp · optional

Poll pattern: pass your last read time.

limitint · 1–200 · default 50

classification: interested · not_interested · out_of_office · unsubscribe · bounce · other (nullable while unclassified).

Response · 200
{
  "result": { "replies": [{
    "reply_id": "0368c0f6-…",
    "campaign_id": "883c0efe-…",
    "from_email": "prospect@company.com",
    "subject": "Re: Quick question",
    "snippet": "Sounds interesting — tell me more",
    "classification": "interested",
    "received_at": "…"
  }] }
}
POST/v1/llm/chatPER 1K TOKENS · BY MODEL

llm

OpenAI-compatible chat completions so your agent never needs a second key mid-loop. Allowlisted models only; unknown fields pass through. Streaming is supported — streamed calls settle a provisional charge that is reconciled to the exact token count, with the difference refunded automatically.

ModelCredits / 1k tokens
anthropic/claude-sonnet-50.5
anthropic/claude-haiku-4.50.25
openai/gpt-5-mini0.1
Request · curl
curl https://api.gtmrouter.dev/v1/llm/chat \
  -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \
  -d '{
    "model": "anthropic/claude-haiku-4.5",
    "messages": [{"role":"user","content":"Draft a 2-line opener for a hospital CEO"}]
  }'
GET/v1/usage · /v1/requests/:id · /v1/operations/:idFREE

Usage & state

GET /v1/usage — balance, reserved holds, available credits, per-verb usage for the last 30 days. GET /v1/requests/:id — status and final billing of any previous request, including interrupted streams. GET /v1/operations/:id — async operation progress: queued → running → waiting_external → succeeded | partially_succeeded | failed.

GET /v1/usage · 200
{
  "credits_balance": "8672.4",
  "credits_reserved": "0",
  "credits_available": "8672.4",
  "last_30_days": [
    { "verb": "enrich", "calls": 3, "credits_charged": "15" }
  ]
}
MCPhttps://mcp.gtmrouter.dev/mcp

MCP tools

Every verb is also a hosted MCP tool — same execution path, same metering, same approvals. Tools accept an optional idempotency_key argument; reuse the same value when retrying an external action.

ToolMaps to
find_leads · enrich · verify_email · find_intentthe data verbs above
setup_sending · create_campaign · launch_campaignthe sending verbs (same approvals)
get_replies/v1/get_replies
get_usage · get_operation · get_requestthe state reads

Setup guide: Add to your agent.

claude
claude mcp add --transport http gtmrouter https://mcp.gtmrouter.dev/mcp \
  --header "Authorization: Bearer YOUR_GTMROUTER_API_KEY"