Skip to content
Console
Menu

Getting Started

Authentication

KV Store

Realtime quickstart

A channel, a connected client, a published message, and a resume after a drop

This takes you from nothing to a message pushed to a connected client, using only a key and curl. Nothing is deployed: the channel lives in Sylphx Events.

The examples use the environment orgs/acme/projects/shop/envs/production; use your own. sylphx access whoami prints the environment your key belongs to, and a key only reaches its own environment.

Shell
export ENV=orgs/acme/projects/shop/envs/production

#1. Create the channel

The channel id is the last segment of its name, and your clients and servers will name it, so choose it rather than letting the server assign one.

curl -sS -X POST "https://api.sylphx.com/v1/$ENV/realtime_channels?realtime_channel_id=orders" \
  -H "Authorization: Bearer $SYLPHX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"spec": {"history_retention": "86400s"}}'

The answer carries status.connect_uri (WebSocket) and status.stream_uri (Server-Sent Events): the two addresses clients connect to.

#2. Mint a token for the client

A browser or device never holds your secret key. Your server mints a token for this one channel and hands it to the client; it lives at most an hour.

Shell
curl -sS -X POST "https://api.sylphx.com/v1/$ENV/realtime_channels/orders:issueToken" \
  -H "Authorization: Bearer $SYLPHX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ttl": "3600s", "client_id": "user-42"}' > token.json
export STREAM_URI=$(jq -r '.connect_uri | sub("^wss://"; "https://") | sub("/subscribe$"; "/stream")' token.json)
export RT_TOKEN=$(jq -r .token token.json)

The answer has the token (rtt_…, returned once), its expire_time and the connect_uri. Naming a client_id puts the client in the channel's presence while it is connected.

#3. Connect a client

In a second terminal, read the channel's Server-Sent Events stream with the token. It stays open and prints each message as it arrives.

Shell
curl -sS -N "$STREAM_URI?token=$RT_TOKEN"

In a browser, the WebSocket at connect_uri does the same and carries presence:

TypeScript
const socket = new WebSocket(`${connectUri}?token=${token}`)
socket.onmessage = (frame) => {
  const { cursor, event } = JSON.parse(frame.data)
  // event.type is the message type, event.data the payload,
  // event.subject the publisher's client id.
  localStorage.setItem('orders-cursor', cursor)
}

#4. Publish

Back in the first terminal, publish a message. Every connected client receives it at once.

curl -sS -X POST "https://api.sylphx.com/v1/$ENV/realtime_channels/orders:publish" \
  -H "Authorization: Bearer $SYLPHX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001-shipped" \
  -d '{"message_type": "order.shipped", "data": {"order": "1001"}}'

The stream prints one frame. Its event: line is the message type, its id: line the cursor, and data: the message as JSON: cursor, and an event whose type, data and subject are the message type, the payload and the publisher's client id. The same Idempotency-Key sent again returns this message and appends nothing.

#5. Resume after a drop

Stop the stream, publish twice more, then reconnect from the cursor the stream last printed:

Shell
curl -sS -N "$STREAM_URI?token=$RT_TOKEN&after_cursor=<cursor>"

The two messages published while you were away arrive first, in order, and then the stream carries on live. An SSE client sends Last-Event-ID on its own; a WebSocket client sends {"op": "subscribe", "afterCursor": "<cursor>"}.

#Read it back

Shell
curl -sS "https://api.sylphx.com/v1/$ENV/realtime_channels/orders/realtime_messages" \
  -H "Authorization: Bearer $SYLPHX_API_KEY"

The channel's history, in order, for as long as history_retention keeps it. realtime_members lists who is connected now, and the channel's status.connection_count counts them.

#Next