MisarMisar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisarSEOMisar PlatformMisar SSO
API Reference

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

ChannelPathDescription
Inboxwss://api.misar.io/mail/ws/inboxReal-time inbox events for the authenticated user
Campaign statuswss://api.misar.io/mail/ws/campaigns/:idLive campaign delivery progress

Inbox channel

wss://api.misar.io/mail/ws/inbox?token=msk_your_api_key

Event types

typeDescription
email_receivedNew inbound email received
bounceAn outbound email bounced
complaintSpam complaint received
unsubscribeA contact unsubscribed
campaign_startedCampaign send began
campaign_completedCampaign 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

typeDescription
progressPeriodic send progress update
completedCampaign send finished
failedCampaign send failed
cancelledCampaign 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

CodeMeaning
1000Normal closure
1001Server restart or heartbeat timeout
4401Unauthorized — missing or invalid API key
4403Forbidden — campaign does not belong to this account