MisarMisar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisarSEOMisar PlatformMisar SSO
Streaming

Newsletter Send Progress

Monitor newsletter issue send progress in real time using Server-Sent Events.

Overview

The newsletter send-stream endpoint delivers live progress updates while a newsletter issue is being sent to subscribers. Use it to display a real-time progress bar in your dashboard or integration.


Endpoint

GET api.misar.io/blog/newsletter/issues/:id/send-stream
Authorization: Bearer mbk_your_api_key

Returns text/event-stream — a Server-Sent Events stream.


Response headers

HeaderValue
Content-Typetext/event-stream
Cache-Controlno-cache, no-transform
X-Accel-Bufferingno

Event format

Each event is a JSON-encoded data line:

data: {"status":"sending","sent":250,"total":1000,"opened":42,"bounced":3}

data: {"status":"sent","sent":1000,"total":1000,"opened":380,"bounced":12}

data: [DONE]

Fields

status"sending" | "sent" | "failed" | "cancelled"

Current send status. "sent", "failed", and "cancelled" are terminal states.

sentnumber

Number of emails sent so far.

totalnumber

Total recipients in the issue.

openednumber

Emails opened (tracked via pixel).

bouncednumber

Emails that bounced.


Stream behavior

  • Polls the issue status every 3 seconds
  • Terminates automatically when status reaches "sent", "failed", or "cancelled"
  • Times out after 10 minutes and sends data: [DONE]
  • Returns error event {"error":"issue_not_found"} if the issue ID doesn't belong to your account

Error events

data: {"error":"unauthorized"}
data: [DONE]
data: {"error":"issue_not_found"}
data: [DONE]
data: {"error":"poll_failed"}
data: [DONE]
data: {"error":"stream_error"}
data: [DONE]

An unauthorized event is returned with HTTP 401 when the API key is missing or invalid. issue_not_found is returned when the issue ID doesn't belong to your account. poll_failed and stream_error indicate a transient server-side read error.


Browser example

const issueId = "your-issue-uuid";
const token = "mbk_your_api_key";

const source = new EventSource(
  `https://api.misar.io/blog/newsletter/issues/${issueId}/send-stream`,
  {
    // EventSource doesn't support Authorization headers — use a short-lived
    // signed URL or proxy the request through your backend
  }
);

// Alternatively use fetch + ReadableStream for header support:
const res = await fetch(
  `https://api.misar.io/blog/newsletter/issues/${issueId}/send-stream`,
  { headers: { Authorization: `Bearer ${token}` } }
);

const reader = res.body!.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const lines = decoder.decode(value).split("\n\n");
  for (const line of lines) {
    if (line.startsWith("data: [DONE]")) return;
    if (line.startsWith("data: ")) {
      const event = JSON.parse(line.slice(6));
      updateProgressBar(event.sent, event.total);
      if (["sent", "failed", "cancelled"].includes(event.status)) return;
    }
  }
}

Authentication

Requires a valid API key (mbk_…) in the Authorization: Bearer header. The issue must belong to the authenticated account, or the stream returns an issue_not_found error event.