API Reference
WebSocket events, REST endpoints, and data structures
Complete API documentation for the Gryt signaling server.
Web Client API
Audio Processing Hooks
useMicrophone
Manages microphone input and audio processing.
const {
microphoneBuffer,
isRecording,
analyser,
gainNode
} = useMicrophone(shouldAccess: boolean);Parameters:
shouldAccess(boolean): Whether to request microphone access
Returns:
microphoneBuffer(AudioBuffer): Raw microphone audio bufferisRecording(boolean): Whether microphone is currently recordinganalyser(AnalyserNode): Audio analyser for visualizationgainNode(GainNode): Volume control node
useSFU
Manages SFU connection and WebRTC handling.
const {
connect,
disconnect,
isConnected,
isConnecting,
streamSources,
connectionState
} = useSFU();Returns:
connect()(function): Connect to SFU serverdisconnect()(function): Disconnect from SFU serverisConnected(boolean): Connection statusisConnecting(boolean): Connection in progressstreamSources(Map): Active audio streamsconnectionState(string): Current connection state
useSockets
Manages WebSocket connections to signaling servers.
const {
sockets,
clients,
serverDetailsList,
currentConnection
} = useSockets();Returns:
sockets(Map): Active WebSocket connectionsclients(Map): Connected clients per serverserverDetailsList(Array): Available serverscurrentConnection(string): Current server ID
Server API
WebSocket Events
Client → Server
| Event | Payload | Description |
|---|---|---|
join | { channelID: string } | Join a voice channel |
leave | {} | Leave current voice channel |
updateNickname | string | Update user nickname |
updateMute | boolean | Update mute state |
offer | RTCSessionDescription | WebRTC offer for SFU |
answer | RTCSessionDescription | WebRTC answer from SFU |
ice-candidate | RTCIceCandidate | ICE candidate for connection |
Server → Client
| Event | Payload | Description |
|---|---|---|
info | ServerInfo | Server information and channels |
users | UserList | Current users in channels |
user-joined | UserInfo | User joined notification |
user-left | UserInfo | User left notification |
user-updated | UserInfo | User state changed |
offer | RTCSessionDescription | WebRTC offer from SFU |
answer | RTCSessionDescription | WebRTC answer to SFU |
ice-candidate | RTCIceCandidate | ICE candidate from SFU |
REST Endpoints
Messages
GET /api/messages/:conversationId
Get messages for a conversation.
Query Parameters:
limit(number, optional): Number of messages to return (default: 50)before(string, optional): ISO timestamp to get messages before
Response:
{
"items": [
{
"id": "msg_123",
"senderId": "user_456",
"text": "Hello world",
"attachments": ["file_789"],
"created_at": "2024-01-15T10:30:00Z"
}
]
}POST /api/messages/:conversationId
Create a new message.
Request Body:
{
"senderId": "user_456",
"text": "Hello world",
"attachments": ["file_789"]
}Response:
{
"id": "msg_123",
"senderId": "user_456",
"text": "Hello world",
"attachments": ["file_789"],
"created_at": "2024-01-15T10:30:00Z"
}Uploads
POST /api/uploads
Upload a file.
Request: multipart/form-data
file: The file to upload
Response:
{
"fileId": "file_789",
"key": "uploads/file_789.jpg",
"thumbnailKey": "thumbnails/file_789_320.jpg"
}Custom Emojis
GET /api/emojis
List all custom server emojis. No authentication required.
Response:
[
{ "name": "pepehappy", "file_id": "abc-123" },
{ "name": "catjam", "file_id": "def-456" }
]GET /api/emojis/img/:name
Serve a custom emoji image by name (128x128 PNG). Long-lived cache headers.
POST /api/emojis
Upload a custom emoji. Requires admin or owner role.
Request: multipart/form-data
file: Image file (any format; resized to 128x128 PNG server-side)name: Emoji shortcode name (2-32 lowercase alphanumeric/underscore chars)
Response:
{ "name": "pepehappy", "file_id": "abc-123" }DELETE /api/emojis/:name
Delete a custom emoji. Requires admin or owner role.
Response:
{ "ok": true }Data Structures
ServerInfo
interface ServerInfo {
name: string;
members: string;
channels: Channel[];
}Channel
interface Channel {
id: string;
name: string;
type: 'voice' | 'text';
}UserInfo
interface UserInfo {
id: string;
nickname: string;
isMuted: boolean;
hasJoinedChannel: boolean;
isConnectedToVoice: boolean;
streamID?: string;
}SFU API
WebSocket Events
Client → SFU
| Event | Payload | Description |
|---|---|---|
join | JoinMessage | Join a room with user information |
leave | LeaveMessage | Leave current room |
offer | RTCSessionDescription | WebRTC offer from client |
answer | RTCSessionDescription | WebRTC answer from client |
ice-candidate | RTCIceCandidate | ICE candidate from client |
SFU → Client
| Event | Payload | Description |
|---|---|---|
joined | JoinedMessage | Confirmation of room join |
user-joined | UserJoinedMessage | Another user joined the room |
user-left | UserLeftMessage | User left the room |
offer | RTCSessionDescription | WebRTC offer from SFU |
answer | RTCSessionDescription | WebRTC answer from SFU |
ice-candidate | RTCIceCandidate | ICE candidate from SFU |
Message Types
JoinMessage
type JoinMessage struct {
RoomID string `json:"roomId"`
UserID string `json:"userId"`
UserInfo struct {
Nickname string `json:"nickname"`
IsMuted bool `json:"isMuted"`
} `json:"userInfo"`
}JoinedMessage
type JoinedMessage struct {
RoomID string `json:"roomId"`
UserID string `json:"userId"`
Peers []string `json:"peers"`
Success bool `json:"success"`
Message string `json:"message,omitempty"`
}Debug Endpoints
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Health check |
/debug/rooms | GET | Active rooms |
/debug/peers | GET | Peer connections |
/debug/tracks | GET | Media tracks |
/metrics | GET | Prometheus metrics |
Auth Service API
Authentication Endpoints
User Registration
POST /api/register
Register a new user account.
Request Body:
{
"email": "[email protected]",
"password": "securepassword",
"nickname": "UserNickname"
}Response:
{
"success": true,
"message": "Registration successful. Please check your email for verification.",
"userId": "user_123456789"
}User Login
POST /api/login
Authenticate user and get access token.
Request Body:
{
"email": "[email protected]",
"password": "securepassword"
}Response:
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "refresh_token_here",
"user": {
"id": "user_123456789",
"email": "[email protected]",
"nickname": "UserNickname",
"verified": true
}
}Token Validation
GET /api/validate
Validate an authentication token.
Headers:
Authorization: Bearer <token>
Response:
{
"valid": true,
"user": {
"id": "user_123456789",
"email": "[email protected]",
"nickname": "UserNickname",
"verified": true
}
}Refresh Token
POST /api/refresh
Get a new access token using refresh token.
Request Body:
{
"refreshToken": "refresh_token_here"
}Response:
{
"success": true,
"token": "new_jwt_token_here",
"refreshToken": "new_refresh_token_here"
}User Management Endpoints
Get User Profile
GET /api/user/profile
Get current user's profile information.
Headers:
Authorization: Bearer <token>
Response:
{
"id": "user_123456789",
"email": "[email protected]",
"nickname": "UserNickname",
"avatar": "https://example.com/avatar.jpg",
"verified": true,
"created_at": "2024-01-15T10:30:00Z"
}Update User Profile
PUT /api/user/profile
Update user profile information.
Headers:
Authorization: Bearer <token>
Request Body:
{
"nickname": "NewNickname",
"avatar": "https://example.com/new-avatar.jpg"
}Response:
{
"success": true,
"user": {
"id": "user_123456789",
"email": "[email protected]",
"nickname": "NewNickname",
"avatar": "https://example.com/new-avatar.jpg",
"verified": true
}
}Change Password
PUT /api/user/password
Change user password.
Headers:
Authorization: Bearer <token>
Request Body:
{
"currentPassword": "oldpassword",
"newPassword": "newpassword"
}Response:
{
"success": true,
"message": "Password changed successfully"
}Error Codes
Server Error Codes
| Code | Description | Solution |
|---|---|---|
AUTH_001 | Invalid credentials | Check email/password |
AUTH_002 | Token expired | Use refresh token |
AUTH_003 | Rate limit exceeded | Wait and retry |
AUTH_004 | Account not verified | Check email for verification |
AUTH_005 | Account suspended | Contact support |
WebSocket Error Codes
| Code | Description | Solution |
|---|---|---|
WS_001 | Connection failed | Check server status |
WS_002 | Authentication required | Provide valid token |
WS_003 | Room not found | Check room ID |
WS_004 | User already in room | Leave current room first |
WS_005 | Room full | Wait for space |
SFU Error Codes
| Code | Description | Solution |
|---|---|---|
SFU_001 | WebRTC connection failed | Check STUN servers and SFU UDP media port range |
SFU_002 | Track not found | Check track ID |
SFU_003 | Room not found | Check room ID |
SFU_004 | Peer connection failed | Check network connectivity |
SDK Examples
JavaScript SDK
import { GrytClient } from '@gryt/client-sdk';
const client = new GrytClient({
serverUrl: 'wss://server.example.com',
authToken: 'your-auth-token'
});
// Connect to server
await client.connect();
// Join a voice channel
await client.joinChannel('general');
// Update mute state
await client.setMuted(true);
// Leave channel
await client.leaveChannel();Go SDK
package main
import (
"github.com/gryt/sfu-go"
"log"
)
func main() {
client := sfu.NewClient("ws://localhost:5005")
// Connect to SFU
err := client.Connect()
if err != nil {
log.Fatal(err)
}
// Join room
err = client.JoinRoom("test-room", "user-123")
if err != nil {
log.Fatal(err)
}
// Handle incoming tracks
client.OnTrack(func(track *webrtc.TrackRemote) {
log.Printf("Received track: %s", track.ID())
})
}Rate Limits
Authentication Service
- Login attempts: 5 per 15 minutes per IP
- Registration: 3 per hour per IP
- API calls: 1000 per hour per user
- Password reset: 3 per hour per email
Signaling Server
- WebSocket messages: 100 per minute per connection
- Room joins: 10 per minute per user
- File uploads: 10 per hour per user
SFU Server
- WebRTC connections: 50 per minute per IP
- Track additions: 100 per minute per connection
- ICE candidates: 200 per minute per connection