catchall.in for AI agents
You are setting up registrations, trials or monitoring for a person, and every service on the way wants an email address it can verify. This page is the walkthrough: real mailboxes on your human's own domains, unlimited addresses that need no creating, and confirmation mail read over POP3S — protocols your runtime's standard library already speaks.
What you get
Every address at the issued subdomain already exists. Invent a fresh one per registration — signup-7f2q@mail.example.com, billing-x1@mail.example.com — nothing to create, and it all lands in one mailbox you poll.
The domain is your human's own zone, so sender trust and control stay with them; we take one subdomain and never touch the apex. Credentials are issued once at creation — no OAuth dance, no browser session to keep alive.
There is deliberately no HTTP endpoint for reading mail — messages never enter the API layer at all. Pickup is plain POP3S (995) or IMAPS (993). The management API is documented in full at /api.
Set up in three calls
1. Create the domain. Two DNS paths. manual works with any DNS: the answer returns mailbox credentials plus the TXT challenge and MX record to set. cf_token writes the records for you — use it when your human connected their Cloudflare account on the Integrations page (omit the token field) or handed you a scoped bootstrap token (the exact three permissions are listed at /api).
curl -X POST https://catchall.in/v1/domains \
-H "Authorization: Bearer ck_your_key" \
-H "Idempotency-Key: create-example-com-1" \
-H "Content-Type: application/json" \
-d '{"zone_name": "example.com", "path": "manual"}'2. Set the records, then verify. Relay the TXT and MX to whoever runs the DNS — possibly you. Then POST /v1/domains/{id}/verify and poll GET /v1/domains/{id} until state is active. DNS moves in minutes, not milliseconds: poll at tens of seconds, not in a tight loop. On the cf_token path there is nothing to set — the domain activates on its own.
3. Fetch the mail. Host is mx_host on the domain object (also the MX target). There is no parser on our side — the message reaches you verbatim, extracting the code is your regex:
import poplib, re, time
HOST = "mx1.catchall.in" # mx_host from GET /v1/domains/{id}
USER, PASSWORD = "<username>", "<password>" # from the create response - shown once
deadline = time.time() + 180
while time.time() < deadline:
box = poplib.POP3_SSL(HOST, 995)
box.user(USER); box.pass_(PASSWORD)
count = len(box.list()[1])
if count:
body = b"\n".join(box.retr(count)[1]).decode(errors="replace")
m = re.search(r"\b\d{4,8}\b", body)
if m:
print(m.group()); box.quit(); break
box.quit()
time.sleep(5) # one POP3 session per source IP - poll sequentiallyGround rules
Retries are safe by construction — use that. Every POST that returns a secret takes an Idempotency-Key; repeating the same key and body replays the original answer for 15 minutes, afterwards it answers 410 and only a rotation issues a new secret. Rate limits answer 429 with Retry-After in seconds — honor it.
One POP3 session per mailbox from one source IP. Parallel streams come from more mailboxes, not more connections: the Pro tier issues five mailboxes on five subdomains under one parent domain.
Mail lives 72 hours, then it is deleted on our side. Fetch promptly; what you downloaded is yours.
Mailboxes only receive. Sending is not part of the service at all, and the acceptable-use policy applies to the traffic your registrations create elsewhere. If a check fails or a domain degrades, the panel and GET /v1/domains/{id} show the state and the reason — surface them to your human instead of retrying blind.
Cheat sheet
Dense on purpose — keep it in your context:
base_url: https://catchall.in
auth: Authorization: Bearer <key from your human>
mail_pickup: POP3S :995 / IMAPS :993 (no HTTP mail endpoint - by design)
addresses: any local part @ <label>.<zone> - nothing to pre-create
mail_ttl: 72 hours, then deleted
money: usd_micro, integer ($10 = 10000000); errors: {"error": "machine_code"}
pricing: standard $10 / 30 days - pro $15, five mailboxes on five subdomains
idempotency: Idempotency-Key on domain create / verify / rotate-password / key create
full_docs: https://catchall.in/api