Skip to content

WebSockets

Astro is StreamElements’ dedicated websocket gateway. It employs a publish-subscribe (pubsub) pattern to facilitate real-time data updates. Subscribe to topics such as channel activities, session updates, and overlay events to build tools that react to live stream events the moment they happen.

Connect to the WebSocket endpoint:

wss://astro.streamelements.com/

If reconnecting after a graceful shutdown, include the reconnect token as a query parameter:

wss://astro.streamelements.com/?reconnect_token=eyJhbGciOiJIUzI1NiIs...

If the server is draining, it rejects new connections with 502 Bad Gateway.

If the connection rate limit is exceeded, it responds with 429 Too Many Requests and a Retry-After: 2 header.

Subscribing to a topic requires a token, passed as data.token together with its data.token_type:

token_type What it is Where to get it
jwt A StreamElements JWT for your channel. StreamElements dashboard: click your avatar in the top-right corner, select your channel name, choose the correct channel, then copy the token.
apikey A StreamElements Overlay Token for your channel. Same place as the JWT, on the StreamElements dashboard.
oauth2 An OAuth2 access token, used in place of a JWT. Supplied by your OAuth2 integration.

Immediately after connecting, the server sends a welcome message:

{
"id": "01J5KXYZ...",
"ts": "2026-03-19T12:00:00Z",
"type": "welcome",
"data": {
"message": "You are in a maze of dank memes, all alike.",
"client_id": "01J5KXYZ..."
}
}

The server sends WebSocket PING frames every 30 seconds. The client must respond with PONG. If the server receives no pong within 70 seconds, it closes the connection.

These are WebSocket control frames, not application-level JSON messages. Most WebSocket libraries handle pong responses automatically.

sequenceDiagram
    participant Client
    participant Edge as Edge Server

    Client->>Edge: WebSocket Upgrade
    Edge-->>Client: 101 Switching Protocols
    Edge-->>Client: welcome message

    Client->>Edge: subscribe {topic, token}
    Note over Edge: Auth check
    Edge-->>Client: response {success/error}

    loop Every 30s
        Edge-->>Client: PING
        Client->>Edge: PONG
    end

    Edge-->>Client: message {topic, room, data}
    Edge-->>Client: message {topic, room, data}

    Client->>Edge: unsubscribe {topic, room}
    Edge-->>Client: response {success}

    rect rgba(43, 108, 255, 0.12)
        Note over Client,Edge: Graceful Shutdown
        Edge-->>Client: reconnect {token}
        Client->>Edge: New connection + reconnect_token
        Edge-->>Client: welcome (subscriptions restored)
    end

The following parameters are used in a client-to-server request:

Parameter Type Required Description
type string Yes Defines the type of request. Valid options are subscribe and unsubscribe.
nonce string No A unique identifier for the request. Echoed back in the response.
data.topic string Yes The topic to subscribe to.
data.room string No The room/channel to subscribe to. Defaults to "" (global). For unsubscribe, if omitted or empty, unsubscribes from all rooms for the topic.
data.token string For subscribe The token used to authenticate the request.
data.token_type string For subscribe Specifies the type of token. Valid options are jwt, oauth2, and apikey.

Only text frames are accepted. Binary frames are ignored.

Here is an example of a subscribe request:

{
"type": "subscribe",
"nonce": "req-001",
"data": {
"topic": "channel.activities",
"room": "603abc123",
"token": "eyJhbGc...",
"token_type": "jwt"
}
}

Here is an example of an unsubscribe request:

{
"type": "unsubscribe",
"nonce": "req-002",
"data": {
"topic": "channel.activities",
"room": "603abc123"
}
}

To unsubscribe from all rooms for a topic, omit or send an empty room:

{
"type": "unsubscribe",
"nonce": "req-003",
"data": {
"topic": "channel.activities"
}
}
Scope Limit When exceeded
Connections Connection rate limit per client. The server responds with 429 Too Many Requests and a Retry-After: 2 header.
Commands (subscribe/unsubscribe) 1 command per 100 ms, burst of 100 per 10 seconds. A response with error rate_limit_exceeded. Rate limit responses do not include a nonce.
Parameter Type Present on Description
id string All messages Unique message identifier (ULID).
ts string All messages Timestamp in RFC 3339 format.
type string All messages Message type: welcome, response, message, or reconnect.
topic string message The topic the message was published to.
room string message The room the message was published to.
nonce string response Echoes the nonce from the original request.
error string response (errors only) The error code when an error occurred.
data object All messages The message payload.

Here is an example of a successful subscribe response:

{
"id": "01J5KXYZ...",
"ts": "2026-03-19T12:00:01Z",
"type": "response",
"nonce": "req-001",
"data": {
"message": "successfully subscribed to topic",
"topic": "channel.activities",
"room": "603abc123"
}
}

When a message is published to a topic the client is subscribed to:

{
"id": "01J5M2AB...",
"ts": "2026-03-19T12:05:00Z",
"type": "message",
"topic": "channel.activities",
"room": "603abc123",
"data": {
"type": "follow",
"provider": "twitch",
"channel": "603abc123"
}
}

The data field contains the payload from the publisher. See individual topic pages for payload details.

All errors are returned as response messages:

{
"id": "01J5KXYZ...",
"ts": "2026-03-19T12:00:01Z",
"type": "response",
"nonce": "req-001",
"error": "err_bad_request",
"data": {
"message": "human readable description"
}
}
Error Description
err_internal_error Server-side failure.
err_bad_request Malformed request, missing fields, limit exceeded, or invalid topic.
err_unauthorized Authentication failed or permission denied.
err_deadline_exceeded Authorization timed out. Retry the request.
rate_limit_exceeded Command rate limit exceeded.
invalid_message_type Unknown command type (not subscribe or unsubscribe).

Astro supports zero-downtime reconnection during graceful server shutdown.

  1. The server sends a reconnect message to each client:

    {
    "type": "reconnect",
    "data": {
    "message": "The server is shutting down.",
    "reconnect_token": "eyJhbGciOiJIUzI1NiIs..."
    }
    }
  2. The client saves the reconnect_token and opens a new connection:

    wss://astro.streamelements.com/?reconnect_token=eyJhbGciOiJIUzI1NiIs...
  3. The new server verifies the token and restores all subscriptions automatically — no need to re-subscribe.

  4. The client receives a welcome message and resumes normal operation.

Invalid, expired, or tampered reconnect tokens cause the new connection to be closed immediately.

Why are the messages not coming through? I received the message “successfully subscribed to topic”

Section titled “Why are the messages not coming through? I received the message “successfully subscribed to topic””

Make sure you’re using the token for the specific platform from which you want to receive activities. If you have multiple accounts linked (Twitch, YouTube, Kick, etc.), switch to the correct account on the StreamElements dashboard (click your avatar in the top-right corner) and copy the token again.

I’m not receiving YouTube activities, and I’m using the correct token

Section titled “I’m not receiving YouTube activities, and I’m using the correct token”

If your stream is set to private or unlisted, StreamElements cannot access it. Only public YouTube livestreams are supported.

How can I make sure I copied the correct token?

Section titled “How can I make sure I copied the correct token?”

If you are using either a JWT or an Overlay Token (apikey), go to the StreamElements dashboard, click your avatar in the top-right corner > select your channel name, and choose the correct channel. After that, you can copy the correct token.