Skip to content

WebSocket

Get real-time notifications when new emails arrive. More efficient than polling GET /api/messages.

Important

  • Only server-side code (Python, Node.js, Go, etc.) can connect. Browser JavaScript from third-party websites will be rejected due to origin restrictions — only mail.cx is allowed as a browser origin.
  • Only mailbox JWT tokens are accepted. Use the token returned by POST /api/accounts (create mailbox) or POST /api/token (sign in). Pro API tokens (tm_pro_...) and Pro JWT tokens cannot be used for WebSocket. If you are a Pro user and want to monitor a mailbox, first call POST /api/token with that mailbox's address and password to get a mailbox JWT token.

Connection

wss://api.mail.cx/api/ws

Authentication

After connecting, send an auth message within 10 seconds:

json
{ "type": "auth", "token": "eyJhbGciOiJIUzI1NiIs..." }

Success

json
{ "type": "auth_ok" }

Errors

json
{ "error": "invalid_token" }
json
{ "error": "invalid_auth_message" }
json
{ "error": "too_many_connections" }

Each account supports up to 3 concurrent WebSocket connections.

New Email Notification

When a new email arrives, the server pushes:

json
{
  "type": "new_email",
  "id": "f5e6d7c8-a1b2-3c4d-e5f6-789012345678",
  "sender": "noreply@example.com",
  "from": "Example <noreply@example.com>",
  "subject": "Verify your email",
  "preview_text": "Click the link below to verify...",
  "size": 4523,
  "created_at": "2025-01-15T10:30:00Z",
  "account_id": "a1b2c3d4-...",
  "address": "demo@mail.cx"
}
FieldTypeDescription
typestringAlways "new_email"
iduuidMessage ID (use to fetch full content)
senderstringEnvelope sender address
fromstringFrom header (display name + address)
subjectstringSubject line
preview_textstringFirst ~100 characters of message body
sizeintegerMessage size in bytes
created_atstringReceived timestamp (ISO 8601)
account_iduuidYour account ID
addressstringRecipient address

Python Example

python
import asyncio
import json
import aiohttp

API = "https://api.mail.cx/api"
WS  = "wss://api.mail.cx/api/ws"

async def main():
    # Create mailbox and get token
    async with aiohttp.ClientSession() as session:
        r = await session.post(f"{API}/accounts", json={
            "address": "demo@mail.cx", "password": "secret"
        })
        token = (await r.json())["token"]

    # Connect WebSocket
    async with aiohttp.ClientSession() as session:
        async with session.ws_connect(WS) as ws:
            await ws.send_json({"type": "auth", "token": token})

            async for msg in ws:
                data = json.loads(msg.data)
                if data.get("type") == "auth_ok":
                    print("Connected, waiting for emails...")
                elif data.get("type") == "new_email":
                    print(f"New email: {data['subject']} from {data['from']}")

                    # Fetch full message
                    async with session.get(
                        f"{API}/messages/{data['id']}",
                        headers={"Authorization": f"Bearer {token}"}
                    ) as r:
                        detail = await r.json()
                        print(detail["text_body"])

asyncio.run(main())

Node.js Example

javascript
import WebSocket from "ws";

const API = "https://api.mail.cx/api";
const token = "YOUR_TOKEN";

const ws = new WebSocket("wss://api.mail.cx/api/ws");

ws.on("open", () => {
  ws.send(JSON.stringify({ type: "auth", token }));
});

ws.on("message", async (raw) => {
  const data = JSON.parse(raw);

  if (data.type === "auth_ok") {
    console.log("Connected, waiting for emails...");
    return;
  }

  if (data.error) {
    console.error("Error:", data.error);
    ws.close();
    return;
  }

  // data.type === "new_email"
  console.log(`New email: ${data.subject} from ${data.from}`);

  // Fetch full message
  const res = await fetch(`${API}/messages/${data.id}`, {
    headers: { Authorization: `Bearer ${token}` },
  });
  const detail = await res.json();
  console.log(detail.text_body);
});

ws.on("close", () => console.log("Disconnected"));

Connection Notes

  • The server sends ping frames every 30 seconds — most WebSocket libraries handle pong automatically
  • If the connection drops, reconnect with exponential backoff
  • Each connection monitors one mailbox — open multiple connections for multiple addresses
  • The WebSocket only sends notifications; use the REST API to fetch full message content

Mail.cx API Documentation