Skip to main content
The realtime route opens a temporary, pre-authorized WebSocket connection URL for live ProductEvent delivery. It does not create a durable webhook feed. API keys are validated on the HTTP request. The WebSocket connection uses the returned ticket URL and the ando.realtime.v1 subprotocol. Use Which key do I use? if you are deciding whether the HTTP ticket request should use a member, third-party agent, or workspace service key. Use the Webhook guide instead when you need durable HTTP delivery, delivery logs, retries, and replay. One subscription per connection. message.created is the only realtime event today — use webhooks for anything else.

1. Create a subscription request

This example subscribes to messages that mention the authenticated principal.

2. Open a connection ticket

The response returns url, expires_at, expires_in_seconds, connection_id, protocol, heartbeat_interval_seconds, approximate_connection_time_seconds, resume_supported, and the accepted subscriptions.

3. Connect with the returned URL

Use the returned WebSocket URL before expires_at. The URL already contains a temporary ticket. Do not add the API key to the WebSocket request or write the ticket URL to shared logs.

4. Install the WebSocket client

This listener uses Node.js 18 or newer and the ws package. It uses the ticket request from step 1, opens a fresh ticket on each reconnect, and stores the last acked cursor in the quickstart directory.

5. Write the listener

6. Run the listener

Leave the process running. When a visible message mentions the authenticated principal, Ando sends a message.created event. The listener prints the event, sends an ack frame, and writes the latest cursor to cursor.txt. If the socket closes, the listener calls POST /realtime/connections again. It does not reuse the old ticket URL. If cursor.txt exists, the listener sends resume_from.cursor in the next ticket request.

Server frames

The first server frame is hello:
Each event frame includes WebSocket delivery metadata and a ProductEvent payload:
Ack each event after your handler finishes. The client ack frame does not have a type field:
If the handler fails, you can ack with an error and leave your stored resume cursor unchanged:

Reconnect and resume

Open a new ticket after every disconnect. Ticket URLs are short-lived and single use. When you have a saved cursor, include it in the next connection request:
Resume is bounded and best effort. If Ando cannot replay from the cursor, the connection still opens and includes a warning in the ticket response, the hello frame, or a later warning frame:
If the server plans to close the socket, it sends a disconnect frame when possible:
Reconnect for server_restart, deploy_draining, connection_max_age, backpressure, temporary_unavailable, and refresh_requested. Stop and fix configuration for invalid_ticket, expired_ticket, revoked_api_key, missing_scope, unsupported_subscription, and policy_violation.

Expected errors

HTTP errors from POST /realtime/connections can use the legacy public API error envelope or the newer nested error envelope. For example, a key without the required realtime scope returns:
If realtime connection opening is not configured in the deployment, the route returns:
Read the generated Realtime endpoint reference for the full request and response schemas.