Real-time notification stream (SSE)

Stream new in-app notifications to foregrounded clients via Server-Sent Events.

GET /v1/me/notifications/stream pushes each new in-app Notification row to
connected clients the moment it is persisted, without polling. Use this endpoint
when the app is foregrounded so travelers see disruption alerts instantly.

Authentication

Same requirement as all other /v1 endpoints: sign the request with the
consumer HMAC and pass a valid traveler JWT in the
Authorization: Bearer <token> header.

A missing or invalid token returns 401.

Protocol

The endpoint uses Server-Sent Events (text/event-stream). Clients should:

  1. Open the connection with Accept: text/event-stream (most SSE client
    libraries set this automatically).
  2. Handle each event named notification as it arrives.
  3. Reconnect automatically when the connection closes — use the standard
    SSE retry: field or a fixed back-off strategy.
GET /v1/me/notifications/stream HTTP/1.1
Authorization: Bearer <token>
Accept: text/event-stream
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache

Event format

notification — new in-app row

Emitted for every new Notification row persisted for the authenticated
traveler. The data field is a JSON-serialised
NotificationOut object
(the same shape returned by GET /v1/me/notifications).

event: notification
data: {"id":"...","eventType":"SEGMENT_DELAYED","severity":"warning","title":"Flight delayed","body":"Your flight is delayed by 30 minutes.",...}

done — stream closing

Emitted when the server initiates a graceful shutdown. After receiving this
event the client should reconnect if it still needs real-time delivery.

event: done
data: {}

Example payload

{
  "id": "018f2c3e-1234-7abc-8def-000000000001",
  "tripId": "018f2c3e-1234-7abc-8def-000000000002",
  "segmentId": "018f2c3e-1234-7abc-8def-000000000003",
  "eventType": "SEGMENT_DELAYED",
  "severity": "warning",
  "title": "Flight delayed",
  "body": "Your flight MXP → LHR is delayed by 30 minutes.",
  "deepLink": "mercury://trips/018f2c3e/segment/018f2c3e",
  "channel": "push",
  "dispatchedAt": "2026-05-25T10:30:00Z",
  "readAt": null,
  "isDedupSkipped": false,
  "deliveryStatus": "delivered",
  "createdAt": "2026-05-25T10:30:00Z"
}

Single-process limitation

The SSE fan-out is in-process: only clients connected to the same Mercury
worker process that dispatched the notification receive it in real time. In a
multi-worker deployment, some SSE clients may miss an event.

Recommended client strategy:

  • On reconnect, call GET /v1/me/notifications to catch up on any rows
    delivered while the SSE connection was closed or routed to a different worker.
  • Do not rely solely on SSE for authoritative notification state — treat it as
    a low-latency hint and fall back to the REST poll endpoint for catch-up.

Relationship to push notifications

When the app is connected via SSE, the client should suppress local push
notification UI for events it receives via the stream to avoid double-alerting
the traveler. The push notification is still sent; the client decides at
render time whether to display it based on SSE connection state.

Error responses

StatusCondition
401Missing or invalid bearer token
503Notification fan-out service not available (startup in progress)

Reporting issues

This page is maintained by the BizAway integration team. To request changes or
report an error, contact your BizAway integration contact. Edits made directly
in the ReadMe dashboard are overwritten on the next publish.