https://relay.plooza.io/apiInclude JWT token in Authorization header:
Authorization: Bearer <jwt_token>Register a new user
{
"username": "string (3-20 chars)",
"firstName": "string (1-50 chars)",
"lastName": "string (1-50 chars)",
"age": "number (13-120)",
"bio": "string (optional, max 500 chars)",
"password": "string (min 6 chars)"
}Login user
{
"username": "string",
"password": "string"
}Get current user info (requires authentication)
Get user profile by ID
Update current user profile
{
"firstName": "string (optional)",
"lastName": "string (optional)",
"bio": "string (optional)",
"avatarUrl": "string (optional)"
}Search users by username, firstName, or lastName
Get user's chats
Create or get existing chat with user
{
"userId": "string (cuid)"
}Get chat messages
Query params: limit (default: 50), offset (default: 0)
Send a message
{
"chatId": "string (cuid)",
"content": "string (1-4000 chars)",
"attachments": ["fileId1", "fileId2"], // optional
"replyToId": "string (cuid)" // optional
}Get specific message by ID
Add reaction to message
{
"emoji": "string (emoji character)"
}Remove reaction from message
Initiate a call
{
"chatId": "string (cuid)",
"type": "audio" | "video"
}Answer incoming call
Reject incoming call
End active call
Get available reaction emojis
Get all reactions (admin only)
Get all music files with metadata
Extract metadata from audio file
{
"fileId": "string (cuid)"
}Upload a file
Content-Type: multipart/form-data
Form field: file
Max size: 100MB
Supported types: images, videos, audio, documents
Download or stream file by ID
Returns file with appropriate Content-Type header
Admin authentication
{
"username": "admin",
"password": "admin123"
}Get system statistics
Get all users (admin only)
Get all messages (admin only)
URL: wss://relay.plooza.io/ws?token=YOUR_JWT_TOKEN
Authentication: Pass JWT token as query parameter
// Authentication (alternative to query param)
{
"type": "auth",
"data": { "token": "jwt_token" }
}
// Send message
{
"type": "message:send",
"data": { "chatId": "chat_id", "content": "message" }
}
// Typing indicators
{
"type": "typing:start",
"data": { "chatId": "chat_id" }
}
{
"type": "typing:stop",
"data": { "chatId": "chat_id" }
}
// Call signaling
{
"type": "call:offer",
"callId": "call_id",
"offer": { /* RTCSessionDescription */ }
}
{
"type": "call:answer",
"callId": "call_id",
"answer": { /* RTCSessionDescription */ }
}
{
"type": "call:ice-candidate",
"callId": "call_id",
"candidate": { /* RTCIceCandidate */ }
}// Authentication
{
"type": "auth:success",
"data": { "userId": "user_id", "username": "username" }
}
{
"type": "auth:error",
"data": { "message": "error_message" }
}
// Messages
{
"type": "message:new",
"data": {
"id": "msg_id",
"content": "message",
"sender": {...},
"attachments": [...],
"replyTo": {...}
}
}
{
"type": "message:status",
"data": {
"messageId": "msg_id",
"status": "delivered" | "read",
"chatId": "chat_id"
}
}
// Reactions
{
"type": "reaction:new",
"data": {
"messageId": "msg_id",
"chatId": "chat_id",
"reaction": { "emoji": "👍", "userId": "user_id" }
}
}
{
"type": "reaction:removed",
"data": {
"messageId": "msg_id",
"chatId": "chat_id",
"reactionId": "reaction_id"
}
}
// Typing indicators
{
"type": "typing:start",
"data": { "chatId": "chat_id", "userId": "user_id", "username": "username" }
}
{
"type": "typing:stop",
"data": { "chatId": "chat_id", "userId": "user_id" }
}
// Calls
{
"type": "call:incoming",
"data": {
"id": "call_id",
"chatId": "chat_id",
"type": "audio" | "video",
"initiator": {...}
}
}
{
"type": "call:ended",
"data": {
"id": "call_id",
"chatId": "chat_id",
"status": "ended" | "rejected" | "cancelled",
"duration": 123
}
}
// Call signaling (WebRTC)
{
"type": "call:offer",
"callId": "call_id",
"offer": { /* RTCSessionDescription */ }
}
{
"type": "call:answer",
"callId": "call_id",
"answer": { /* RTCSessionDescription */ }
}
{
"type": "call:ice-candidate",
"callId": "call_id",
"candidate": { /* RTCIceCandidate */ }
}