sondahub

sondahub / SSE test server

Server-Sent Events test server

An SSE clock you can set the pace of, and live event streams from seven mock APIs — ids, named events, retry and Last-Event-ID resumption included. Free, no key, CORS open.

The endpoints

GET/v1/utils/sse?count=10&interval=1000A clock: count ticks (up to 1,000), one every interval ms (50–10,000), each with an id; a note event every fifth tick; done at the end.
GET/v1/{api}/events?topics=a,bA mock API’s own activity, one tick a second, each event named after its topic. Same events as the WebSocket stream.
GET/v1/utils/stream/{n}?interval=100Not SSE but its cousin: n lines of NDJSON, chunked — for clients that read a streamed body.
GET/v1/utils/drip?numbytes=20&duration=3Bytes dripped over a duration, for timeouts and progress bars.

With curl

Five ticks
curl -N "https://api.sondahub.com/v1/utils/sse?count=5&interval=1000"

retry: 3000
: sondahub clock — 5 ticks every 1000 ms

id: 1
event: tick
data: {"n":1,"of":5,"iso":"…","unix_ms":…}
…
event: done
data: {"sent":5}
A live departures board
curl -N "https://api.sondahub.com/v1/flights/events?topics=board"

From a browser

const es = new EventSource('https://api.sondahub.com/v1/utils/sse?count=10&interval=1000')
es.addEventListener('tick', (e) => console.log(e.lastEventId, JSON.parse(e.data)))
es.addEventListener('done', () => es.close())

const board = new EventSource('https://api.sondahub.com/v1/flights/events?topics=board')
board.addEventListener('board', (e) => console.log(JSON.parse(e.data).data))

CORS is open, so this works from any page.

Topics per API

APIAddressEvents
Storehttps://api.sondahub.com/v1/store/eventsorders — An order changing status (paid → shipped → delivered).
inventory — A stock level moving at a warehouse.
Fleethttps://api.sondahub.com/v1/fleet/eventstelemetry — A fresh reading from one of the devices, with its serial, type and metrics.
alerts — An alert opening or resolving.
devices — A device going online, offline or degraded.
Bankhttps://api.sondahub.com/v1/bank/eventsfx — A rate ticking: pair, rate, bid, ask.
transactions — A card payment posting on one of the seed accounts.
Socialhttps://api.sondahub.com/v1/social/eventsposts — A new post from one of the seed users.
likes — Someone liking something.
Helpdeskhttps://api.sondahub.com/v1/helpdesk/eventstickets — A ticket opening, being assigned, or changing status.
messages — A new message on a ticket.
Flightshttps://api.sondahub.com/v1/flights/eventsboard — The departures board: a flight boarding, departing, delayed, landing or cancelled.
bookings — A seat being booked or checked in on a seed flight.
Identityhttps://api.sondahub.com/v1/identity/eventsdirectory — Someone joining, leaving, changing team, or being deactivated or reactivated.
logins — A sign-in: who, how (SAML, OIDC, password), from where, and whether it worked.

Questions

Why does EventSource.onmessage not fire?

Because every event here is named — tick, note and done on the clock, the topic on the API streams — and onmessage only receives unnamed ones. Listen with addEventListener(name, …), as in the snippet above.

Does reconnection with Last-Event-ID work?

Yes. Each stream sends retry: 3000, numbers its events, and a reconnect carrying Last-Event-ID continues the numbering — the clock resumes after that tick. EventSource does this by itself; for a client that does not, the clock also takes ?last=.

Is there an SSE endpoint that answers a POST?

Yes — the MCP server streams its answer as text/event-stream when a POST asks for it and the tool streams (slow_operation): progress notifications first, then the result. That is the shape a fetch-based SSE client has to handle.

Are connections kept alive behind proxies?

The API streams send a comment line every fifteen seconds, and every stream answers with Cache-Control: no-store and X-Accel-Buffering: no so proxies pass events through as they come.