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.
Plain-language audience description. Steers your agent's filter choices; the search itself uses the structured filters below.
Job titles, contains-matched.
LinkedIn industry taxonomy, e.g. "Hospitals and Health Care".
Countries or cities.
Employee-count range.
Maximum leads to return.
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 }'
{
"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"
}
}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.
Identity handles: full_name or first_name+last_name, plus company_domain; or linkedin_url; or email. At least one identifiable combination.
work_email · mobile_phone · profile
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.
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"] }'
{
"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" }
}verify_email
Two-stage deliverability check with real catch-all analysis. The six statuses actually mean something:
Mailbox confirmed. Safe to send.
Rejected or disposable. Do not send.
Domain accepts everything, and our specialist confirmed this mailbox is deliverable. Safe to send.
Catch-all domain, deliverability unconfirmed. Send at your own bounce-risk.
Deliverable but flagged (e.g. quality signals). Use judgment.
No provider could answer. The call settles as a free miss.
Request body: {"email": "…"}. Response also carries is_catch_all_domain and checked_at.
curl https://api.gtmrouter.dev/v1/verify_email \ -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \ -d '{"email": "bswift@unified-imaging.com"}'
{
"result": {
"email": "bswift@unified-imaging.com",
"status": "catch_all_valid",
"is_catch_all_domain": true,
"checked_at": "2026-09-02T…"
},
"gtmrouter": { "credits_charged": "1" }
}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.
hiring (live job posts) · funding · news · job_change · technology
curl https://api.gtmrouter.dev/v1/find_intent \ -H "Authorization: Bearer YOUR_GTMROUTER_API_KEY" \ -d '{"company_domains": ["stripe.com"], "signals": ["hiring","funding"]}'
{
"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" }
}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.
Desired steady-state capacity. Sizing: ~25 sends/day per mailbox, 5 mailboxes per domain.
Brand word used to derive sending-domain candidates (e.g. acme → getacme.com).
Identity stamped on provisioned mailboxes.
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.
{
"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-…"
}
}{
"result": {
"status": "purchased",
"operation_id": "72bec6ce-…",
"domains": ["getacme.com"]
},
"gtmrouter": { "credits_charged": "4000" }
}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.
{email, first_name?, last_name?, company_name?, custom?}
{subject?, body, wait_days} — bodies support variables like {{first_name}} and {{company_name}}. A step without a subject continues the thread.
{timezone, days, start_hour, end_hour} — IANA timezone (e.g. America/Chicago), default weekdays 9–17.
Replies always stop the sequence for that lead. Not configurable.
{
"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" }
}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.
Absent → preview. Present + approved → launch.
{
"result": {
"status": "launched",
"campaign_id": "883c0efe-…",
"mailboxes_attached": 4,
"leads_active": 47,
"leads_suppressed_at_launch": 1
}
}get_replies
Read campaign replies, newest first. Repliers are automatically suppressed from all future contact — reading is how your agent decides what happens next.
Poll pattern: pass your last read time.
classification: interested · not_interested · out_of_office · unsubscribe · bounce · other (nullable while unclassified).
{
"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": "…"
}] }
}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.
| Model | Credits / 1k tokens |
|---|---|
| anthropic/claude-sonnet-5 | 0.5 |
| anthropic/claude-haiku-4.5 | 0.25 |
| openai/gpt-5-mini | 0.1 |
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"}] }'
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.
{
"credits_balance": "8672.4",
"credits_reserved": "0",
"credits_available": "8672.4",
"last_30_days": [
{ "verb": "enrich", "calls": 3, "credits_charged": "15" }
]
}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.
| Tool | Maps to |
|---|---|
| find_leads · enrich · verify_email · find_intent | the data verbs above |
| setup_sending · create_campaign · launch_campaign | the sending verbs (same approvals) |
| get_replies | /v1/get_replies |
| get_usage · get_operation · get_request | the state reads |
Setup guide: Add to your agent.
claude mcp add --transport http gtmrouter https://mcp.gtmrouter.dev/mcp \ --header "Authorization: Bearer YOUR_GTMROUTER_API_KEY"