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
| Header | Value |
|---|---|
Content-Type | text/event-stream |
Cache-Control | no-cache, no-transform |
X-Accel-Buffering | no |
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.
sentnumberNumber of emails sent so far.
totalnumberTotal recipients in the issue.
openednumberEmails opened (tracked via pixel).
bouncednumberEmails that bounced.
Stream behavior
- Polls the issue status every 3 seconds
- Terminates automatically when
statusreaches"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.