The SpacetimeDB WebSocket API
As an extension of the HTTP API, SpacetimeDB offers a WebSocket API. Clients can subscribe to a database via a WebSocket connection to receive streaming updates as the database changes, and send requests to invoke reducers. Messages received from the server over a WebSocket will follow the same total ordering of transactions as are committed to the database.
The SpacetimeDB SDKs comminicate with their corresponding database using the WebSocket API.
Connecting
To initiate a WebSocket connection, send a GET
request to the /database/subscribe/:name_or_address
endpoint with headers appropriate to upgrade to a WebSocket connection as per RFC 6455.
To re-connect with an existing identity, include its token in a SpacetimeDB Authorization header. Otherwise, a new identity and token will be generated for the client.
Protocols
Clients connecting via WebSocket can choose between two protocols, v1.bin.spacetimedb
and v1.text.spacetimedb
. Clients should include one of these protocols in the Sec-WebSocket-Protocol
header of their request.
Sec-WebSocket-Protocol header value |
Selected protocol |
---|---|
v1.bin.spacetimedb |
Binary |
v1.text.spacetimedb |
Text |
Binary Protocol
The SpacetimeDB binary WebSocket protocol, v1.bin.spacetimedb
, encodes messages using ProtoBuf 3, and reducer and row data using BSATN.
The binary protocol's messages are defined in client_api.proto
.
Text Protocol
The SpacetimeDB text WebSocket protocol, v1.text.spacetimedb
, encodes messages, reducer and row data as JSON. Reducer arguments and table rows are JSON-encoded according to the SATN JSON format.
Messages
Client to server
Message | Description |
---|---|
FunctionCall |
Invoke a reducer. |
Subscribe |
Register queries to receive streaming updates for a subset of the database. |
`FunctionCall`
Clients send a FunctionCall
message to request that the database run a reducer. The message includes the reducer's name and a SATS ProductValue
of arguments.
Binary: ProtoBuf definition
message FunctionCall {
string reducer = 1;
bytes argBytes = 2;
}
Field | Value |
---|---|
reducer |
The name of the reducer to invoke. |
argBytes |
The reducer arguments encoded as a BSATN ProductValue . |
Text: JSON encoding
{
"call": {
"fn": string,
"args": array,
}
}
Field | Value |
---|---|
fn |
The name of the reducer to invoke. |
args |
The reducer arguments encoded as a JSON array. |
`Subscribe`
Clients send a Subscribe
message to register SQL queries in order to receive streaming updates.
The client will only receive TransactionUpdate
s for rows to which it is subscribed, and for reducer runs which alter at least one subscribed row. As a special exception, the client is always notified when a reducer run it requests via a FunctionCall
message fails.
SpacetimeDB responds to each Subscribe
message with a SubscriptionUpdate
message containing all matching rows at the time the subscription is applied.
Each Subscribe
message establishes a new set of subscriptions, replacing all previous subscriptions. Clients which want to add a query to an existing subscription must send a Subscribe
message containing all the previous queries in addition to the new query. In this case, the returned SubscriptionUpdate
will contain all previously-subscribed rows in addition to the newly-subscribed rows.
Each query must be a SQL SELECT * FROM
statement on a single table with an optional WHERE
clause. See the SQL Reference for the subset of SQL supported by SpacetimeDB.
Binary: ProtoBuf definition
message Subscribe {
repeated string query_strings = 1;
}
Field | Value |
---|---|
query_strings |
A sequence of strings, each of which contains a single SQL query. |
Text: JSON encoding
{
"subscribe": {
"query_strings": array<string>
}
}
Field | Value |
---|---|
query_strings |
An array of strings, each of which contains a single SQL query. |
Server to client
Message | Description |
---|---|
IdentityToken |
Sent once upon successful connection with the client's identity and token. |
SubscriptionUpdate |
Initial message in response to a Subscribe message. |
TransactionUpdate |
Streaming update after a reducer runs containing altered rows. |
`IdentityToken`
Upon establishing a WebSocket connection, the server will send an IdentityToken
message containing the client's identity and token. If the client included a SpacetimeDB Authorization header in their connection request, the IdentityToken
message will contain the same token used to connect, and its corresponding identity. If the client connected anonymously, SpacetimeDB will generate a new identity and token for the client.
Binary: ProtoBuf definition
message IdentityToken {
bytes identity = 1;
string token = 2;
}
Field | Value |
---|---|
identity |
The client's public Spacetime identity. |
token |
The client's private access token. |
Text: JSON encoding
{
"IdentityToken": {
"identity": array<number>,
"token": string
}
}
Field | Value |
---|---|
identity |
The client's public Spacetime identity. |
token |
The client's private access token. |
`SubscriptionUpdate`
In response to a Subscribe
message, the database sends a SubscriptionUpdate
containing all of the matching rows which are resident in the database at the time the Subscribe
was received.
Binary: ProtoBuf definition
message SubscriptionUpdate {
repeated TableUpdate tableUpdates = 1;
}
message TableUpdate {
uint32 tableId = 1;
string tableName = 2;
repeated TableRowOperation tableRowOperations = 3;
}
message TableRowOperation {
enum OperationType {
DELETE = 0;
INSERT = 1;
}
OperationType op = 1;
bytes row = 3;
}
Each SubscriptionUpdate
contains a TableUpdate
for each table with subscribed rows. Each TableUpdate
contains a TableRowOperation
for each subscribed row. SubscriptionUpdate
, TableUpdate
and TableRowOperation
are also used by the TransactionUpdate
message to encode rows altered by a reducer, so TableRowOperation
includes an OperationType
which identifies the row alteration as either an insert or a delete. When a client receives a SubscriptionUpdate
message in response to a Subscribe
message, all of the TableRowOperation
s will have op
of INSERT
.
TableUpdate field |
Value |
---|---|
tableId |
An integer identifier for the table. A table's tableId is not stable, so clients should not depend on it. |
tableName |
The string name of the table. Clients should use this field to identify the table, rather than the tableId . |
tableRowOperations |
A TableRowOperation for each inserted or deleted row. |
TableRowOperation field |
Value |
---|---|
op |
INSERT for inserted rows during a TransactionUpdate or rows resident upon applying a subscription; DELETE for deleted rows during a TransactionUpdate . |
row |
The altered row, encoded as a BSATN ProductValue . |
Text: JSON encoding
// SubscriptionUpdate:
{
"SubscriptionUpdate": {
"table_updates": array<TableUpdate>
}
}
// TableUpdate:
{
"table_id": number,
"table_name": string,
"table_row_operations": array<TableRowOperation>
}
// TableRowOperation:
{
"op": "insert" | "delete",
"row": array
}
Each SubscriptionUpdate
contains a TableUpdate
for each table with subscribed rows. Each TableUpdate
contains a TableRowOperation
for each subscribed row. SubscriptionUpdate
, TableUpdate
and TableRowOperation
are also used by the TransactionUpdate
message to encode rows altered by a reducer, so TableRowOperation
includes an "op"
field which identifies the row alteration as either an insert or a delete. When a client receives a SubscriptionUpdate
message in response to a Subscribe
message, all of the TableRowOperation
s will have "op"
of "insert"
.
TableUpdate field |
Value |
---|---|
table_id |
An integer identifier for the table. A table's table_id is not stable, so clients should not depend on it. |
table_name |
The string name of the table. Clients should use this field to identify the table, rather than the table_id . |
table_row_operations |
A TableRowOperation for each inserted or deleted row. |
TableRowOperation field |
Value |
---|---|
op |
"insert" for inserted rows during a TransactionUpdate or rows resident upon applying a subscription; "delete" for deleted rows during a TransactionUpdate . |
row |
The altered row, encoded as a JSON array. |
`TransactionUpdate`
Upon a reducer run, a client will receive a TransactionUpdate
containing information about the reducer which ran and the subscribed rows which it altered. Clients will only receive a TransactionUpdate
for a reducer invocation if either of two criteria is met:
- The reducer ran successfully and altered at least one row to which the client subscribes.
- The reducer was invoked by the client, and either failed or was terminated due to insufficient energy.
Each TransactionUpdate
contains a SubscriptionUpdate
with all rows altered by the reducer, including inserts and deletes; and an Event
with information about the reducer itself, including a FunctionCall
containing the reducer's name and arguments.
Binary: ProtoBuf definition
message TransactionUpdate {
Event event = 1;
SubscriptionUpdate subscriptionUpdate = 2;
}
message Event {
enum Status {
committed = 0;
failed = 1;
out_of_energy = 2;
}
uint64 timestamp = 1;
bytes callerIdentity = 2;
FunctionCall functionCall = 3;
Status status = 4;
string message = 5;
int64 energy_quanta_used = 6;
uint64 host_execution_duration_micros = 7;
}
Field | Value |
---|---|
event |
An Event containing information about the reducer run. |
subscriptionUpdate |
A SubscriptionUpdate containing all the row insertions and deletions committed by the transaction. |
Event field |
Value |
---|---|
timestamp |
The time when the reducer started, as microseconds since the Unix epoch. |
callerIdentity |
The identity of the client which requested the reducer invocation. For event-driven and scheduled reducers, this is the identity of the database owner. |
functionCall |
A FunctionCall containing the name of the reducer and the arguments passed to it. |
status |
committed if the reducer ran successfully and its changes were committed to the database; failed if the reducer signaled an error; out_of_energy if the reducer was canceled due to insufficient energy. |
message |
The error message with which the reducer failed if status is failed , or the empty string otherwise. |
energy_quanta_used |
The amount of energy consumed by running the reducer. |
host_execution_duration_micros |
The duration of the reducer's execution, in microseconds. |
Text: JSON encoding
// TransactionUpdate:
{
"TransactionUpdate": {
"event": Event,
"subscription_update": SubscriptionUpdate
}
}
// Event:
{
"timestamp": number,
"status": "committed" | "failed" | "out_of_energy",
"caller_identity": string,
"function_call": {
"reducer": string,
"args": array,
},
"energy_quanta_used": number,
"message": string
}
Field | Value |
---|---|
event |
An Event containing information about the reducer run. |
subscription_update |
A SubscriptionUpdate containing all the row insertions and deletions committed by the transaction. |
Event field |
Value |
---|---|
timestamp |
The time when the reducer started, as microseconds since the Unix epoch. |
status |
committed if the reducer ran successfully and its changes were committed to the database; failed if the reducer signaled an error; out_of_energy if the reducer was canceled due to insufficient energy. |
caller_identity |
The identity of the client which requested the reducer invocation. For event-driven and scheduled reducers, this is the identity of the database owner. |
function_call.reducer |
The name of the reducer. |
function_call.args |
The reducer arguments encoded as a JSON array. |
energy_quanta_used |
The amount of energy consumed by running the reducer. |
message |
The error message with which the reducer failed if status is failed , or the empty string otherwise. |