This document provides comprehensive documentation for the Real-Time Collaborative Editor REST API and WebSocket protocol.
Base URL: http://localhost:3001/api (development)
Authentication: JWT Bearer tokens required for most endpoints
Content-Type: application/json
- Authentication Endpoints
- Document Management Endpoints
- Health Check Endpoints
- WebSocket Protocol
- Error Responses
- Rate Limits
Create a new user account.
Endpoint: POST /api/auth/register
Authentication: None required
Request Body:
{
"email": "user@example.com",
"password": "securePassword123",
"name": "John Doe"
}Validation Rules:
email: Valid email format, uniquepassword: Minimum 8 charactersname: 1-100 characters
Success Response (201 Created):
{
"message": "User registered successfully",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"createdAt": "2025-01-15T10:30:00.000Z"
},
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Error Responses:
400 Bad Request: Invalid input or validation error409 Conflict: Email already exists500 Internal Server Error: Server error
Example:
curl -X POST http://localhost:3001/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securePassword123",
"name": "John Doe"
}'Authenticate with existing credentials.
Endpoint: POST /api/auth/login
Authentication: None required
Request Body:
{
"email": "user@example.com",
"password": "securePassword123"
}Success Response (200 OK):
{
"message": "Login successful",
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"preferences": {
"editorTheme": "light",
"cursorColor": "#4A90E2"
}
},
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Error Responses:
400 Bad Request: Missing email or password401 Unauthorized: Invalid credentials500 Internal Server Error: Server error
Example:
curl -X POST http://localhost:3001/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securePassword123"
}'Obtain a new access token using a refresh token.
Endpoint: POST /api/auth/refresh
Authentication: None required (refresh token in body)
Request Body:
{
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Success Response (200 OK):
{
"message": "Token refreshed successfully",
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}Error Responses:
400 Bad Request: Missing refresh token401 Unauthorized: Invalid or expired refresh token500 Internal Server Error: Server error
Example:
curl -X POST http://localhost:3001/api/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}'Retrieve the authenticated user's profile.
Endpoint: GET /api/auth/me
Authentication: Required (Bearer token)
Success Response (200 OK):
{
"user": {
"id": "507f1f77bcf86cd799439011",
"email": "user@example.com",
"name": "John Doe",
"preferences": {
"editorTheme": "light",
"cursorColor": "#4A90E2"
},
"createdAt": "2025-01-15T10:30:00.000Z",
"lastLoginAt": "2025-01-16T14:20:00.000Z"
}
}Error Responses:
401 Unauthorized: Missing or invalid token404 Not Found: User not found500 Internal Server Error: Server error
Example:
curl -X GET http://localhost:3001/api/auth/me \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Create a new collaborative document.
Endpoint: POST /api/documents
Authentication: Required (Bearer token)
Request Body:
{
"title": "My New Document"
}Validation Rules:
title: Required, 1-200 characters, non-empty after trimming
Success Response (201 Created):
{
"id": "507f1f77bcf86cd799439012",
"title": "My New Document",
"ownerId": "507f1f77bcf86cd799439011",
"createdAt": "2025-01-16T15:00:00.000Z",
"updatedAt": "2025-01-16T15:00:00.000Z",
"permissions": [
{
"userId": "507f1f77bcf86cd799439011",
"role": "owner"
}
],
"metadata": {
"characterCount": 0,
"operationCount": 0,
"activeUsers": 0
}
}Error Responses:
400 Bad Request: Invalid title401 Unauthorized: Missing or invalid token500 Internal Server Error: Server error
Example:
curl -X POST http://localhost:3001/api/documents \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"title": "My New Document"
}'Retrieve a document by ID.
Endpoint: GET /api/documents/:id
Authentication: Required (Bearer token)
URL Parameters:
id: Document ID (MongoDB ObjectId)
Success Response (200 OK):
{
"id": "507f1f77bcf86cd799439012",
"title": "My New Document",
"ownerId": "507f1f77bcf86cd799439011",
"createdAt": "2025-01-16T15:00:00.000Z",
"updatedAt": "2025-01-16T15:30:00.000Z",
"lastSnapshotAt": "2025-01-16T15:30:00.000Z",
"permissions": [
{
"userId": "507f1f77bcf86cd799439011",
"role": "owner"
},
{
"userId": "507f1f77bcf86cd799439013",
"role": "editor"
}
],
"metadata": {
"characterCount": 1250,
"operationCount": 45,
"activeUsers": 2
}
}Error Responses:
400 Bad Request: Invalid document ID format401 Unauthorized: Missing or invalid token404 Not Found: Document not found or access denied500 Internal Server Error: Server error
Example:
curl -X GET http://localhost:3001/api/documents/507f1f77bcf86cd799439012 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."List all documents accessible to the authenticated user with pagination.
Endpoint: GET /api/documents
Authentication: Required (Bearer token)
Query Parameters:
page(optional): Page number (default: 1, min: 1)limit(optional): Items per page (default: 20, min: 1, max: 100)
Success Response (200 OK):
{
"documents": [
{
"id": "507f1f77bcf86cd799439012",
"title": "My New Document",
"ownerId": "507f1f77bcf86cd799439011",
"createdAt": "2025-01-16T15:00:00.000Z",
"updatedAt": "2025-01-16T15:30:00.000Z",
"lastSnapshotAt": "2025-01-16T15:30:00.000Z",
"permissions": [
{
"userId": "507f1f77bcf86cd799439011",
"role": "owner"
}
],
"metadata": {
"characterCount": 1250,
"operationCount": 45,
"activeUsers": 2
}
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 15,
"totalPages": 1,
"hasNextPage": false,
"hasPrevPage": false
}
}Error Responses:
400 Bad Request: Invalid pagination parameters401 Unauthorized: Missing or invalid token500 Internal Server Error: Server error
Example:
curl -X GET "http://localhost:3001/api/documents?page=1&limit=20" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Update document metadata (title).
Endpoint: PATCH /api/documents/:id
Authentication: Required (Bearer token)
URL Parameters:
id: Document ID (MongoDB ObjectId)
Request Body:
{
"title": "Updated Document Title"
}Validation Rules:
title: 1-200 characters, non-empty after trimming
Success Response (200 OK):
{
"id": "507f1f77bcf86cd799439012",
"title": "Updated Document Title",
"ownerId": "507f1f77bcf86cd799439011",
"createdAt": "2025-01-16T15:00:00.000Z",
"updatedAt": "2025-01-16T16:00:00.000Z",
"lastSnapshotAt": "2025-01-16T15:30:00.000Z",
"permissions": [
{
"userId": "507f1f77bcf86cd799439011",
"role": "owner"
}
],
"metadata": {
"characterCount": 1250,
"operationCount": 45,
"activeUsers": 2
}
}Error Responses:
400 Bad Request: Invalid document ID or title401 Unauthorized: Missing or invalid token404 Not Found: Document not found500 Internal Server Error: Server error
Example:
curl -X PATCH http://localhost:3001/api/documents/507f1f77bcf86cd799439012 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Document Title"
}'Soft delete a document (marks as deleted, doesn't remove from database).
Endpoint: DELETE /api/documents/:id
Authentication: Required (Bearer token)
URL Parameters:
id: Document ID (MongoDB ObjectId)
Success Response (200 OK):
{
"message": "Document deleted successfully",
"id": "507f1f77bcf86cd799439012"
}Error Responses:
400 Bad Request: Invalid document ID401 Unauthorized: Missing or invalid token404 Not Found: Document not found500 Internal Server Error: Server error
Example:
curl -X DELETE http://localhost:3001/api/documents/507f1f77bcf86cd799439012 \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Grant permissions to another user for a document.
Endpoint: POST /api/documents/:id/share
Authentication: Required (Bearer token)
URL Parameters:
id: Document ID (MongoDB ObjectId)
Request Body:
{
"email": "collaborator@example.com",
"role": "editor"
}Validation Rules:
email: Valid email format, must exist in systemrole: One ofowner,editor,viewer
Success Response (200 OK):
{
"message": "Document shared successfully",
"documentId": "507f1f77bcf86cd799439012",
"sharedWith": {
"userId": "507f1f77bcf86cd799439013",
"email": "collaborator@example.com",
"name": "Jane Smith",
"role": "editor"
}
}Error Responses:
400 Bad Request: Invalid document ID, email, or role401 Unauthorized: Missing or invalid token404 Not Found: Document or user not found500 Internal Server Error: Server error
Example:
curl -X POST http://localhost:3001/api/documents/507f1f77bcf86cd799439012/share \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"email": "collaborator@example.com",
"role": "editor"
}'Retrieve operation log for a document with pagination and date filtering.
Endpoint: GET /api/documents/:id/history
Authentication: Required (Bearer token)
URL Parameters:
id: Document ID (MongoDB ObjectId)
Query Parameters:
page(optional): Page number (default: 1, min: 1)limit(optional): Items per page (default: 50, min: 1, max: 100)startDate(optional): Filter operations after this date (ISO 8601 format)endDate(optional): Filter operations before this date (ISO 8601 format)
Success Response (200 OK):
{
"operations": [
{
"id": "507f1f77bcf86cd799439014",
"documentId": "507f1f77bcf86cd799439012",
"userId": {
"_id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "user@example.com"
},
"timestamp": "2025-01-16T15:30:00.000Z",
"operationType": "insert",
"metadata": {
"clientId": "client-abc123",
"sessionId": "session-xyz789"
}
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 45,
"totalPages": 1,
"hasNextPage": false,
"hasPrevPage": false
},
"filters": {
"startDate": "2025-01-16T00:00:00.000Z",
"endDate": "2025-01-17T00:00:00.000Z"
}
}Error Responses:
400 Bad Request: Invalid document ID, pagination, or date parameters401 Unauthorized: Missing or invalid token500 Internal Server Error: Server error
Example:
curl -X GET "http://localhost:3001/api/documents/507f1f77bcf86cd799439012/history?page=1&limit=50&startDate=2025-01-16T00:00:00.000Z" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."Check if the server is running.
Endpoint: GET /health/live
Authentication: None required
Success Response (200 OK):
{
"status": "ok",
"timestamp": "2025-01-16T15:00:00.000Z"
}Example:
curl -X GET http://localhost:3001/health/liveCheck if the server is ready to accept traffic (MongoDB and Redis connections).
Endpoint: GET /health/ready
Authentication: None required
Success Response (200 OK):
{
"status": "ready",
"timestamp": "2025-01-16T15:00:00.000Z",
"checks": {
"mongodb": true,
"redis": true
}
}Error Response (503 Service Unavailable):
{
"status": "not ready",
"timestamp": "2025-01-16T15:00:00.000Z",
"checks": {
"mongodb": false,
"redis": true
}
}Example:
curl -X GET http://localhost:3001/health/readyPrometheus metrics endpoint.
Endpoint: GET /metrics
Authentication: None required
Success Response (200 OK):
Returns Prometheus text format metrics.
Example:
curl -X GET http://localhost:3001/metricsURL: ws://localhost:3001?token=<JWT_TOKEN>&documentId=<DOCUMENT_ID>
Query Parameters:
token: JWT access token for authenticationdocumentId: Document ID to join
Connection Flow:
- Client connects with JWT token and document ID
- Server validates token and permissions
- Server sends initial sync message (Yjs state vector)
- Client sends its state vector
- Server sends missing updates
- Connection established, real-time sync begins
Example (JavaScript):
const token = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...';
const documentId = '507f1f77bcf86cd799439012';
const ws = new WebSocket(
`ws://localhost:3001?token=${token}&documentId=${documentId}`
);
ws.onopen = () => {
console.log('Connected to document');
};
ws.onmessage = (event) => {
// Handle Yjs sync messages
const message = new Uint8Array(event.data);
// Process with Yjs
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};
ws.onclose = () => {
console.log('Disconnected from document');
};The WebSocket protocol uses Yjs binary encoding for all messages. Messages are categorized by their first byte:
Sync Step 1 - State Vector:
- Client sends its current state vector
- Server responds with missing updates
Sync Step 2 - Update:
- Server sends document updates to sync client
Update Message:
- Incremental document changes
- Broadcast to all clients in room
Awareness Update:
- Cursor position and selection
- User presence information
- Throttled to 10 updates/second
Awareness State Structure:
{
user: {
id: "507f1f77bcf86cd799439011",
name: "John Doe",
color: "#4A90E2"
},
cursor: {
line: 10,
column: 25
},
selection: {
start: { line: 10, column: 25 },
end: { line: 10, column: 35 }
}
}Recommended Setup:
import * as Y from 'yjs';
import { WebsocketProvider } from 'y-websocket';
const yjsDoc = new Y.Doc();
const provider = new WebsocketProvider(
'ws://localhost:3001',
documentId,
yjsDoc,
{
params: { token: accessToken },
}
);
// Listen to sync status
provider.on('status', (event) => {
console.log('Connection status:', event.status);
// 'connecting' | 'connected' | 'disconnected'
});
provider.on('sync', (isSynced) => {
console.log('Document synced:', isSynced);
});
// Get shared text
const yText = yjsDoc.getText('content');
// Listen to changes
yText.observe((event) => {
console.log('Text changed:', event);
});
// Make changes
yText.insert(0, 'Hello, world!');All error responses follow this format:
{
"error": "Error Type",
"message": "Human-readable error message"
}200 OK: Request succeeded201 Created: Resource created successfully400 Bad Request: Invalid request parameters or validation error401 Unauthorized: Missing or invalid authentication token403 Forbidden: Insufficient permissions404 Not Found: Resource not found409 Conflict: Resource already exists500 Internal Server Error: Server error503 Service Unavailable: Service temporarily unavailable
Validation Error (400):
{
"error": "Validation error",
"message": "Title must be between 1 and 200 characters"
}Authentication Error (401):
{
"error": "Authentication failed",
"message": "Invalid email or password"
}Permission Error (403):
{
"error": "Forbidden",
"message": "You do not have permission to edit this document"
}Not Found Error (404):
{
"error": "Not found",
"message": "Document not found or access denied"
}- General API requests: 100 requests per minute per IP
- Document creation: 10 documents per hour per user
- Authentication attempts: 5 failed attempts per 15 minutes per IP
- Operations per second: 100 ops/sec per connection
- Connections per IP: 10 concurrent connections
- Message size: Maximum 1MB per operation
Rate Limit Response (429 Too Many Requests):
{
"error": "Rate limit exceeded",
"message": "Too many requests. Please try again later.",
"retryAfter": 60
}-
Register or Login:
- Call
POST /api/auth/registerorPOST /api/auth/login - Receive
accessToken(15 min expiry) andrefreshToken(7 days expiry)
- Call
-
Make Authenticated Requests:
- Include
Authorization: Bearer <accessToken>header - Access token valid for 15 minutes
- Include
-
Token Refresh:
- When access token expires (401 response)
- Call
POST /api/auth/refreshwith refresh token - Receive new access token
-
WebSocket Connection:
- Use access token in WebSocket URL query parameter
- Connection authenticated on handshake
- Access Token: Store in memory (React state/context)
- Refresh Token: Store in httpOnly cookie (server-side) or secure storage
- Never: Store tokens in localStorage (XSS vulnerability)
A Postman collection is available for testing all API endpoints:
Import URL: docs/postman_collection.json
The collection includes:
- Pre-configured environment variables
- All authentication endpoints
- All document management endpoints
- Health check endpoints
- Example requests with sample data
- Automated token refresh scripts
For issues or questions:
- GitHub Issues: [Project Repository]
- Documentation: README.md
- API Status:
GET /health/ready