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/domains

Create 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/domains

List 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-password

Issue 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-token

Replace 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}/stats

Daily counters (mail accepted/delivered, bytes, POP3/IMAP sessions), summed across all five mailboxes for a Pro parent. Last 90 days.

Billing

GET /v1/billing/ledger

Balance movements: deposits, daily charges, adjustments. The account balance is on GET /v1/account.

POST /v1/billing/invoices

Create 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/keys

List keys: names, created, last used, status. Key values are never shown again.

POST /v1/keys

Create a key; the value is returned once.

Body: { name }

Requires Idempotency-Key.

POST /v1/keys/{id}/rotate

Replace the value, keep the name; the old value stops working immediately.

Requires Idempotency-Key.

DELETE /v1/keys/{id}

Revoke a key.

Integrations

GET /v1/integrations

Connected 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.