API
A tiny REST API for receiving mail at any address you pick. Free. No mailbox to create, no quota to track — give us a string, point your test signup at it, then read what arrives.
Base URL
https://api.mail.cx/v1All endpoints live under /v1 and require HTTPS.
Authentication
Every request carries a token in the x-api-token header. Register an account, then create a token from Dashboard → Tokens. Tokens look like tm_live_… (72 chars).
curl https://api.mail.cx/v1/inbox/test@mail.cx \
-H "x-api-token: tm_live_your_token_here"Receive mail
Pick any local-part under one of the system domains (or a custom domain you own) and read the inbox. Nothing is created server-side — the SMTP gateway accepts mail for any address under a system domain, and the inbox endpoint just returns whatever is currently buffered. Mail lives for one hour.
/v1/inbox/:addressLong-poll one address. Holds up to 25s for new mail, then returns 200 with results or 204 on timeout. Query params: since (cursor), count (default 1), limit (default 20, max 50), from, subject.
/v1/inbox/:addressClear the inbox — delete every email currently buffered for the address.
/v1/email/:idRead one full email (text body, HTML body, attachments metadata, headers).
/v1/email/:id/rawStream the original .eml. Returns message/rfc822. 410 if the message has expired.
/v1/email/:id/attachments/:indexDownload one attachment by zero-based index. Returns the original Content-Type.
/v1/email/:idDelete a single email. 204 No Content on success.
Wait for the first email:
curl "https://api.mail.cx/v1/inbox/test@mail.cx" \
-H "x-api-token: tm_live_your_token_here"
// → 200
{
"emails": [
{
"id": "uuid",
"from_email": "sender@example.com",
"subject": "Verify your email",
"preview_text": "Your code is 123456",
"created_at": "2026-05-14T12:00:00Z"
}
],
"next_since": "1715706012"
}Real-time push (SSE)
Server-Sent Events over plain HTTP. The browser EventSource API handles reconnection and Last-Event-ID replay automatically. Pass the token as a query parameter — EventSourcecannot set custom headers.
/v1/sse/addr?address=<addr>&token=<token>Stream events for a single address.
/v1/sse/user?token=<token>Stream events across every owned address.
const es = new EventSource(
"https://api.mail.cx/v1/sse/user?token=tm_live_your_token_here"
);
es.addEventListener("email", (e) => {
const data = JSON.parse(e.data);
// { id, address, from, subject, preview }
});Custom domains
Add a domain you own and receive mail on every address under it. Verification requires two DNS records: a TXT record at _tempmail.<domain> with value tempmail-verify=<token>, and an MX record pointing to smtp.mail.cx. Verifier polls every 5 minutes; pending domains time out after 72 hours.
/v1/domainsAdd a custom domain. Body: { domain }. Returns the DNS records to configure.
/v1/domainsList your custom domains with verify_status (pending / verified / failed).
/v1/domains/:idRemove a custom domain.
/v1/domain/:domainLong-poll every address under one of your verified custom domains. Same query params as /v1/inbox/:address.
Account
/v1/configServer config: system domains list, local-part rules, default TTL, OAuth client IDs. Public — no auth. Cached 5 min.
/v1/meLong-poll across every owned address.
/v1/tokensCreate a new API token. Body: { name? }. The plaintext token is returned only once.
/v1/tokensList your tokens (id, name, prefix, created_at, last_used_at).
/v1/tokens/:idRevoke a token. Cache invalidation is immediate.
Rate limit
10 requests per second per user, enforced by a sliding-window counter in Redis. A 429 response with { "error": "rate_limit_exceeded" } sets a Retry-After header. Long-poll concurrency is separately capped (one in-flight wait per token, ten per address) to keep one client from holding the connection pool.
Errors
Errors are JSON with a machine-readable error key. The HTTP status code carries the category.
{ "error": "rate_limit_exceeded" }| Status | Description |
|---|---|
| 400 | Bad request. |
| 401 | Missing or invalid x-api-token. |
| 403 | Account disabled, or you don't own the custom domain. |
| 404 | Resource not found. |
| 410 | Email body expired (error: email_expired). |
| 429 | Rate limit (rate_limit_exceeded) or long-poll concurrent-cap. Retry-After header included. |
| 503 | Real-time push transport unavailable. |