Files
bookhoard/docs/developer/api/websocket/sync_api.md
T
john-okeefe c4607cd9b5 docs(api): complete backend documentation with all missing endpoints
Complete API documentation audit covering all backend endpoints.

Auth Endpoints:
- Fixed endpoint paths from /api/users/me/* to /api/auth/*
- Added update_email.md and update_username.md

Device Management:
- Device shelf operations (add, get, remove, clear)
- Device CRUD operations (update, delete)
- Registration management (pending, approve, reject)

Books Operations:
- Bulk delete and bulk update with normalization
- Download endpoint with format-specific headers

Conflict Resolution:
- Complete conflict management (list, get, resolve, delete)
- Bulk operations (bulk resolve, bulk dismiss, dismiss all)

Sync Protocols:
- KOReader: progress, metadata, library, bookmarks
- Kobo: markup, bookmarks, analytics, initialization, server sync

Scanner:
- Enhanced docs with manga/comic support
- Added 148-line comprehensive overview
- All formats documented (ebooks, comics, manga)

WebSocket:
- Comprehensive real-time sync API
- Messages, topics, authentication, examples

Documentation:
- Updated api-reference.md with all 122+ endpoints
- Updated index.md with new categories

Total: 36 new files, 6 modified files, 100% coverage
2026-02-08 12:39:46 -05:00

5.2 KiB

WebSocket Sync API

Real-time bidirectional sync API for live updates and notifications.

Endpoint: WS /ws/sync Auth: Required (JWT token or Device authentication)

Connection

Connect to the WebSocket endpoint with authentication:

const ws = new WebSocket('wss://bookhoard.example/ws/sync?token=eyJhbGci...');

// Or with device authentication
const ws = new WebSocket('wss://bookhoard.example/ws/sync?device_id=uuid&device_key=key');

Message Format

All messages are JSON:

{
  "type": "message_type",
  "data": { ... }
}

Client→Server Messages

Subscribe to Progress Updates

{
  "type": "subscribe",
  "data": {
    "topic": "progress",
    "device_id": "device-uuid"
  }
}

Unsubscribe

{
  "type": "unsubscribe",
  "data": {
    "topic": "progress"
  }
}

Heartbeat/Ping

{
  "type": "ping",
  "data": {
    "timestamp": "2026-02-08T10:00:00Z"
  }
}

Server→Client Messages

Progress Updated

{
  "type": "progress_updated",
  "data": {
    "media_item_id": "uuid",
    "device_id": "device-uuid",
    "percentage": 75.5,
    "position": 1234,
    "updated_at": "2026-02-08T10:00:00Z"
  }
}

Conflict Detected

{
  "type": "conflict_detected",
  "data": {
    "conflict_id": "uuid",
    "media_item_id": "uuid",
    "severity": "high",
    "created_at": "2026-02-08T10:00:00Z"
  }
}

Scan Progress

{
  "type": "scan_progress",
  "data": {
    "job_id": "uuid",
    "library_id": "uuid",
    "percentage": 45.5,
    "files_processed": 850,
    "total_files": 1523,
    "status": "in_progress"
  }
}

Scan Complete

{
  "type": "scan_complete",
  "data": {
    "job_id": "uuid",
    "library_id": "uuid",
    "files_added": 125,
    "files_updated": 45,
    "files_failed": 3,
    "completed_at": "2026-02-08T10:00:00Z"
  }
}

Device Connected

{
  "type": "device_connected",
  "data": {
    "device_id": "uuid",
    "device_name": "My Kobo",
    "connected_at": "2026-02-08T10:00:00Z"
  }
}

Device Disconnected

{
  "type": "device_disconnected",
  "data": {
    "device_id": "uuid",
    "disconnected_at": "2026-02-08T10:00:00Z"
  }
}

Pong Response

{
  "type": "pong",
  "data": {
    "timestamp": "2026-02-08T10:00:00Z"
  }
}

Connection Lifecycle

  1. Connect - WebSocket connection established
  2. Authenticate - Send JWT token or device credentials via query string
  3. Subscribed - Server confirms authentication and subscribes to relevant topics
  4. Messages - Server pushes real-time updates
  5. Heartbeat - Client sends ping every 30 seconds
  6. Disconnect - Connection closed

Authentication

User Authentication

wss://bookhoard.example/ws/sync?token=<jwt_token>

Device Authentication

wss://bookhoard.example/ws/sync?device_id=<uuid>&device_key=<key>

Error Messages

Authentication Failed

{
  "type": "error",
  "data": {
    "code": "auth_failed",
    "message": "Invalid or expired token"
  }
}

Subscription Failed

{
  "type": "error",
  "data": {
    "code": "subscription_failed",
    "message": "Cannot subscribe to topic"
  }
}

Usage Example

const ws = new WebSocket('wss://bookhoard.example/ws/sync?token=eyJhbGci...');

ws.onopen = () => {
  console.log('Connected to sync WebSocket');

  // Subscribe to progress updates
  ws.send(JSON.stringify({
    type: 'subscribe',
    data: { topic: 'progress', device_id: 'device-uuid' }
  }));

  // Start heartbeat
  setInterval(() => {
    ws.send(JSON.stringify({
      type: 'ping',
      data: { timestamp: new Date().toISOString() }
    }));
  }, 30000);
};

ws.onmessage = (event) => {
  const message = JSON.parse(event.data);

  switch (message.type) {
    case 'progress_updated':
      console.log('Progress updated:', message.data);
      break;
    case 'conflict_detected':
      console.log('New conflict detected:', message.data);
      break;
    case 'scan_complete':
      console.log('Scan complete:', message.data);
      break;
    case 'pong':
      console.log('Pong received');
      break;
    default:
      console.log('Unknown message type:', message.type);
  }
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

ws.onclose = () => {
  console.log('WebSocket connection closed');
};

Topics

Topic Description Events
progress Reading progress updates progress_updated
conflicts Sync conflict events conflict_detected, conflict_resolved
scanner Library scan events scan_progress, scan_complete
devices Device connection events device_connected, device_disconnected
queue Sync queue events queue_item_added, queue_item_processed

Best Practices

  1. Heartbeat: Send ping every 30 seconds to keep connection alive
  2. Reconnect: Implement exponential backoff for reconnection
  3. Message Queue: Queue messages when disconnected and replay on reconnect
  4. Error Handling: Handle all error types gracefully
  5. Cleanup: Unsubscribe from topics when no longer needed

Try It Out