Skip to main content

Real-time (SSE)

RSMG Engage streams live discussion activity over Server-Sent Events (SSE). To subscribe, mint a short-lived, single-use ticket from your backend, then open an EventSource to the stream with that ticket.

1. Mint a ticket (backend)

POST /api/v1/stream/ticket-by-external
X-API-Key: ek_…
Content-Type: application/json

{ "externalId": "article-123" }
{ "data": { "ticket": "…", "discussionId": "…", "expiresAt": "…", "discussionStatus": "open" } }

Tickets are short-lived (~60 s) and single-use, so mint one per connection. You can also mint by UUID via POST /api/v1/stream/ticket with { "discussionId": "…" }.

2. Connect (client)

const es = new EventSource(
`https://{slug}.rsmg-engage.com/api/v1/stream/${discussionId}?ticket=${ticket}`,
);
es.addEventListener('comment_created', (e) => render(JSON.parse(e.data)));

The ticket is the only credential the browser needs — no API key reaches the client.

Event types

EventWhen
comment_createdA comment is posted
comment_editedA comment body changes
comment_deletedA comment is removed (carries deletedBy)
comment_approved / comment_rejectedModeration decision on a pending comment
comment_pinned / comment_unpinnedAdmin pins/unpins
reaction_toggledA reaction is added/removed
discussion_locked / discussion_unlocked / discussion_archivedDiscussion lifecycle change
poll_vote / poll_status_changedPoll activity

Two framing events bracket the stream: connected on subscribe, and connection-timeout when a long-lived connection is cycled.

Suppressing your own echoes

Every event includes originatedBy: { userId: string | null } — the acting reader's internal user id, which is null for admin and visitor actions. If your client knows the internal id, match on it to skip echoing an action you just performed locally.

For clients that don't hold internal ids, two sibling fields cover the gap:

  • externalUserId on reaction_toggled — the reacting reader's external (your-side) id.
  • ballotKey on poll_vote — for anonymous poll voters.

Match either against your local viewer to self-suppress without ever seeing internal ids.

See Stream in the API Reference for payload shapes, and Webhooks for server-to-server delivery of the same events.