Skip to main content

WebSocket Endpoint

Sockudo implements the Pusher WebSocket protocol. Connect to the WebSocket endpoint using your application key:
ws://host:port/app/{appKey}
For secure connections:
wss://host:port/app/{appKey}

Connection Parameters

Optional query parameters can be included:
protocol
integer
default:"7"
Protocol version (currently version 7)
client
string
Client library name (e.g., “pusher-js”)
version
string
Client library version

Connection Handshake

When a WebSocket connection is established, the server immediately sends a pusher:connection_established event:
{
  "event": "pusher:connection_established",
  "data": "{\"socket_id\":\"123456.789012\",\"activity_timeout\":120}"
}
event
string
Always pusher:connection_established
data
string
JSON-encoded string containing connection details
data.socket_id
string
Unique identifier for this connection in the format high.low (e.g., “123456.789012”)
data.activity_timeout
integer
Number of seconds before the connection is considered inactive (default: 120)

Socket ID

The socket_id is a unique identifier for each WebSocket connection:
  • Format: Two random integers separated by a period (e.g., “1234567890.9876543210”)
  • Used for authentication signatures on private/presence channels
  • Required when publishing client events
  • Automatically generated by the server

Keep-Alive Protocol

Sockudo uses ping/pong frames to keep connections alive:

Server-Initiated Ping

The server may send a pusher:ping event to check connection health:
{
  "event": "pusher:ping",
  "data": null
}
Clients should respond with a pusher:pong event:
{
  "event": "pusher:pong",
  "data": null
}

Client-Initiated Ping

Clients can also send pusher:ping to verify the connection is active. The server will respond with pusher:pong.

Error Handling

The server sends error messages in this format:
{
  "event": "pusher:error",
  "data": {
    "code": 4001,
    "message": "Application does not exist"
  },
  "channel": null
}
data.code
integer
Error code (4000-4999 range)
data.message
string
Human-readable error description
channel
string | null
Channel name if the error is channel-specific, otherwise null

Common Error Codes

CodeDescription
4000Generic error
4001Application does not exist
4004Application disabled
4005Origin not allowed
4009Connection timeout
4100Buffer full - slow consumer disconnected

Example: Connecting with pusher-js

import Pusher from 'pusher-js';

const pusher = new Pusher('your-app-key', {
  wsHost: 'localhost',
  wsPort: 6001,
  forceTLS: false,
  enabledTransports: ['ws'],
  cluster: '' // Leave empty for self-hosted
});

pusher.connection.bind('connected', () => {
  console.log('Socket ID:', pusher.connection.socket_id);
});

pusher.connection.bind('error', (err) => {
  console.error('Connection error:', err);
});

Connection Lifecycle

  1. Client opens WebSocket connection to /app/{appKey}
  2. Server validates the application key
  3. Server sends pusher:connection_established with socket_id
  4. Connection is active - client can now subscribe to channels
  5. Server may send periodic pusher:ping frames
  6. Client responds with pusher:pong to maintain connection
  7. Connection remains open until closed by client or server

Origin Validation

Sockudo supports per-app origin validation for additional security. Configure allowed origins in your app configuration:
{
  "allowed_origins": [
    "https://app.example.com",
    "*.staging.example.com",
    "http://localhost:3000"
  ]
}
Connections from unauthorized origins receive error code 4005.

Build docs developers (and LLMs) love