Management API
Everything the panel does, over plain HTTPS with an API key: domains, billing, keys, integrations. Base URL https://catchall.in, JSON in and out. Working as an AI agent for a person? Start here.
Authentication
Create an API key on the Account page (or via POST /v1/keys with a browser session). Send it as a bearer token; keys act for the whole account and can be rotated or revoked at any time.
curl https://catchall.in/v1/account \ -H "Authorization: Bearer ck_your_key"
Conventions
Errors are JSON: {"error": "machine_code", "detail": "optional human text"}. Rate limits answer 429 with Retry-After in seconds. Money is always usd_micro — integer millionths of a dollar: $10 is 10000000. Timestamps are UTC ISO-8601.
Operations that return a secret (domain creation, resume, password rotation, key creation) require an Idempotency-Key header — any unique string. Repeating the same key with the same body replays the original answer instead of running twice; the secret inside stays replayable for 15 minutes, afterwards the replay answers 410 secret_expired and only a rotation can issue a new one.
Domains
POST /v1/domainsCreate a domain. Two DNS paths: cf_token (we write the MX record via a Cloudflare token — pasted in the body, or taken from your connected Cloudflare integration when the field is omitted) and manual (we issue a TXT challenge and MX instructions, you set the records anywhere). Tier pro provisions five mailboxes on five subdomains (one password, up to five parallel POP3 sessions from one machine).
Body: { zone_name, path: "cf_token"|"manual", label?, tier?: "standard"|"pro", bootstrap_token? }
Returns: 201 with domain_id, fqdn, state, mailbox credentials (shown once) and DNS instructions on the manual path. With access verified but balance short: the domain is saved as a draft — 402 with domain_id on cf_token, 201 with note insufficient_funds_draft on manual. Drafts are released after 7 days unpaid.
Errors: zone_taken, zone_taken_by_you (with domain_id of your own draft), bootstrap_invalid, zone_not_found, zone_not_active, insufficient_funds
Requires Idempotency-Key.
GET /v1/domainsList your domains. Pro subdomains come nested under the parent as subdomains[], not as separate rows.
GET /v1/domains/{id}One domain with state, last_error, DNS instructions while records are pending, and subdomains[] for Pro.
POST /v1/domains/{id}/verify“I set the records — check.” Runs the pending DNS checks; on a cf_token domain stuck in created it resumes provisioning and re-issues mailbox credentials. On a Pro parent it also queues the checks of every subdomain. Checks before first activation require a funded balance (402 otherwise; the draft stays).
Requires Idempotency-Key.
POST /v1/domains/{id}/rotate-passwordIssue a new mailbox password (returned once, applies when the mail host confirms; the old one stops working then). On Pro the same new password goes to all five mailboxes.
Errors: mailbox_not_ready (nothing provisioned yet), child_subdomain (rotate via the parent)
Requires Idempotency-Key.
POST /v1/domains/{id}/cf-tokenReplace the Cloudflare token of a live cf_token domain (e.g. before the old one expires).
Errors: not_cf_path, child_subdomain
DELETE /v1/domains/{id}Release the domain: mailboxes and our DNS records are removed, the zone becomes available again. Pro releases all five subdomains; releasing a single subdomain is refused (child_subdomain).
Requires Idempotency-Key.
GET /v1/domains/{id}/statsDaily counters (mail accepted/delivered, bytes, POP3/IMAP sessions), summed across all five mailboxes for a Pro parent. Last 90 days.
Billing
GET /v1/billing/ledgerBalance movements: deposits, daily charges, adjustments. The account balance is on GET /v1/account.
POST /v1/billing/invoicesCreate a top-up invoice. Crypto invoices return a payment_url to the processor's page; the deposit is credited when the payment is confirmed on their side and verified on ours. First top-up from $10.
Body: { amount_usd_micro }
Requires Idempotency-Key.
GET /v1/billing/invoices/{id}Invoice status: pending, paid, or lost to expiry.
API keys
GET /v1/keysList keys: names, created, last used, status. Key values are never shown again.
POST /v1/keysCreate a key; the value is returned once.
Body: { name }
Requires Idempotency-Key.
POST /v1/keys/{id}/rotateReplace the value, keep the name; the old value stops working immediately.
Requires Idempotency-Key.
DELETE /v1/keys/{id}Revoke a key.
Integrations
GET /v1/integrationsConnected external accounts: provider, status, alias. Stored keys are never returned.
POST /v1/integrations/{provider}Connect cloudflare ({token} — the same three-permission token as in the wizard; afterwards domains can be added without pasting it), namesilo ({api_key}), virustotal ({api_key}, 64 hex) or namecheap ({api_user, api_key} — accepted as unchecked until our mail machine, the only allow-listed IPv4, verifies it). Keys are verified on connect where the provider allows it; a rejected key is not stored.
DELETE /v1/integrations/{id}Disconnect; the stored key is wiped immediately. Live domains keep working — their zone-scoped tokens are independent.
Mail pickup (not HTTP)
Each domain (five per Pro domain) is one catch-all mailbox: any address at the subdomain lands there. Connect with the issued credentials over POP3S 995 or IMAPS 993. One POP3 session per mailbox from the same source IP at a time — parallelism comes from more mailboxes (Pro), not more connections. Messages are deleted after 72 hours on our side; what you have downloaded is yours.