Read stream
bucketpathstringrequiredBucket ID.
streampathstringrequiredStream ID within the bucket.
offsetquerystringStarting offset: -1 for the beginning, now for the current tail, or a Stream-Next-Offset value from an earlier response.
cursorquerystringOn a long-poll or SSE read, the Stream-Cursor value from the previous live response. It lets caches tell successive live requests apart. It is not a position and never replaces offset.
consistencyquerystringlocal (default) or leader, on catch-up reads only. leader makes the read linearizable: it includes every append acknowledged before the request, at the cost of one round trip from the group's leader to a majority of voters. Use it to read back your own acknowledged writes. Combining it with live answers 400. See Read path.
livequerystringLive mode: sse for Server-Sent Events, long-poll for long-polling. Omit for catch-up read.
max_bytesquerynumberOn an offset read, the maximum bytes to read in one response or SSE data batch. Every response is capped at 8 MiB; a larger value is clamped, and a value that is not a decimal integer is ignored. A shortened response has no Stream-Up-To-Date and may end inside a message, on a JSON stream too; continue from Stream-Next-Offset. For UTF-8 SSE data, Ursula may shorten the emitted batch so Stream-Next-Offset lands on a valid text boundary.
Read modes
No live parameter. Returns all available data from the given offset immediately.
curl 'http://127.0.0.1:4437/demo/hello?offset=-1'live=long-poll. Returns immediately if data is available, otherwise holds the connection until new data arrives or timeout_ms elapses (default 1000, at most 60000).
curl 'http://127.0.0.1:4437/demo/hello?offset=00000000000000000042&live=long-poll'live=sse. Opens a persistent Server-Sent Events connection. The server pushes data events as new entries are appended. It sends no heartbeats, so a proxy with an idle timeout may close a quiet connection; reconnect from the last control event's streamNextOffset.
curl 'http://127.0.0.1:4437/demo/hello?offset=-1&live=sse'Stream-IncarnationheaderstringOptional precondition: the stream's incarnation token, as a previous response's Stream-Incarnation header returned it. The read is answered only if the stream that serves it is still that incarnation; otherwise it answers 412. A long-poll or SSE read with it ends when the stream it was opened against is deleted or recreated (a long-poll answers 404 or 412; an SSE stream ends with an error event). Without the header, a long-poll still ends when the stream it registered against is recreated, usually with 416; otherwise the request behaves exactly as described here. A malformed value answers 400. See Stream-Incarnation.
Response
| Status | Meaning |
|---|---|
200 | Data returned. A catch-up read at the tail answers 200 with an empty body and Stream-Up-To-Date: true. |
204 | Long-poll only: timeout_ms passed without new data, or the stream is closed and the read is at its tail (answered at once with Stream-Closed: true, which signals end of stream). |
304 | If-None-Match matched the response's ETag, compared weakly. A read the server may gzip (JSON or NDJSON, at least 256 bytes) has a weak tag (W/"…"). |
307 | In a cluster, this node could not serve the read as the stream's group leader (a long-poll or SSE read on a follower, a consistency=leader read on a node that lost leadership, or a read that would answer 404, 410 or 416 on a leader that cannot confirm its leadership). Location is the same request on the leader. |
400 | Invalid offset, live mode or consistency, consistency=leader with live, a read parameter removed in 0.6.0 (see the release notes), or incarnation or aligned, which immutable reads carry in the path instead. |
404 | Stream not found or expired. |
410 | Requested offset has been trimmed. Stream-Next-Offset is the earliest offset still readable, and Stream-Incarnation the token of the stream that answered. |
412 | Stream-Incarnation did not match: the stream was deleted and recreated. The response's Stream-Incarnation is the current token. A read that would answer 404, 410 or 416 without the header still does. |
416 | Requested offset is beyond the stream's tail, on a catch-up read or a long-poll. Stream-Next-Offset is the tail, and Stream-Incarnation the token of the stream that answered. A 410 or 416 comes before the Stream-Incarnation precondition, so compare its token with yours: another token means the stream was replaced, not that your offset is wrong. |
503 | The group has no known leader, the leader could not confirm its leadership in time (consistency=leader and live reads), or this node holds too many live readers. Retry after Retry-After. |
Response headers include Stream-Next-Offset, Stream-Incarnation, ETag, Stream-Up-To-Date, Stream-Closed, and Content-Type; the SSE response and the long-poll 204 carry Stream-Incarnation too. Long-poll responses for an open stream also carry Stream-Cursor.
Streams written with Content-Type: application/json are returned as newline-delimited JSON with response Content-Type: application/x-ndjson, one stored message per line, exactly as written minus insignificant whitespace (JSON message text). On an offset read, max_bytes applies to the encoded byte stream, so a response can end mid-line. Resume from Stream-Next-Offset and buffer any incomplete trailing line before parsing. HEAD reports the configured stream content type, while read responses report the wire representation.
SSE event format
In SSE mode, the server sends:
- Data events (
event: data): stream payload in thedatafield. The responseStream-Data-Content-Typeheader identifies the data payload type (application/x-ndjsonfor JSON streams, the original content type for other streams). SSEdata:lines are transport lines, not guaranteed message boundaries. JSON clients should buffer until newline before parsing messages. For binary streams, data is base64-encoded (controlled by theStream-Sse-Data-Encodingheader). - Control events (
event: control): JSON metadata including the current offset and stream state.
curl 'http://127.0.0.1:4437/demo/hello?offset=-1'curl 'http://127.0.0.1:4437/demo/hello?offset=00000000000000000042&live=long-poll'curl 'http://127.0.0.1:4437/demo/hello?offset=-1&live=sse'curl -N 'http://127.0.0.1:4437/demo/hello?offset=now&live=sse'See read modes, binary SSE, and offsets for more details.