Protocol
SignalR is used as the communication layer for the WebSocket API.
It handles the real-time, bidirectional connection between Bluebox and connected clients. This allows the server to push data to clients immediately, without clients repeatedly polling the API.
Message Type
Defines the type of a Hub Message.
Name | Value | Description |
|---|---|---|
| 1 | Indicates the message is an Invocation message and implements the InvocationMessage interface. |
| 2 | Indicates the message is a StreamItem message and implements the StreamItemMessage interface. |
| 3 | Indicates the message is a Completion message and implements the CompletionMessage interface. |
| 4 | Indicates the message is a Stream Invocation message and implements the StreamInvocationMessage interface. |
| 5 | Indicates the message is a Cancel Invocation message and implements the CancelInvocationMessage interface. |
| 6 | Indicates the message is a Ping message and implements the PingMessage interface. |
| 7 | Indicates the message is a Close message and implements the CloseMessage interface. |
Record Separator
SignalR uses a Record Separator character to mark the end of each JSON protocol message.
The Record Separator is the ASCII control character 30:
0x1E
\u001e
␞
Negotiation
Every WebSocket connection needs to start with a negotiation.
Request
The client sends an HTTP POST request to the server’s /negotiate endpoint.
Establishing the WebSocket connection | ||
type | object | |
properties | ||
| Negotiate version | |
type | number | |
const | 1 | |
Example request
POST https://interay.io/hubs/properties/negotiate?negotiateVersion=1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Response
The server responds with a JSON payload containing the connectionId, available transports, and connection tokens.
type | object | |
properties | ||
| Negotiate version | |
type | number | |
| Connection ID | |
type | string | |
| Secret connection token | |
type | string | |
| Available transports | |
type | array | |
Example response
{
"negotiateVersion": 1,
"connectionId": "abc123",
"connectionToken": "secret-connection-token",
"availableTransports": [
{
"transport": "WebSockets",
"transferFormats": [
"Text",
"Binary"
]
},
{
"transport": "ServerSentEvents",
"transferFormats": [
"Text"
]
},
{
"transport": "LongPolling",
"transferFormats": [
"Text",
"Binary"
]
}
]
}
Connection
The client uses this information to initiate the actual persistent connection (e.g., upgrading an HTTP request to a WebSocket).
wss://interay.io/hubs/hub | ||
Opens the WebSocket connection | ||
type | object | |
properties | ||
| Secret connection token | |
type | string | |
Example connection
wss://interay.io/hubs/properties?id=secret-connection-token
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Handshake
After the transport connection has been opened, the client sends a handshake message:
type | object | |
properties | ||
| Protocol | |
type | string | |
const | json | |
| Version | |
type | number | |
const | 1 | |
Example client request
{
"protocol": "json",
"version": 1
}␞
Example server response
{
}␞
Ping
SignalR periodically sends Ping messages to keep an idle connection active and to confirm that the remote endpoint is still reachable. SignalR does not define a separate Pong message. The client needs to respond with a Ping message to confirm that the connection is active.
type | object | |
properties | ||
| Message Type | |
type | number | |
const | 6 | |
Example server request
{
"type": 6
}␞
Example client response
{
"type": 6
}␞
Invocation
An Invocation message requests the receiving endpoint to execute a method identified by the target field. The method arguments are provided in the arguments array. When an invocationId is included, the receiver returns a Completion message containing the same identifier and either a result or an error. Invocation messages may be sent by either the server or a connected client.
Client to server
type | object | |
properties | ||
| Message Type | |
type | number | |
const | 1 | |
| Invocation ID | |
type | string | |
| Function name | |
type | string | |
| Function arguments | |
type | array | |
Response
type | object | |
properties | ||
| Message Type | |
type | number | |
const | 1 | |
| Invocation ID | |
type | string | |
| Function result | |
type | object | |
Notes
The invocationId needs to be incremented on every invocation.
Example client request
{
"type": 1,
"invocationId": "12",
"target": "SetProperties",
"arguments": [
{
...
}
]
}␞
Example server response
{
"type": 3,
"invocationId": "12",
"result": {
...
}
}␞
Server to client
type | object | |
properties | ||
| Message Type | |
type | number | |
const | 1 | |
| Function name | |
type | string | |
| Function arguments | |
type | array | |
Example server request
{
"type": 1,
"target": "Notify",
"arguments": [
{
...
}
]
}␞