WebSocket API Documentation
The PianoRhythm WebSocket API enables real-time, bidirectional communication between clients and the server. This document details the WebSocket protocol, message types, and usage patterns.
๐ Connection Establishmentโ
WebSocket Endpointโ
wss://api.pianorhythm.io/api/websocket
Authenticationโ
The WebSocket handshake is authenticated by the same JWT used for the REST API. The
client must already hold a valid access token cookie (obtained via /login,
/register, or /oauth2/discord); the browser attaches it automatically on
upgrade. Native clients may instead send the token via the Authorization: Bearer <token> header.
// Browser โ cookies set by /login flow are sent automatically.
const ws = new WebSocket('wss://api.pianorhythm.io/api/websocket');
The server derives uuid, username, usertag, and role membership directly
from the token claims, and mints a fresh socket_id for each connection. The
generated socket_id is returned to the client in the welcome message.
Connection Lifecycleโ
- WebSocket Handshake - HTTP upgrade to WebSocket (JWT cookie/header attached)
- Token Verification - Server validates the Ed25519-signed access token
- Session Initialization - User session created with a freshly generated
socket_id - Welcome Message - Server sends user data including the
socket_id - Ready State - Connection ready for messages
๐จ Message Protocolโ
Message Formatโ
All messages use Protocol Buffers for efficient binary serialization:
message ServerMessage {
ServerMessageType messageType = 1;
oneof message {
CreateRoomCommand createRoomCommand = 2;
UpdateRoomCommand updateRoomCommand = 3;
JoinRoomByName joinRoomByName = 4;
RoomChatMessage roomChatMessage = 5;
MidiMessage midiMessage = 6;
ServerCommand serverCommand = 7;
AvatarCommand avatarCommand = 8;
// ... additional message types
}
}
Message Typesโ
Room Management Messagesโ
CreateRoomCommand- Create a new roomUpdateRoomCommand- Update room settingsJoinRoomByName- Join room by nameJoinNextAvailableLobby- Join any available lobbyLeaveRoom- Leave current room
Communication Messagesโ
RoomChatMessage- Send chat messageRoomChatServerCommand- Server chat commandsPrivateMessage- Direct user messaging
Game Messagesโ
MidiMessage- Musical note dataAvatarCommand- Avatar updatesUserStatusUpdate- Status changes
System Messagesโ
ServerCommand- General server commandsHeartbeatMessage- Connection keep-aliveErrorMessage- Error notifications
๐ฎ Room Managementโ
Creating a Roomโ
message CreateRoomCommand {
string room_name = 1;
RoomType room_type = 2;
string password = 3;
RoomSettings settings = 4;
}
Example Usage:
const createRoomMessage = {
messageType: 'CreateRoomCommand',
createRoomCommand: {
room_name: 'My Piano Room',
room_type: 'PUBLIC',
password: '',
settings: {
max_users: 10,
allow_chat: true,
allow_guests: true
}
}
};
ws.send(encodeProtobuf(createRoomMessage));
Joining a Roomโ
message JoinRoomByName {
string room_name = 1;
string password = 2;
}
Server Response:
message RoomJoinedResponse {
bool success = 1;
RoomInfo room_info = 2;
repeated UserInfo current_users = 3;
string error_message = 4;
}
Room Settingsโ
message RoomSettings {
int32 max_users = 1;
bool allow_chat = 2;
bool allow_guests = 3;
bool auto_moderation = 4;
bool require_pro = 5;
string welcome_message = 6;
}
๐ฌ Chat Systemโ
Sending Chat Messagesโ
message RoomChatMessage {
string message = 1;
ChatMessageType message_type = 2;
}
Message Types:
USER_MESSAGE- Regular user messageSYSTEM_MESSAGE- System notificationBOT_MESSAGE- Bot-generated messageMODERATOR_MESSAGE- Moderator announcement
Chat Commandsโ
Special commands prefixed with /:
/help- Show available commands/users- List users in room/kick <username>- Kick user (moderators only)/ban <username>- Ban user (moderators only)/mute <username>- Mute user (moderators only)
Chat Moderationโ
message RoomChatServerCommand {
string command = 1;
string target_user = 2;
string reason = 3;
}
๐ต MIDI Messagesโ
MIDI Data Formatโ
message MidiMessage {
bytes midi_data = 1;
int64 timestamp = 2;
string user_id = 3;
}
MIDI Event Typesโ
- Note On - Key press events
- Note Off - Key release events
- Control Change - Pedal and other controls
- Program Change - Instrument selection
Real-time Synchronizationโ
- Timestamp Sync - Server timestamps for synchronization
- Latency Compensation - Client-side prediction
- Jitter Buffer - Smooth playback despite network variations
๐ค User Managementโ
Avatar Updatesโ
message AvatarCommand {
AvatarAction action = 1;
AvatarData avatar_data = 2;
}
enum AvatarAction {
UPDATE_POSITION = 0;
UPDATE_APPEARANCE = 1;
UPDATE_STATUS = 2;
}
User Statusโ
enum UserStatus {
ONLINE = 0;
AWAY = 1;
BUSY = 2;
INVISIBLE = 3;
}
Friend Systemโ
message FriendRequest {
string target_user_id = 1;
FriendAction action = 2;
}
enum FriendAction {
SEND_REQUEST = 0;
ACCEPT_REQUEST = 1;
DECLINE_REQUEST = 2;
REMOVE_FRIEND = 3;
}
๐ Server Commandsโ
General Commandsโ
message ServerCommand {
ServerCommandType commandType = 1;
map<string, string> parameters = 2;
}
enum ServerCommandType {
JOIN = 0;
LEAVE = 1;
CREATE_OR_JOIN_ROOM = 2;
ENTER_LOBBY = 3;
UPDATE_SETTINGS = 4;
}
System Commandsโ
HEARTBEAT- Connection keep-aliveRECONNECT- Request reconnectionSYNC_STATE- Synchronize client stateUPDATE_PERMISSIONS- Refresh user permissions
๐ก Client-Server Communication Patternsโ
Request-Response Patternโ
// Client sends request
const requestId = generateUniqueId();
const message = {
messageType: 'GetRoomInfo',
requestId: requestId,
getRoomInfo: { room_id: 'room123' }
};
ws.send(encodeProtobuf(message));
// Server responds with matching requestId
ws.onmessage = (event) => {
const response = decodeProtobuf(event.data);
if (response.requestId === requestId) {
// Handle response
}
};
Event Broadcastingโ
// Server broadcasts to all room members
const broadcastMessage = {
messageType: 'UserJoinedRoom',
userJoinedRoom: {
user_info: userInfo,
room_id: 'room123'
}
};
// All clients in room receive this message
Heartbeat Mechanismโ
// Client sends heartbeat every 30 seconds
setInterval(() => {
const heartbeat = {
messageType: 'HeartbeatMessage',
heartbeatMessage: {
timestamp: Date.now()
}
};
ws.send(encodeProtobuf(heartbeat));
}, 30000);
// Server responds with heartbeat acknowledgment
๐ก๏ธ Error Handlingโ
Connection Errorsโ
- Authentication Failed - Invalid credentials
- Connection Timeout - Network issues
- Rate Limited - Too many messages
- Server Unavailable - Maintenance mode
Message Errorsโ
message ErrorMessage {
ErrorType error_type = 1;
string error_code = 2;
string error_message = 3;
map<string, string> error_details = 4;
}
enum ErrorType {
VALIDATION_ERROR = 0;
PERMISSION_ERROR = 1;
RESOURCE_ERROR = 2;
SYSTEM_ERROR = 3;
}
Reconnection Strategyโ
class WebSocketClient {
constructor(url) {
this.url = url;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectDelay = 1000;
}
connect() {
this.ws = new WebSocket(this.url);
this.ws.onclose = (event) => {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
setTimeout(() => {
this.reconnectAttempts++;
this.connect();
}, this.reconnectDelay * Math.pow(2, this.reconnectAttempts));
}
};
}
}
๐ Performance Considerationsโ
Message Optimizationโ
- Binary Protocol - Protocol Buffers for efficiency
- Message Batching - Group related messages
- Compression - WebSocket compression enabled
Connection Managementโ
- Connection Pooling - Reuse connections where possible
- Graceful Degradation - Handle partial connectivity
- Resource Cleanup - Proper connection disposal
Monitoringโ
- Message Rates - Track messages per second
- Connection Count - Monitor active connections
- Error Rates - Track connection and message errors
- Latency Metrics - Measure round-trip times
The WebSocket API provides the foundation for real-time multiplayer piano gaming, enabling synchronized musical collaboration and social interaction.