Files
linearvoid/docs/API.md
T
zwitschi 926a663c23 Add comprehensive documentation for Linear Void project
- Created README.md in docs folder outlining project structure and documentation links.
- Added SECURITY.md detailing the security model, threat model, authentication, transport security, network isolation, and incident response procedures.
- Introduced SETUP.md providing a detailed setup guide for local and production environments, including prerequisites, environment setup, and Gitea integration.
- Added STREAMING.md outlining the streaming pipeline, including production flow, source-media contract, playout and HLS packaging, cache contract, player behavior, and monitoring.
- Updated architecture documentation to include links to new SETUP.md and STREAMING.md files for better navigation.
2026-08-08 14:52:19 +02:00

7.0 KiB

API Reference

This document describes the currently implemented API surfaces in Linear Void.

Base URLs

Authentication Model

Admin REST endpoints use a cookie session.

  • Cookie name: linearvoid_admin_session
  • Cookie attributes: HttpOnly, SameSite=Strict, Secure when request is HTTPS (or X-Forwarded-Proto=https)
  • Session TTL: controlled by ADMIN_SESSION_TTL_HOURS (default 12h)

Chat WebSocket API

Connect

Endpoint:

  • GET /ws?username={name}&room={room}

Client sends JSON messages over the socket.

Message Envelope (client -> server)

{
  "room": "main",
  "username": "viewer123",
  "text": "hello world",
  "type": "public"
}

Notes:

  • type is usually public for room chat and private for DM room routing.
  • Private room names are formatted like dm:userA-userB (sorted usernames).
  • Moderation/system events are sent as type=system messages.

Message Envelope (server -> client)

{
  "room": "main",
  "username": "viewer123",
  "text": "hello world",
  "type": "public",
  "timestamp": "2026-08-04T12:34:56Z"
}

Admin Session API

Login

  • POST /api/admin/login
  • Auth: none

Request:

{
  "username": "admin",
  "password": "your-password"
}

Success response:

{
  "authenticated": true,
  "username": "admin"
}

Logout

  • POST /api/admin/logout
  • Auth: optional (clears cookie either way)

Response:

{
  "authenticated": false
}

Session Check

  • GET /api/admin/session
  • Auth: cookie required

Success response:

{
  "authenticated": true,
  "username": "admin"
}

Failure:

  • 401 unauthorized

Admin Data API

All endpoints below require admin authentication.

Overview

  • GET /api/admin/overview

Returns aggregate counters and runtime/system snapshot fields.

Playlist

  • GET /api/admin/playlist
  • PUT /api/admin/playlist

PUT request:

{
  "content": "file '/app/media/video1.mp4'\nfile '/app/media/video2.mp4'\n"
}

Schedule

  • GET /api/admin/schedule

Returns parsed playlist entries plus matched media metadata/runtime.

Moderation

  • GET /api/admin/moderation/logs?limit=50
  • POST /api/admin/moderation/actions

Action request:

{
  "action": "mute",
  "target": "username-or-id",
  "moderator": "admin",
  "reason": "spam",
  "room": "main"
}

Analytics

  • GET /api/admin/analytics

Returns totals (messages, moderation actions, rooms) and top room summary.

System

  • GET /api/admin/system

Returns service health snapshot for chat/playout/redis/database and config metadata.

Active Users

  • GET /api/admin/users

Returns currently discovered presence users (room + username) when Redis is available.

Media Library API

Media Collection

  • GET /api/admin/media
  • POST /api/admin/media (multipart upload, legacy path)

Multipart form field name: file

Media Item

  • GET /api/admin/media/{id}
  • PUT /api/admin/media/{id}
  • DELETE /api/admin/media/{id}

PUT request:

{
  "status": "ready",
  "title": "My Clip",
  "tags": "music,live"
}

Resumable Upload API

Maximum file size: 2GB

Default chunk size: 8MB

Initialize or Resume Session

  • POST /api/admin/media/uploads

Request:

{
  "uploadId": "optional-existing-id",
  "fileName": "clip.mp4",
  "fileSize": 123456789,
  "mimeType": "video/mp4",
  "chunkSize": 8388608,
  "totalChunks": 15
}

Response:

{
  "uploadId": "hex-token",
  "fileName": "clip.mp4",
  "fileSize": 123456789,
  "chunkSize": 8388608,
  "totalChunks": 15,
  "uploadedChunks": 3,
  "progress": 20
}

Check Upload Status

  • GET /api/admin/media/uploads/{uploadId}

Returns same status envelope as initialize.

Upload Chunk

  • PUT /api/admin/media/uploads/{uploadId}/chunk?index={chunkIndex}
  • Content-Type: application/octet-stream

Response returns updated upload status envelope.

Complete Upload

  • POST /api/admin/media/uploads/{uploadId}/complete

On success returns admin media listing payload (files + generatedAt).

Metrics and Health

Chat metrics

  • GET /metrics

Prometheus exposition includes connected clients, stored messages, moderation actions, Redis indicators, active admin sessions, and build info.

Health

  • GET /health on chat service
  • GET /health on playout service
  • GET /health on nginx reverse proxy

HTTP Status Conventions

Code Meaning When
200 OK Successful GET, PUT, or action
201 Created Successful POST (upload init, override created)
204 No Content Successful DELETE, CORS preflight
400 Bad Request Malformed JSON, missing required fields, invalid input
401 Unauthorized Missing or expired admin session
403 Forbidden Valid session but insufficient permissions
404 Not Found Resource doesn't exist
405 Method Not Allowed Wrong HTTP method for endpoint
409 Conflict Schedule override overlap, upload ID mismatch
413 Payload Too Large Upload exceeds 2 GB limit
422 Unprocessable File fails normalization check (codec, fps, resolution)
429 Too Many Requests Rate limit exceeded (chat messages, WS connections, login)
500 Internal Server Error Unexpected server failure
503 Service Unavailable Redis unavailable for user actions, playout health degraded

Rate Limiting

All limits are per-IP (from X-Forwarded-For or RemoteAddr) unless noted.

Resource Limit Window Response
Chat messages CHAT_RATE_LIMIT_MAX (default 10) CHAT_RATE_LIMIT_WINDOW_S (default 10s) 429 + {"type":"system","text":"Rate limit exceeded"}
WebSocket connections 5 60s 429 + "too many connections from this IP"
Admin login 5 5min 429 + "too many login attempts, try again later"

Rate limit headers on applicable responses:

  • X-RateLimit-Limit: maximum requests per window
  • Retry-After: seconds until window resets
  • 413: payload too large
  • 500: internal server error