Skip to main content
AI-powered cold email infrastructure

Cold email infrastructure that owns its data supply.

outreachstack builds lead sets by querying a 343M-domain feed it ingests daily, generates and then verifies every DNS record a sending domain needs, and sends on a scheduler that halts the sequence the moment someone replies. One /api/v1 surface — every operation is an HTTP call, and every lead carries its provenance.

outreachstacktenant#1
curl -sX POST /api/v1/icps/draft-from-url
criteria drafted — versioned, yours to edit first
curl -sX POST /api/v1/icps/estimate
audience sized — costs nothing, commits nothing
curl -sX POST /api/v1/leads/build
leads promoted — deduped, provenance + lawful basis
curl -s /api/v1/sending-domains/$ID/records
MX, SPF, DKIM, DMARC — each with what breaks
curl -sX POST /api/v1/campaigns/$ID/launch
dry run by default — a reply halts the sequence
// publishing those DNS records is still yours.
343M
domains in the feed we ingest
~300k/day
new registrations in the daily delta
1,570
zones the feed covers
The pipeline

Four stages, one system. What each stage emits is what the next one queries.

01Supply

A domain lake we ingest, not a list we rent

A daily bulk delta lands in ClickHouse, and MX, TXT, SPF and CNAME records are resolved into signals before anyone is contacted. The distinction that matters: an SPF `include:shops.shopify.com` proves a company *sends through* Shopify, while a CNAME to `myshopify.com` proves the storefront *runs on* it — and only the second can install your app. An ICP is a versioned query over that, not a CSV someone else already sold four times.

acme-competitor.com
providergoogle-workspace (mx)
platformshopify (cname)
techklaviyo (txt)
registered2026-07-19
02Domains

Every record a sending domain needs, generated then verified

The API emits the exact MX, SPF, DKIM and DMARC records for a domain — each one carrying what breaks without it — then checks them from public DNS and reports the value it actually observed. Not a boolean: `present but wrong` is the common case and the dangerous one. The SPF evaluator is a real RFC 7208 implementation, so it counts the ten-lookup limit across the whole expansion tree instead of guessing. Publishing the records is still yours to do; automating that is next.

MXmx1.outreachstack.orgverified
SPFv=spf1 ip4:203.0.113.10 ~allverified
DKIMos2026._domainkey · rsa-2048verified
DMARCv=DMARC1; p=quarantine; rua=mailto:…verified
03Send

Copy a model writes, on a scheduler that will not misfire

Copy is generated per campaign from the ICP and the offer, and every model call is retained, so any line traces back to the request that produced it. Sends are claimed out of Postgres under a per-mailbox daily cap inside the recipient's own business hours — and one reply halts every pending step for that person, across every campaign, not just the one they answered.

window09:00–17:00 (the lead's tz)
capper mailbox, per day (warmup)
haltedno — rechecked at claim time
claimFOR UPDATE SKIP LOCKED
// one reply halts every campaign for that person
04Deliverability

Bounces and complaints, handled the moment they land

The MTA posts bounces and complaints back as webhooks; they are classified, attributed to the mailbox and domain that produced them, and the address goes onto a suppression list every later send is checked against. New mailboxes climb a warmup ramp and a campaign cannot launch past a mailbox that has not started one. The control loop that throttles, rotates and pauses on its own is documented and not yet built — a human runs those runbooks today.

What runs, and what doesn't yet
  • daily cap
  • sends
Dogfooded, not demoed

Tenant #1 is us, and the first send went to spam.

outreachstack.org is a real sending domain on our own Postal MTA and our own IPs — deliberately separate from the brand domain you're reading this on, so a reputation problem on one can never touch the other. It authenticates cleanly: spf=pass dkim=pass dmarc=pass, mail-tester at 9/10. Then the first live message to a Gmail account was filed as spam anyway, which is the lesson a spec sheet will not teach you and which is written up in our own deliverability runbook. We have no customer logos to show you; we're pre-launch, and this page will say so until it isn't true.

Built for agents, not just humans

Every operation is an HTTP call — the dashboard is one client of it, not the product.

Drafting an ICP from a competitor's URL, sizing the audience before you pay to build it, generating a sequence's copy, connecting a mailbox, launching a campaign — none of it exists only behind a click. An autonomous agent and the dashboard sit on the same /api/v1 surface, authenticated with the same scoped, tenant-bound keys and subject to the same row-level tenant isolation as a human operator.

UI

The dashboard, for operators who want to look at the data.

CLI

A typed client over the same API. Commands whose endpoint isn't wired yet exit `4` and name the endpoint they are waiting on, rather than faking a success.

Agents

Ordinary API consumers with scoped keys — no privileged back door. Anything that spends money or sends mail takes `dry_run=true`, and long jobs return an envelope to poll.

Infrastructure you script, not a dashboard you babysit.