API Documentation
EMLX Mail REST API for programmatic email access. Receive, read, search, and manage emails via simple HTTP requests.
Authentication
API Key Required
All API requests require authentication via the X-API-Key header or ?key= query parameter.
curl -H "X-API-Key: your_api_key" https://emlx.cloud/api/stats
curl "https://emlx.cloud/api/stats?key=your_api_key"
Response on Invalid Key
{
"success": false,
"error": "Invalid API key"
}Base URL
All endpoints are relative to:
Error Handling
All responses include a success boolean. On error, an error message is provided.
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad request — missing or invalid parameters |
| 401 | Unauthorized — invalid or missing API key |
| 404 | Not found — email or endpoint doesn't exist |
List Emails
Retrieve all emails for a specific address. Returns newest first.
| Name | Type | Description |
|---|---|---|
| address | string required | Email address (URL-encoded) |
| Name | Type | Description |
|---|---|---|
| limit | integer optional | Max results (default: 50) |
| offset | integer optional | Pagination offset (default: 0) |
| since_id | integer optional | Only return emails with ID greater than this value. Use for snapshot-based polling. |
curl -H "X-API-Key: your_key" \ "https://emlx.cloud/api/emails/user@sub.emlx.cloud?limit=10"
{
"success": true,
"address": "user@sub.emlx.cloud",
"total": 3,
"emails": [
{
"id": 42,
"from": "noreply@spotify.com",
"to": "user@sub.emlx.cloud",
"subject": "Your verification code",
"body": "Your code is 482910",
"size": 2048,
"received_at": "2026-10-06 10:30:00",
"read": false
}
]
}Latest Email
Get the most recent email for an address. Supports since_id for snapshot-based OTP polling without deleting old emails.
| Name | Type | Description |
|---|---|---|
| since_id | integer optional | Only return email with ID greater than this. Returns 404 if no newer email exists. |
curl -H "X-API-Key: your_key" \ "https://emlx.cloud/api/emails/user@sub.emlx.cloud/latest?since_id=41"
{
"success": true,
"email": {
"id": 42,
"from": "noreply@spotify.com",
"subject": "Your verification code",
"body": "Your code is 482910",
"received_at": "2026-10-06 10:30:00",
"read": false
}
}Wait for Email
Long-poll endpoint that waits for a new email with ID greater than since_id. Returns immediately when a matching email arrives, or 408 on timeout. No need to delete old emails first.
| Name | Type | Description |
|---|---|---|
| since_id | integer required | Wait for email with ID greater than this value |
| timeout | integer optional | Max wait time in seconds (default: 30, max: 55) |
| interval | integer optional | Poll interval in seconds (default: 1, min: 1) |
| from | string optional | Filter by sender (partial match, e.g. "spotify") |
curl -H "X-API-Key: your_key" \ "https://emlx.cloud/api/emails/user@sub.emlx.cloud/wait?since_id=41&timeout=30&from=spotify"
{
"success": true,
"email": {
"id": 42,
"from": "noreply@spotify.com",
"subject": "Your verification code",
"body": "Your code is 482910",
"received_at": "2026-10-06 10:30:00"
}
}{
"success": false,
"error": "Timeout waiting for new email"
}Get Specific Email
Get full email details including HTML body and headers. Automatically marks as read.
| Name | Type | Description |
|---|---|---|
| address | string required | Email address |
| id | integer required | Email ID |
{
"success": true,
"email": {
"id": 42,
"from": "noreply@spotify.com",
"to": "user@sub.emlx.cloud",
"subject": "Your verification code",
"body": "Your code is 482910",
"html": "<html>...</html>",
"headers": { "..." },
"received_at": "2026-10-06 10:30:00",
"read": true
}
}Delete All Emails
Delete all emails for a specific address.
curl -X DELETE -H "X-API-Key: your_key" \ "https://emlx.cloud/api/emails/user@sub.emlx.cloud"
{ "success": true, "deleted": 5 }Delete Specific Email
Delete a single email by ID.
{ "success": true, "deleted": 1 }Search Emails
Search across all emails by subject, body, or sender.
| Name | Type | Description |
|---|---|---|
| q | string required | Search keyword |
| limit | integer optional | Max results (default: 50) |
curl -H "X-API-Key: your_key" \ "https://emlx.cloud/api/search?q=verification+code"
Dashboard Stats
Get overall email statistics.
{
"success": true,
"stats": {
"total_emails": 1250,
"unread": 42,
"unique_addresses": 380,
"latest_email": "2026-10-06 10:30:00",
"last_24h": 67
}
}List Addresses
List all email addresses with message counts. Supports search and pagination.
| Name | Type | Description |
|---|---|---|
| q | string optional | Filter by address |
| limit | integer optional | Max results (default: 100) |
| offset | integer optional | Pagination offset |
{
"success": true,
"addresses": [
{
"address": "user@sub.emlx.cloud",
"count": 12,
"latest": "2026-10-06 10:30:00",
"unread": 3
}
]
}Cleanup Old Emails
Delete emails older than N days. Default: 7 days.
| Name | Type | Description |
|---|---|---|
| days | integer optional | Delete emails older than this (default: 7) |
curl -X POST -H "X-API-Key: your_key" \ "https://emlx.cloud/api/cleanup?days=3"
API Key Management
Admin Only
API key management requires the master password. Only the system owner can create, list, or revoke API keys.
Generate a new API key. Requires master password in request body.
curl -X POST -H "Content-Type: application/json" \ -d '{"master":"your_master_password","name":"my-bot"}' \ "https://emlx.cloud/api/keys/create"
{
"success": true,
"key": {
"id": "k_abc123",
"name": "my-bot",
"key": "emlx_sk_...",
"created_at": "2026-10-06 10:30:00"
}
}List all active API keys (keys are partially masked).
Revoke an API key by its ID.
OTP Flow (Best Practice)
No Delete Required
Use the snapshot pattern: save the latest email ID before triggering OTP, then poll for emails newer than that ID. No need to delete old emails first.
Step 1: GET /api/emails/{address}/latest → save id as snapshot_id Step 2: Trigger OTP (register, login, etc.) Step 3: GET /api/emails/{address}/wait?since_id=snapshot_id&from=spotify Step 4: Extract OTP from response body
Python Example
import requests import re API = "https://emlx.cloud/api" KEY = "your_api_key" headers = {"X-API-Key": KEY} def get_snapshot_id(address): """Get current latest email ID as snapshot""" r = requests.get(f"{API}/emails/{address}/latest", headers=headers) data = r.json() if data.get("success"): return data["email"]["id"] return 0 # no emails yet def wait_for_otp(address, snapshot_id, sender=None, timeout=30): """Wait for new OTP email after snapshot_id""" params = {"since_id": snapshot_id, "timeout": timeout} if sender: params["from"] = sender r = requests.get(f"{API}/emails/{address}/wait", headers=headers, params=params) data = r.json() if data.get("success"): body = data["email"]["body"] or "" otp = re.search(r"\b(\d{4,8})\b", body) return otp.group(1) if otp else None return None # Usage address = "user@sub.emlx.cloud" snapshot = get_snapshot_id(address) # ... trigger OTP here (register, login, etc.) ... code = wait_for_otp(address, snapshot, sender="spotify") print(f"OTP: {code}")