FastMailApp API
Public REST API to create disposable email addresses, receive and read mail. No registration required (optional API key for higher rate limits).
@nmailbox.cc
@nmailbox.live
@nmailbox.org
@smailbox.us
Features
- Create disposable mailbox (random or custom name)
- Receive real mail from Gmail / Outlook / any MTA via SMTP port 25
- Read mail as JSON (text + html)
- Mailbox and all its mail are auto-destroyed after TTL
- No storage, no tracking, no cookies
Authentication #
The API is fully public โ you can use it without registering. Registering an API key gives you a much higher rate limit.
Use an API key
Pass your key via the Authorization: Bearer <key> header:
# Anonymous (low rate limit) curl https://fastmailapp.com/api/new # With API key (high rate limit) curl -H "Authorization: Bearer nmb_xxxxxxxxxxxxxx" \ https://fastmailapp.com/api/new
Register an API key
Call POST /api/keys โ no authentication required:
curl -X POST https://fastmailapp.com/api/keys \ -H "Content-Type: application/json" \ -d '{"name":"my-app"}'
The response contains the key โ save it immediately; it will not be shown again:
{
"id": "a1b2c3d4e5f6g7h8",
"key": "nmb_XXXX...XXXX",
"name": "my-app",
"createdAt": 1778523000,
"rateLimit": 2000
}
Rate limits #
Limits are per minute and reset every 60 seconds.
Every response includes the following headers:
X-RateLimit-Limitโ max requests per minuteX-RateLimit-Remainingโ requests left in the current minuteRetry-Afterโ seconds to wait (only when 429)
When you exceed the limit, the server responds with 429 Too Many Requests.
Quick start #
Create a mailbox โ wait for mail โ read the inbox. Three steps.
# 1. Create a mailbox with a custom name ADDR=$(curl -s https://fastmailapp.com/api/new/john | jq -r .address) echo "Mailbox: $ADDR" # 2. List inbox (poll every 5s) curl -s "https://fastmailapp.com/api/inbox?address=$ADDR" | jq # 3. Read a specific mail curl -s https://fastmailapp.com/api/mail/MAIL_ID | jq
import requests, time # 1. Create mailbox r = requests.get("https://fastmailapp.com/api/new/john") addr = r.json()["address"] print(f"Mailbox: {addr}") # 2. Poll inbox until mail arrives while True: r = requests.get("https://fastmailapp.com/api/inbox", params={"address": addr}) data = r.json() if data["emails"]: print(f"Got {len(data['emails'])} mail(s)") break time.sleep(5) # 3. Read the first mail first_id = data["emails"][0]["id"] mail = requests.get(f"https://fastmailapp.com/api/mail/{first_id}").json() print(mail["subject"], "\n", mail["text"])
// 1. Create mailbox const r = await fetch("https://fastmailapp.com/api/new/john"); const { address } = await r.json(); console.log("Mailbox:", address); // 2. Poll inbox async function poll() { const r = await fetch(`https://fastmailapp.com/api/inbox?address=${address}`); return (await r.json()).emails; } // 3. Read mail const mails = await poll(); if (mails.length) { const mail = await (await fetch(`https://fastmailapp.com/api/mail/${mails[0].id}`)).json(); console.log(mail.subject, mail.text); }
Mailbox #
Create / inspect / delete a disposable email address.
Create a random mailbox โ the server generates a 10-character local part.
Request
curl https://fastmailapp.com/api/new
Response 200 OK
{
"address": "k7p2qe9w3x@fastmailapp.com",
"createdAt": 1778523000,
"expiresAt": 1778524800,
"secondsLeft": 1800,
"lifetime": 1800,
"reused": false
}
Create a mailbox with a custom local part. If the name already exists, the server returns reused: true (you will share the inbox with the previous user).
Path parameters
| Name | Type | Description |
|---|---|---|
| localrequired | string | Part before @. Allowed: a-z 0-9 . _ -, 2-32 chars. |
Request
curl https://fastmailapp.com/api/new/john
Response 200 OK
{
"address": "john@fastmailapp.com",
"createdAt": 1778523000,
"expiresAt": 1778524800,
"secondsLeft": 1800,
"lifetime": 1800,
"reused": false
}
Errors
400โ invalid local part503โ no domains configured
Create a mailbox using a JSON body โ useful when you also want to specify the domain (when multiple are available).
Body (JSON)
| Field | Type | Description |
|---|---|---|
| address | string | Full user@domain. Omit for random. |
Request
curl -X POST https://fastmailapp.com/api/mailbox \ -H "Content-Type: application/json" \ -d '{"address":"hello@fastmailapp.com"}'
Get mailbox info (remaining TTL). Returns 404 if not found or expired.
curl https://fastmailapp.com/api/mailbox/john@fastmailapp.com
Delete the mailbox immediately and all of its emails. Returns the number of mails deleted.
curl -X DELETE https://fastmailapp.com/api/mailbox/john@fastmailapp.com
{"deleted": 3}
Mail #
List the inbox and read individual messages.
List all mails in a mailbox, newest first.
Query parameters
| Name | Type | Description |
|---|---|---|
| addressrequired | string | Full mailbox address. |
Request
curl "https://fastmailapp.com/api/inbox?address=john@fastmailapp.com"
Response 200 OK
{
"address": "john@fastmailapp.com",
"secondsLeft": 1542,
"count": 2,
"emails": [
{
"id": "a5259346b1f446d4a1fc285dd2b44bb3",
"subject": "Welcome",
"fromAddress": "noreply@example.com",
"toAddress": "john@fastmailapp.com",
"createdAt": 1778523450,
"expiresAt": 1778524800,
"readAt": null,
"hasHtml": true,
"hasText": true
}
]
}
GET /api/email/{recipient} still works (path param instead of query).Fetch the full content of a single mail. The first call marks the mail as read.
Request
curl https://fastmailapp.com/api/mail/a5259346b1f446d4a1fc285dd2b44bb3
Response 200 OK
{
"id": "a5259346b1f446d4a1fc285dd2b44bb3",
"subject": "Welcome",
"fromAddress": "noreply@example.com",
"toAddress": "john@fastmailapp.com",
"createdAt": 1778523450,
"expiresAt": 1778524800,
"readAt": 1778523500,
"hasHtml": true,
"hasText": true,
"html": "<p>Hello</p>",
"text": "Hello"
}
GET /api/inbox/{email_id} still works.Delete a single mail.
curl -X DELETE https://fastmailapp.com/api/mail/a5259346b1f446d4a1fc285dd2b44bb3
Verification codes #
The API auto-detects verification codes (OTPs) and magic links from every mail. The detection is language-agnostic โ works for English, Vietnamese, Japanese, Korean, Arabic, Chinese, etc.
verifications field.
Same detection logic, same field name โ drop-in for code written against mail.tm's API.
The verifications field
Every GET /api/mail/{id} response includes two extra fields:
verificationsโ array of detected codes, most likely OTP firstlinksโ array of detected magic / confirmation URLs
{
"id": "a5259346b1f446d4a1fc285dd2b44bb3",
"subject": "Welcome",
"html": "<p>Your code is <b>728493</b>...</p>",
"text": "Your code is 728493...",
"verifications": ["728493"],
"links": []
}
Detection rules
- Tokens inside HTML emphasis tags (
<b>,<strong>,<h1-h6>,<center>,<mark>) - Tokens that appear alone on their own line
- 4-12 chars alphanumeric (with dashes), must contain โฅ1 digit
- Year-like numbers 1900-2099 are filtered out
- Numbers near street suffixes / phone prefixes / state-zip patterns are filtered out
- Magic links: URLs containing
verify / confirm / activate / token= / code= / otp=
Convenience polling endpoint: returns the newest mail that contains a verification code or magic link. Poll this every few seconds while waiting for an OTP โ much simpler than fetching the inbox list and iterating mails yourself.
Query parameters
| Name | Type | Description |
|---|---|---|
| addressrequired | string | Full mailbox address. |
Request
curl "https://fastmailapp.com/api/verifications?address=john@fastmailapp.com"
Response 200 OK โ code found
{
"address": "john@fastmailapp.com",
"mailId": "d387c683769942eeb67e2266dd67f9ea",
"subject": "Your verification code",
"fromAddress": "support@example.com",
"createdAt": 1778527050,
"verification": "728493",
"verifications": ["728493"],
"links": []
}
Response 200 OK โ no code yet
{
"address": "john@fastmailapp.com",
"mailId": null,
"verification": null,
"verifications": [],
"links": []
}
Polling example (Python)
import requests, time addr = requests.get("https://fastmailapp.com/api/new/myapp-signup").json()["address"] print("Mailbox:", addr) # Trigger signup elsewhere that sends a code to `addr`... while True: r = requests.get("https://fastmailapp.com/api/verifications", params={"address": addr}) code = r.json()["verification"] if code: print("Got code:", code) break time.sleep(3)
System #
API keys, allowed domains, health check.
Register a new API key. No authentication required. Each IP can create up to 20 keys per day.
Body (JSON, optional)
| Field | Type | Description |
|---|---|---|
| name | string | Friendly label (max 64 chars). |
curl -X POST https://fastmailapp.com/api/keys \ -H "Content-Type: application/json" \ -d '{"name":"my-bot"}'
Get info about the currently used key. Requires Authorization: Bearer ... header.
curl -H "Authorization: Bearer nmb_xxxxxxxx" \ https://fastmailapp.com/api/keys/me
Revoke the key:
curl -X DELETE \ -H "Authorization: Bearer nmb_xxxxxxxx" \ https://fastmailapp.com/api/keys/me
List of allowed domains.
curl https://fastmailapp.com/api/domains
["@fastmailapp.com", "@nmailbox.cc", ...]
Health check. Not rate-limited.
curl https://fastmailapp.com/api/health
{
"status": "healthy",
"ts": 1778523000,
"mailboxes": 12,
"emails": 45,
"apiKeys": 3
}