saci.cc API
A simple HTTP API, with no sign-up and no auth, to create temporary addresses and read the emails they get. Handy for end-to-end tests of sign-up and password reset flows.
Base URL
https://saci.cc/api
Quick start
Create an address, use it wherever you need, and wait for the email:
# 1. Create an address
curl -X POST https://saci.cc/api/addresses
# 2. Wait for an email (up to 25 s)
curl "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails?wait=25"
# 3. Read the email
curl "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails/{messageId}"// 1. Create an address
const { address } = await fetch("https://saci.cc/api/addresses", { method: "POST" }).then((r) => r.json());
// 2. Wait for an email (up to 25 s)
const { emails } = await fetch(`https://saci.cc/api/addresses/${address}/emails?wait=25`).then((r) => r.json());
// 3. Read the email
const email = await fetch(`https://saci.cc/api/addresses/${address}/emails/${emails[0].messageId}`).then((r) => r.json());
console.log(email.subject, email.text);import requests
# 1. Create an address
address = requests.post("https://saci.cc/api/addresses").json()["address"]
# 2. Wait for an email (up to 25 s)
emails = requests.get(f"https://saci.cc/api/addresses/{address}/emails", params={"wait": 25}).json()["emails"]
# 3. Read the email
email = requests.get(f"https://saci.cc/api/addresses/{address}/emails/{emails[0]['messageId']}").json()
print(email["subject"], email["text"])Endpoints
Create address
POST/addresses
Generates a new random address. Nothing to register: any email sent to it is available for about a day.
| Name | In | Description |
|---|---|---|
name | query | Optional. Address name (3 to 32 letters, numbers, dots, dashes or underscores). Random if omitted. |
curl -X POST https://saci.cc/api/addresses
Response · 201
{ "address": "a1b2c3d4e5f60718@saci.cc" }List emails
GET/addresses/{address}/emails
Lists received emails, newest first. With wait, the request stays open until an email arrives (25 seconds at most), so you don't have to poll in a loop.
| Name | In | Description |
|---|---|---|
addressrequired | path | Full address, e.g. a1b2c3d4e5f60718@saci.cc |
wait | query | Seconds to wait for an email, up to 25. Without it, the response is immediate. |
after | query | ISO 8601 date. With wait, waits for an email received after it. |
curl "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails?wait=25"
Response · 200
{
"emails": [
{
"messageId": "0100019a2b3c4d5e-6f7a8b9c-...",
"from": "GitHub <noreply@github.com>",
"subject": "[GitHub] Please verify your email address",
"receivedAt": "2026-10-20T15:30:00.000Z"
}
]
}Read email
GET/addresses/{address}/emails/{messageId}
Returns the email's content as HTML and plain text.
| Name | In | Description |
|---|---|---|
addressrequired | path | Full address, e.g. a1b2c3d4e5f60718@saci.cc |
messageIdrequired | path | The messageId from the list |
curl "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails/{messageId}"Response · 200
{
"messageId": "0100019a2b3c4d5e-6f7a8b9c-...",
"from": "GitHub <noreply@github.com>",
"subject": "[GitHub] Please verify your email address",
"receivedAt": "2026-10-20T15:30:00.000Z",
"html": "<p>Your code is <b>482913</b></p>",
"text": "Your code is 482913",
"attachments": [
{
"index": 0,
"filename": "invoice.pdf",
"contentType": "application/pdf",
"size": 48213,
"inline": false,
"url": "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails/0100019a2b3c4d5e-6f7a8b9c-.../attachments/0"
}
]
}Download attachment
GET/addresses/{address}/emails/{messageId}/attachments/{index}
Redirects to a download link for the attachment, valid for a few minutes. The index comes from the email's attachments list.
| Name | In | Description |
|---|---|---|
addressrequired | path | Full address, e.g. a1b2c3d4e5f60718@saci.cc |
messageIdrequired | path | The messageId from the list |
indexrequired | path | Position of the attachment in the attachments list, starting at 0 |
curl -L -OJ "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails/{messageId}/attachments/0"Response · 302
Delete email
DELETE/addresses/{address}/emails/{messageId}
Deletes one email and its attachments. Returns 204, or 404 if it doesn't exist.
| Name | In | Description |
|---|---|---|
addressrequired | path | Full address, e.g. a1b2c3d4e5f60718@saci.cc |
messageIdrequired | path | The messageId from the list |
curl -X DELETE "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails/{messageId}"Response · 204
Empty inbox
DELETE/addresses/{address}/emails
Deletes every email in the inbox and says how many there were.
| Name | In | Description |
|---|---|---|
addressrequired | path | Full address, e.g. a1b2c3d4e5f60718@saci.cc |
curl -X DELETE "https://saci.cc/api/addresses/a1b2c3d4e5f60718@saci.cc/emails"
Response · 200
{ "deleted": 3 }Limits and errors
- 120 requests per minute per IP. Above that you get a 429, with a Retry-After header saying how many seconds to wait.
- wait goes up to 25 seconds per request. If time runs out, you get a normal response with the current list (which may be empty).
- Emails are deleted about a day after they arrive. After that, reading one returns 404.
- An invalid address or parameter returns 400.
- There's no password: anyone who knows an address can read its inbox. Don't use it for anything sensitive.
Using it with AI agents
If you use Claude, Cursor or another agent, the MCP server does all of this without writing code. See the MCP server
This documentation is also available as plain text for LLMs: /llms.txt · /llms-full.txt