API Documentation

EMLX Mail REST API for programmatic email access. Receive, read, search, and manage emails via simple HTTP requests.

https://emlx.cloud/api

Authentication

API Key Required

All API requests require authentication via the X-API-Key header or ?key= query parameter.

Header Authentication
curl -H "X-API-Key: your_api_key" https://emlx.cloud/api/stats
Query Parameter Authentication
curl "https://emlx.cloud/api/stats?key=your_api_key"

Response on Invalid Key

401 Unauthorized
{
  "success": false,
  "error": "Invalid API key"
}

Base URL

All endpoints are relative to:

https://emlx.cloud/api

Error Handling

All responses include a success boolean. On error, an error message is provided.

StatusMeaning
200Success
400Bad request — missing or invalid parameters
401Unauthorized — invalid or missing API key
404Not found — email or endpoint doesn't exist

List Emails

GET /api/emails/{address}

Retrieve all emails for a specific address. Returns newest first.

Path Parameters
NameTypeDescription
addressstring requiredEmail address (URL-encoded)
Query Parameters
NameTypeDescription
limitinteger optionalMax results (default: 50)
offsetinteger optionalPagination offset (default: 0)
since_idinteger optionalOnly return emails with ID greater than this value. Use for snapshot-based polling.
Example Request
curl -H "X-API-Key: your_key" \
  "https://emlx.cloud/api/emails/user@sub.emlx.cloud?limit=10"
Response 200
{
  "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 /api/emails/{address}/latest

Get the most recent email for an address. Supports since_id for snapshot-based OTP polling without deleting old emails.

Query Parameters
NameTypeDescription
since_idinteger optionalOnly return email with ID greater than this. Returns 404 if no newer email exists.
Example
curl -H "X-API-Key: your_key" \
  "https://emlx.cloud/api/emails/user@sub.emlx.cloud/latest?since_id=41"
Response 200
{
  "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

GET /api/emails/{address}/wait

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.

Query Parameters
NameTypeDescription
since_idinteger requiredWait for email with ID greater than this value
timeoutinteger optionalMax wait time in seconds (default: 30, max: 55)
intervalinteger optionalPoll interval in seconds (default: 1, min: 1)
fromstring optionalFilter by sender (partial match, e.g. "spotify")
Example Request
curl -H "X-API-Key: your_key" \
  "https://emlx.cloud/api/emails/user@sub.emlx.cloud/wait?since_id=41&timeout=30&from=spotify"
Response (email found) 200
{
  "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"
  }
}
Response (timeout) 408
{
  "success": false,
  "error": "Timeout waiting for new email"
}

Get Specific Email

GET /api/emails/{address}/{id}

Get full email details including HTML body and headers. Automatically marks as read.

NameTypeDescription
addressstring requiredEmail address
idinteger requiredEmail ID
Response 200
{
  "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 /api/emails/{address}

Delete all emails for a specific address.

Example
curl -X DELETE -H "X-API-Key: your_key" \
  "https://emlx.cloud/api/emails/user@sub.emlx.cloud"
Response 200
{ "success": true, "deleted": 5 }

Delete Specific Email

DELETE /api/emails/{address}/{id}

Delete a single email by ID.

Response 200
{ "success": true, "deleted": 1 }
GET /api/search?q={query}

Search across all emails by subject, body, or sender.

NameTypeDescription
qstring requiredSearch keyword
limitinteger optionalMax results (default: 50)
Example
curl -H "X-API-Key: your_key" \
  "https://emlx.cloud/api/search?q=verification+code"

Dashboard Stats

GET /api/stats

Get overall email statistics.

Response 200
{
  "success": true,
  "stats": {
    "total_emails": 1250,
    "unread": 42,
    "unique_addresses": 380,
    "latest_email": "2026-10-06 10:30:00",
    "last_24h": 67
  }
}

List Addresses

GET /api/addresses

List all email addresses with message counts. Supports search and pagination.

NameTypeDescription
qstring optionalFilter by address
limitinteger optionalMax results (default: 100)
offsetinteger optionalPagination offset
Response 200
{
  "success": true,
  "addresses": [
    {
      "address": "user@sub.emlx.cloud",
      "count": 12,
      "latest": "2026-10-06 10:30:00",
      "unread": 3
    }
  ]
}

Cleanup Old Emails

POST /api/cleanup

Delete emails older than N days. Default: 7 days.

NameTypeDescription
daysinteger optionalDelete emails older than this (default: 7)
Example
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.

POST /api/keys/create

Generate a new API key. Requires master password in request body.

Request
curl -X POST -H "Content-Type: application/json" \
  -d '{"master":"your_master_password","name":"my-bot"}' \
  "https://emlx.cloud/api/keys/create"
Response 200
{
  "success": true,
  "key": {
    "id": "k_abc123",
    "name": "my-bot",
    "key": "emlx_sk_...",
    "created_at": "2026-10-06 10:30:00"
  }
}
GET /api/keys/list?master={password}

List all active API keys (keys are partially masked).

DELETE /api/keys/{key_id}?master={password}

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.

Snapshot Pattern Flow
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

python — Snapshot OTP (recommended)
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}")