WebSocket protocol
The WebSocket protocol is how you get realtime state out of Skynet and (where permitted) how you push commands at telescopes. Two distinct WebSocket endpoints are exposed by the public API:
/v1/ws/stream— subscribe/publish for snapshots, events, and log entries. The common case./v1/ws/commands— command publish + command-result events. For sending commands at telescopes and receiving their results.
The protocol is defined by Pydantic models in
skynet_sdk.schemas.ws_protocol
and rendered into the OpenAPI spec for type-generation purposes. The
TypeScript SDK exposes the message types as a discriminated union.
This section is structured as:
- Streams — snapshots and events you subscribe to.
- Commands — commands you can publish (mount, camera, filter wheel, focuser, rotator, lease).
- Direct request/response — synchronous RPC-like calls over the WebSocket transport.
Connection
The connection URLs are:
wss://api.skynetgo.org/v1/ws/stream
wss://api.skynetgo.org/v1/ws/commands
Use the appropriate base URL for your environment (see
Environments). Locally,
ws://127.0.0.1:5001/v1/ws/stream etc.
Authentication
Bearer token, passed via one of:
- Query string —
?token=<access-token>. Easiest for browser WebSocket APIs (which don't let you set custom headers). Authorizationheader — for non-browser clients.- Session cookie — for browser clients already signed into the
web app (the same
skynet_sessioncookie).
The token is the same OAuth access token used for REST requests. See Auth.
Message envelope
Every message on the WebSocket carries a kind discriminator
(WsMessageKind). The full set:
Lifecycle
| Kind | Direction | Purpose |
|---|---|---|
ping |
both | Liveness check |
pong |
both | Response to ping |
ack |
both | Acknowledge a request that has no other response |
error |
server → client | Error envelope (see below) |
Stream messages (on /v1/ws/stream)
| Kind | Direction | Purpose |
|---|---|---|
subscribe_stream |
client → server | Subscribe to one or more streams |
unsubscribe_stream |
client → server | Unsubscribe |
publish_device_snapshot |
client → server (SkyNode) | Publish a new device snapshot |
publish_telescope_snapshot |
client → server (SkyNode) | Publish a new telescope snapshot |
publish_constraint_snapshot |
client → server (SkyNode) | Publish a new constraint snapshot |
publish_constraint_status_snapshot |
client → server (SkyNode) | Publish constraint status |
publish_telescope_log |
client → server (SkyNode) | Publish a telescope log line |
event_device_snapshot |
server → client | Subscribed-stream device snapshot delivery |
event_telescope_snapshot |
server → client | Telescope snapshot delivery |
event_instrument_snapshot |
server → client | Instrument snapshot delivery |
event_constraint_snapshot |
server → client | Constraint snapshot delivery |
event_constraint_status_snapshot |
server → client | Constraint status delivery |
event_manual_control_lease |
server → client | Manual control lease state change |
event_telescope_log |
server → client | Telescope log delivery |
Command messages (on /v1/ws/commands)
| Kind | Direction | Purpose |
|---|---|---|
subscribe_commands |
client → server | Subscribe to command and command-result streams |
unsubscribe_commands |
client → server | Unsubscribe |
publish_command |
client → server | Publish a command at a telescope |
cancel_command |
client → server | Cancel a previously-published command |
publish_command_result |
client → server (SkyNode) | SkyNode publishes a command result |
event_command |
server → client | Command delivery to subscribers |
event_command_result |
server → client | Command result delivery |
Direct request/response (on /v1/ws/commands)
| Kind | Direction | Purpose |
|---|---|---|
direct_request |
client → server | Synchronous RPC-style request |
direct_response_start |
server → client | Response stream start (metadata) |
direct_response_chunk |
server → client | Response data chunk |
direct_response_end |
server → client | Response stream end |
direct_error |
server → client | Direct-request error |
Error envelope
WebSocket errors carry more structure than REST errors:
{
"kind": "error",
"id": "<optional correlation id>",
"code": "invalid | forbidden | not_found | conflict | internal",
"message": "<human-readable message>",
"details": { /* per-error structured detail */ }
}
The code field is from a fixed enum so clients can dispatch
without parsing message.
Subscribe/publish model
The fundamental pattern: open the WebSocket, send a subscribe_*
message identifying what you want, and start receiving event_*
messages. Multiple subscriptions are fine on a single connection;
each subscription has its own filter.
For the specific filter shapes and what each stream carries, see Streams.
SDK support
The TypeScript SDK exposes the WS message types under
packages/ts/skynet-sdk/src/schemas.ts
as a discriminated union. The Python SDK ships them at
skynet_sdk.schemas.ws_protocol. Use these — don't hand-roll the
message JSON.