# TempMail > TempMail (tempmail.lol) is a disposable email API. Create a temporary inbox, receive email at it, and read it over HTTP, by polling, long-polling, or webhooks. Free tier needs no API key. Custom domains, longer inbox lifespans, webhooks and raw .eml access are on paid tiers (TempMail Plus / Ultra). - Human docs: https://tempmail.lol/en/api - Pricing / tiers: https://tempmail.lol/en/pricing - Webhook setup UI: https://tempmail.lol/en/webhooks - Custom domain setup UI: https://tempmail.lol/en/custom - Support: Discord https://discord.gg/GHapeHPWVS **Use API v3 for new integrations.** v2 is still supported; inboxes and tokens are shared between v2 and v3. ## Basics - v3 base URL: `https://api.tempmail.lol/v3` - v2 base URL: `https://api.tempmail.lol/v2` - POST bodies are JSON; send `Content-Type: application/json`. - Auth (optional on free tier, required for Plus/Ultra features): `Authorization: Bearer ` - Primary key looks like `tempmail.20260101.abcdef...` - Scoped key looks like `tempmail.sk.abcdef...` - Per-inbox endpoints are authorized by the inbox `token` in the path. Keep the token: if you lose it, you lose the inbox (custom-domain inboxes can be recovered by re-creating the same prefix). - Official libraries: Python `pip3 install tempmail-lol`, Node `npm install tempmail.lol`, Java Maven `lol.tempmail:api`. ### Inbox lifespan | Tier | Lifespan | |---|---| | Free (no key) | 1 hour | | TempMail Plus | 10 hours | | TempMail Ultra | 30 hours | Custom-domain inboxes can be extended indefinitely by calling create again with the same prefix. ## API v3 ### Errors and rate limits - Every error is `{ "error": { "code": "...", "message": "..." } }` with a matching non-2xx HTTP status (never 200). Some include extra fields, e.g. `required_scope`, `required_tier`. - Known codes include `insufficient_scope` (403), `tier_required` (403), `rate_limited` (429). - Responses carry `x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset` (unix seconds). 429 responses include `retry-after`. ### Inboxes - `POST /v3/inboxes` creates an inbox. Body (all optional): - `prefix` (string, a-z 0-9 _ -), default random - `domain` (string): a TempMail domain (see `/v3/domains/pool`) or a custom domain verified to your account; default random - `community` (boolean): prefer a community domain, default false - 201 response: `{ "address", "token", "created_at" (ISO), "expires_at" (unix ms), "expired", "webhook_configured" }` - Without a key, per-IP limits apply. With a key, the inbox belongs to your account. - `GET /v3/inboxes` lists your account's inboxes (scope `inboxes:read`). Query: `limit` (default 50, max 200), `cursor` (from `next_cursor`), `include_expired` (default false). - `GET /v3/inboxes/:token` returns inbox metadata + email count. - `DELETE /v3/inboxes/:token` deletes the inbox and its emails. ### Emails Reading emails **consumes** them: emails returned in a response are deleted. Emails excluded by your filters stay in the inbox. - `GET /v3/inboxes/:token/emails` fetches and consumes. Query: `since` (unix ms, default 0), `limit` (default 100, max 200). - `DELETE /v3/inboxes/:token/emails/:id` deletes one email without reading it. - `GET /v3/inboxes/:token/emails/:id/raw` downloads RFC822 `.eml` (`Content-Type: message/rfc822`). **Ultra only**, otherwise 403 `tier_required`. Works only on emails not yet consumed. Header `x-tempmail-reconstructed: true` means the verbatim source was unavailable and the file was rebuilt. - Email objects include `id`, `from`, `subject`, `body`, and on Ultra-owned inboxes `raw` (MIME source, or null). ### Wait for email (long poll) Use this instead of a polling loop, e.g. for OTP / signup verification in tests. - `GET /v3/inboxes/:token/wait` blocks until a matching email arrives or the timeout passes. - Query: `timeout` (seconds, default 30, max 60), `from` (sender filter, wildcards like `*@example.com`), `since` (unix ms). - Response: `{ "emails": [...], "timed_out": bool, "waited_ms": number }`. A timeout is still HTTP 200 with `timed_out: true` and empty `emails`. - Matched emails are consumed; non-matching emails stay. - Max 2 concurrent `/wait` requests per inbox. ```sh TOKEN=$(curl -s -X POST https://api.tempmail.lol/v3/inboxes -H "Content-Type: application/json" -d '{}' | jq -r .token) # ... trigger the signup email ... curl "https://api.tempmail.lol/v3/inboxes/$TOKEN/wait?from=*@example.com&timeout=30" ``` ### Per-inbox webhooks (Ultra) - `PUT /v3/inboxes/:token/webhook` sets a webhook; new mail to that inbox is POSTed to your URL. - `GET /v3/inboxes/:token/webhook` reads it; `DELETE /v3/inboxes/:token/webhook` removes it. - Failed deliveries retry at 30s, 5m, 30m, 2h after the first attempt (5 attempts total). Your endpoint must return 200. - `GET /v3/webhooks/deliveries` returns the delivery log (7 days, covers v2 account webhooks, private domain webhooks, and per-inbox webhooks). Query: `status` (`pending` | `success` | `failed`), `address`, `domain`, `limit` (max 200), `cursor`. Each delivery has `url`, `event` (`email.received`), `address`, `status`, `attempt_count`, `attempts[]` (`at`, `status_code`, `error`, `duration_ms`), `created_at`; the response has `next_cursor`. ### Custom domains (Plus/Ultra) - `GET /v3/domains` lists your domains. - `POST /v3/domains` registers a domain and runs verification. - `GET /v3/domains/:domain` returns details + the DNS records to create. - `POST /v3/domains/:domain/verify` re-runs verification for one domain. - `POST /v3/domains/verify` re-verifies up to 100 of your domains (least recently checked first). Once per 10 minutes per account, otherwise 429 `rate_limited`. - `DELETE /v3/domains/:domain` unregisters it. - DNS needed: an ownership TXT record (account-specific name/value, **always read it from the API response**), an `A` record for `mx.yourdomain.com` (value from the API), and `MX yourdomain.com -> mx.yourdomain.com` priority 10, which must be the only MX. - Verify response: `{ "domain": {...}, "checks": { "txt": { "pass", "detail" }, "mx": { "pass", "records", "expected", "detail" } }, "dns": { "ownership_txt_options", "mail_records" } }` ### TempMail domain pool (Plus/Ultra) - `GET /v3/domains/pool` (scope `domains:read`) returns `{ "domains_premium": [...], "domains_free": [...] }`. Premium is Plus/Ultra only; free is usable by any tier. `*.example.com` means the bare domain and any subdomain are accepted. Lists rotate; don't cache them long. ### Scoped API keys Manage with your **primary** key only (scoped keys can't manage keys). The secret is returned once on creation. - `GET /v3/keys`, `POST /v3/keys` (body `{ "name", "scopes": [...] }`, 201 returns `key` once), `PATCH /v3/keys/:id` (rename / re-scope / revoke), `DELETE /v3/keys/:id`. - Scopes: `inboxes:create` (also works on v1/v2 create), `inboxes:read`, `webhooks:read`, `webhooks:write`, `domains:read`, `domains:write`, `usage:read`. ### Usage - `GET /v3/usage` (scope `usage:read`) returns `{ "tier", "inbox_creation": { "window_seconds", "limit", "used", "remaining", "resets_at" (unix ms), "limited_by" }, "inboxes_active", "api_keys_active", "custom_domains", "webhook_deliveries_last_7d" }`. ## API v2 (legacy, still supported) Important difference: **v2 deletes every email in the inbox on each read**, not just the ones returned. ### Types - Email: `from` (string), `to` (string), `subject` (string), `body` (string, plaintext, may be empty), `html` (string or null), `date` (unix ms). - Inbox: `address` (string), `token` (string). ### Endpoints - `POST /v2/inbox/create` creates an inbox. Body: `domain` (optional, may be a custom domain; requires the key that registered it), `prefix` (optional). 201: `{ "address", "token" }`. (GET also works, legacy only.) - `GET /v2/inbox?token=` returns `{ "emails": Email[], "expired": boolean }`. - `POST /v2/custom` with body `{ "domain" }` returns `{ "uuid" }`. Create a TXT record at `[uuid].yourdomain.com` (or `[uuid].sub.yourdomain.com`) with value `tm-custom-domain-verification`. Errors: 4xx `{ "error" }`. Plus/Ultra. - `POST /v2/private_webhook` with body `{ "domain", "url" }` forwards **all** mail for a custom domain to your URL (catch-all, no need to create inboxes). `DELETE /v2/private_webhook?domain=` removes it. Ultra. - `POST /v2/webhook` with body `{ "url" }` forwards mail for every standard inbox you create afterwards (not retroactive). `DELETE /v2/webhook` removes it. Ultra. ### Webhook payload (v2 account and domain webhooks) ```json { "from": "sender@website.com", "to": "receiver@tempmail.lol", "subject": "Awesome Email", "body": "Plaintext body", "html": "HTML Content, may be null", "date": 1736540047182 } ``` Respond with 200 OK or the delivery is retried. Discord webhook URLs are supported natively and get a Discord-shaped payload instead.