# email.singles — email inboxes for AI agents > Create a real email address with one HTTP call, receive mail as clean JSON (verification codes and links already extracted), and send email. Each inbox has 25 MB of storage. Base URL: https://email.singles/v1 Auth: header `Authorization: Bearer ` (alternatives: `X-API-Key: ` or query `?key=`) All request and response bodies are JSON. Every response has `"ok": true|false`. Errors look like: `{"ok": false, "error": {"code": "inbox_not_found", "message": "..."}}` Anywhere `{address}` appears you may use the full address (`bob@email.singles`) or only the part before @ (`bob`). ## Quick start (4 calls) ```bash # 1. Get an API key (shown once — save it) curl -X POST https://email.singles/v1/signup # -> {"ok":true,"api_key":"es_..."} # 2. Create an inbox (random address, or pass {"username":"my-agent"}) curl -X POST https://email.singles/v1/inboxes -H "Authorization: Bearer $KEY" # -> {"ok":true,"inbox":{"address":"swift-otter-4821@email.singles", ...}} # 3. Wait for the next email (long-poll, up to 50 s). Returns the full message. curl "https://email.singles/v1/inboxes/swift-otter-4821/wait?timeout=50" -H "Authorization: Bearer $KEY" # -> {"ok":true,"message":{"subject":"Your code","codes":["483920"],"links":[...],"text":"..."}} # 4. Send an email curl -X POST https://email.singles/v1/inboxes/swift-otter-4821/send -H "Authorization: Bearer $KEY" \ -H "Content-Type: application/json" -d '{"to":"someone@example.com","subject":"Hi","text":"Hello!"}' ``` ## Endpoints ### POST /v1/signup Create an account and API key. No auth. Optional body: `{"contact_email": "you@example.com"}`. Returns `api_key` (only shown once) and `limits`. ### GET /v1/me Your account: inbox count, sends in the last 24h, limits. ### POST /v1/inboxes Create an inbox. Body (all optional): `{"username": "my-agent", "name": "My Agent"}`. - `username`: 3–64 chars a-z 0-9 . _ - → my-agent@email.singles. Omit for a random address. - `name`: display name used as the From name when sending. Addresses are permanent and never reused after deletion. ### GET /v1/inboxes List your inboxes. ### GET /v1/inboxes/{address} Inbox details: `message_count`, `unread_count`, `storage_used`, `storage_limit` (26214400 bytes), `storage_free`, `rejected_over_quota`. ### DELETE /v1/inboxes/{address} Delete the inbox and all its messages. ### GET /v1/inboxes/{address}/wait **Best way for an agent to receive email.** Blocks until an email arrives, then returns it in full and marks it read. Query: `timeout` seconds (0–50, default 30); `after` = a message id → return the first received message newer than it (without `after`, returns the oldest unread received message). If nothing arrives: `{"ok":true,"message":null}` — just call again. ### GET /v1/inboxes/{address}/messages List messages, newest first (summaries). Query: `direction=received|sent`, `unread=1`, `after=`, `limit` (1–100, default 20). ### GET /v1/inboxes/{address}/messages/{id} Full message; marks it read. Fields: `id, direction (received|sent), from {address,name}, to[], cc[], reply_to[], subject, date, text, html, snippet, codes[] (verification codes / OTPs detected, best first), links[] (all URLs), attachments[] {index, filename, content_type, size, url}, headers {}, message_id, raw_url, seen, size`. ### GET /v1/inboxes/{address}/messages/{id}/attachments/{index} Download an attachment (binary). ### GET /v1/inboxes/{address}/messages/{id}/raw Original message source (.eml). ### DELETE /v1/inboxes/{address}/messages/{id} Delete a message and free its storage. ### POST /v1/inboxes/{address}/send Send email from this inbox. Body: ```json { "to": "a@example.com", // string, "a@x.com, b@y.com", or array — required "cc": [], "bcc": [], // optional "subject": "Hello", "text": "Plain text body", // text and/or html required "html": "

HTML body

", "from_name": "My Agent", // optional, defaults to inbox name "reply_to": "other@example.com", // optional Reply-To header "reply_to_message_id": "msg_...", // optional: reply to a received message (sets to, "Re:" subject and threading) "attachments": [{"filename": "a.pdf", "content_type": "application/pdf", "content_base64": "JVBERi0..."}] } ``` A copy of each sent message is stored in the inbox and counts toward its storage. ## Limits - Storage: 25 MB per inbox (received + sent mail). Incoming mail that does not fit is dropped and counted in `rejected_over_quota`. Delete messages to free space. A single message can therefore be up to 25 MB. - Sending: 50 messages per account per 24 h, max 20 recipients per message. - Inboxes: 100 per account. ## Error codes missing_api_key, invalid_api_key, account_disabled (401/403) · inbox_not_found, message_not_found, attachment_not_found (404) · username_taken (409) · invalid_json (400) · invalid_username, invalid_address, missing_to, missing_body, too_many_recipients, invalid_attachment (422) · inbox_full (413) · send_limit, rate_limited (429) · inbox_limit (403) · send_failed (502) OpenAPI spec: https://email.singles/openapi.json