Clients

Talking to Ursula from any HTTP client.

Ursula speaks plain HTTP and Server-Sent Events. There is no required client library; any HTTP client in any language works.

The examples elsewhere in these docs use curl because it's universal. The same routes, headers, and query parameters apply to every other client.

Minimal examples

# create a bucket and stream
curl -X PUT http://127.0.0.1:4437/demo
curl -X PUT http://127.0.0.1:4437/demo/hello

# append
curl -X POST http://127.0.0.1:4437/demo/hello \
  -H 'Content-Type: application/octet-stream' \
  --data-binary 'hello world'

# catch-up read
curl 'http://127.0.0.1:4437/demo/hello?offset=-1'

# live tail
curl 'http://127.0.0.1:4437/demo/hello?offset=-1&live=sse'

Notes for client implementers

  • After every read and append, the server returns Stream-Next-Offset. Track it; use it as the offset query parameter on the next read. Don't construct offsets manually; they're opaque.
  • For binary streams over SSE, data events arrive as a JSON envelope ({ encoding, contentType, payload }) with a base64 payload. See Binary SSE.
  • For exactly-once writes, send Producer-Id, Producer-Epoch, Producer-Seq headers and retry on network errors; the server deduplicates. See Exactly-once writes.
  • For conditional writes, use If-Match with the previous ETag or Stream-Seq with a monotonically increasing token. See Conditional writes.