{"openapi":"3.0.0","info":{"title":"Relay Messenger API","version":"1.0.0","description":"\n# Relay Messenger API\n\nRealtime messenger backend with distributed relay nodes.\n\n## Features\n- User authentication with JWT\n- Real-time messaging via WebSocket\n- File uploads and attachments\n- Message status tracking (sent/delivered/read)\n- User search and chat management\n- Admin panel\n\n## WebSocket Connection\nConnect to WebSocket at: `wss://relay.plooza.io/ws?token=YOUR_JWT_TOKEN`\n\n### WebSocket Events\n\n**Client -> Server:**\n- No events needed (authentication via query param)\n\n**Server -> Client:**\n- `auth:success` - Authentication successful\n- `auth:error` - Authentication failed\n- `message:new` - New message received\n- `message:status` - Message status updated\n\n### Message Status Flow\n1. `sent` - Message sent by sender\n2. `delivered` - Message delivered to recipient\n3. `read` - Message read by recipient\n      ","contact":{"name":"Relay Messenger","url":"https://relay.plooza.io"}},"servers":[{"url":"https://relay.plooza.io/api","description":"Production server"},{"url":"http://localhost:3000/api","description":"Development server"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Enter your JWT token"}},"schemas":{"User":{"type":"object","required":["id","username","firstName","lastName"],"properties":{"id":{"type":"string","format":"cuid","description":"Unique user identifier","example":"clx1234567890abcdefgh"},"username":{"type":"string","description":"Unique username","example":"johndoe"},"firstName":{"type":"string","description":"User first name","example":"John"},"lastName":{"type":"string","description":"User last name","example":"Doe"},"age":{"type":"integer","minimum":13,"maximum":120,"description":"User age","example":25},"bio":{"type":"string","maxLength":500,"description":"User biography","example":"Software developer from San Francisco"},"avatarUrl":{"type":"string","nullable":true,"description":"URL to user avatar image","example":"/uploads/1234567890-avatar.jpg"},"createdAt":{"type":"string","format":"date-time","description":"Account creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last profile update timestamp"}}},"Chat":{"type":"object","required":["id","createdAt"],"properties":{"id":{"type":"string","format":"cuid","description":"Unique chat identifier","example":"clx1234567890abcdefgh"},"createdAt":{"type":"string","format":"date-time","description":"Chat creation timestamp"},"participants":{"type":"array","description":"List of chat participants","items":{"$ref":"#/components/schemas/User"}},"lastMessage":{"type":"object","description":"Last message in chat","properties":{"content":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}}}},"Message":{"type":"object","required":["id","chatId","senderId","content","createdAt"],"properties":{"id":{"type":"string","format":"cuid","description":"Unique message identifier","example":"clx1234567890abcdefgh"},"chatId":{"type":"string","format":"cuid","description":"Chat identifier","example":"clx1234567890abcdefgh"},"senderId":{"type":"string","format":"cuid","description":"Sender user identifier","example":"clx1234567890abcdefgh"},"content":{"type":"string","maxLength":4000,"description":"Message text content","example":"Hello, how are you?"},"status":{"type":"string","enum":["sent","delivered","read"],"description":"Message delivery status","example":"delivered"},"createdAt":{"type":"string","format":"date-time","description":"Message creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Message last update timestamp"},"sender":{"$ref":"#/components/schemas/User","description":"Sender user object"},"attachments":{"type":"array","description":"Message file attachments","items":{"$ref":"#/components/schemas/File"}}}},"File":{"type":"object","required":["id","uploaderId","size","mimeType","status"],"properties":{"id":{"type":"string","format":"cuid","description":"Unique file identifier","example":"clx1234567890abcdefgh"},"uploaderId":{"type":"string","format":"cuid","description":"Uploader user identifier","example":"clx1234567890abcdefgh"},"storageType":{"type":"string","enum":["s3","relay_cache"],"description":"File storage type","example":"relay_cache"},"s3Key":{"type":"string","nullable":true,"description":"S3 object key (if stored in S3)","example":"uploads/2024/01/file.jpg"},"localPath":{"type":"string","nullable":true,"description":"Local file path (if stored locally)","example":"/uploads/1234567890-file.jpg"},"size":{"type":"integer","description":"File size in bytes","example":1024000},"mimeType":{"type":"string","description":"File MIME type","example":"image/jpeg"},"status":{"type":"string","enum":["pending","uploaded","synced"],"description":"File upload status","example":"uploaded"},"createdAt":{"type":"string","format":"date-time","description":"File upload timestamp"}}},"LoginRequest":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string","description":"User username","example":"johndoe"},"password":{"type":"string","format":"password","description":"User password","example":"SecurePass123!"}}},"RegisterRequest":{"type":"object","required":["username","firstName","lastName","age","password"],"properties":{"username":{"type":"string","description":"Desired username (unique)","example":"johndoe"},"firstName":{"type":"string","description":"User first name","example":"John"},"lastName":{"type":"string","description":"User last name","example":"Doe"},"age":{"type":"integer","minimum":13,"maximum":120,"description":"User age","example":25},"bio":{"type":"string","maxLength":500,"description":"User biography (optional)","example":"Software developer"},"password":{"type":"string","format":"password","minLength":6,"description":"User password (min 6 characters)","example":"SecurePass123!"}}},"SendMessageRequest":{"type":"object","required":["chatId","content"],"properties":{"chatId":{"type":"string","format":"cuid","description":"Target chat identifier","example":"clx1234567890abcdefgh"},"content":{"type":"string","maxLength":4000,"description":"Message text content","example":"Hello, how are you?"},"attachments":{"type":"array","description":"Array of file IDs to attach","items":{"type":"string","format":"cuid"},"example":["clx1234567890abcdefgh"]}}},"AuthResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string","description":"JWT authentication token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}}}},"Error":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string","description":"Error message","example":"Invalid credentials"},"details":{"type":"array","description":"Detailed error information","items":{"type":"object"}}}},"Success":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","description":"Response data"}}}}},"security":[{"bearerAuth":[]}],"tags":[{"name":"Authentication","description":"User authentication endpoints"},{"name":"Users","description":"User management endpoints"},{"name":"Chats","description":"Chat management endpoints"},{"name":"Messages","description":"Message endpoints"},{"name":"Files","description":"File upload and management"},{"name":"Admin","description":"Admin panel endpoints"}],"paths":{"/auth/login":{"post":{"summary":"Login user","tags":["Authentication"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"type":"string","example":"johndoe"},"password":{"type":"string","example":"password123"}}}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string"}}}}}],"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}}}}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Authenticate user and return JWT token","security":[]}},"/auth/register":{"post":{"summary":"Register a new user","tags":["Authentication"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username","firstName","lastName","age","password"],"properties":{"username":{"type":"string","minLength":3,"maxLength":20,"example":"johndoe"},"firstName":{"type":"string","minLength":1,"maxLength":50,"example":"John"},"lastName":{"type":"string","minLength":1,"maxLength":50,"example":"Doe"},"age":{"type":"integer","minimum":13,"maximum":120,"example":25},"bio":{"type":"string","maxLength":500,"example":"Hello world!"},"password":{"type":"string","minLength":6,"example":"password123"}}}}}},"responses":{"201":{"description":"User registered successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","properties":{"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string"}}}}}],"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}}}}}}},"400":{"description":"Validation error or username already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"description":"Create a new user account","security":[]}}}}