WebSocket
Subscribe to real-time inbox events and campaign status updates via WebSocket.
Overview
MisarMail's real-time delivery contract is defined over WebSocket at wss://api.misar.io/mail/ws/*, with two channels: inbox (user events) and campaign status (per-campaign progress).
Planned interface — not yet live
This page documents the intended WebSocket contract (channels, event types, and payload shapes). A WebSocket server is not yet deployed, so these endpoints are not currently connectable. For real-time progress today, use the Server-Sent Events endpoints, which are live. The channels and events below are the committed contract and will not change shape when the server ships; new events may be added.
Authentication
Authenticate with your API key (msk_...) via the Authorization: Bearer header (Node.js) or ?token= query parameter (browser). WebSocket connections from browsers cannot set Authorization headers.
Channels
| Channel | Path | Description |
|---|---|---|
| Inbox | wss://api.misar.io/mail/ws/inbox | Real-time inbox events for the authenticated user |
| Campaign status | wss://api.misar.io/mail/ws/campaigns/:id | Live campaign delivery progress |
Inbox channel
wss://api.misar.io/mail/ws/inbox?token=msk_your_api_key
Event types
type | Description |
|---|---|
email_received | New inbound email received |
bounce | An outbound email bounced |
complaint | Spam complaint received |
unsubscribe | A contact unsubscribed |
campaign_started | Campaign send began |
campaign_completed | Campaign send finished |
Example events
{
"type": "email_received",
"from": "customer@example.com",
"subject": "Re: Your email",
"receivedAt": "2026-05-27T10:15:00Z"
}{
"type": "campaign_completed",
"campaignId": "uuid",
"campaignName": "May Newsletter",
"sent": 10000,
"delivered": 9855,
"opened": 2340,
"completedAt": "2026-05-27T11:00:00Z"
}Campaign status channel
wss://api.misar.io/mail/ws/campaigns/:id?token=msk_your_api_key
Ownership verified
The server checks that the campaign belongs to the authenticated user before upgrading the WebSocket connection. An unauthenticated or unauthorized request receives HTTP 403 before the WebSocket handshake completes.
Event types
type | Description |
|---|---|
progress | Periodic send progress update |
completed | Campaign send finished |
failed | Campaign send failed |
cancelled | Campaign was cancelled |
Example events
{
"type": "progress",
"campaignId": "uuid",
"sent": 2500,
"total": 10000,
"delivered": 2480,
"bounced": 20,
"opened": 450
}{
"type": "completed",
"campaignId": "uuid",
"sent": 10000,
"delivered": 9855,
"bounced": 145,
"opened": 2340
}TypeScript example
import WebSocket from "ws";
const ws = new WebSocket(
`wss://api.misar.io/mail/ws/campaigns/${campaignId}`,
{ headers: { Authorization: `Bearer msk_your_api_key` } }
);
ws.on("message", (raw) => {
const event = JSON.parse(raw.toString());
if (event.type === "progress") {
const pct = Math.round((event.sent / event.total) * 100);
console.log(`Progress: ${pct}% (${event.sent}/${event.total})`);
}
if (["completed", "failed", "cancelled"].includes(event.type)) {
ws.close();
}
});const ws = new WebSocket(
`wss://api.misar.io/mail/ws/inbox?token=${apiKey}`
);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "email_received") {
showNotification(`New email from ${data.from}`);
}
};Heartbeat
The server sends a ping frame every 30 seconds. The client must respond with a pong. Unresponsive connections are closed after 30 seconds with code 1001.
Close codes
| Code | Meaning |
|---|---|
1000 | Normal closure |
1001 | Server restart or heartbeat timeout |
4401 | Unauthorized — missing or invalid API key |
4403 | Forbidden — campaign does not belong to this account |