Media and files API
8 endpoints (6 media + 2 room-files).
Media#
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/media/upload |
Upload a file. Multipart. |
GET |
/v1/media/{media_id}/info |
Metadata (sha256, size, mime, dimensions). |
GET |
/v1/media/download/{media_id} |
Download bytes. |
GET |
/v1/media/download/{media_id}/thumbnail |
Pre-generated thumbnail (images/videos). |
GET |
/v1/media/signed/{media_id} |
Get a short-lived signed URL (no auth header needed). |
POST |
/v1/transcribe |
Submit an audio file for transcription. |
POST /v1/media/upload#
1 2 3 4 | |
Returns:
1 2 3 4 5 6 7 8 9 10 11 12 | |
scan_status is pending immediately, becomes clean or
infected once ClamAV has scanned. Infected files are auto-deleted;
references to them 404.
POST /v1/transcribe#
1 2 3 4 | |
Async — returns immediately with a job_id:
1 | |
Poll GET /v1/jobs/{job_id} (under
Queue and scheduled tasks)
for completion. The result includes:
1 2 3 4 5 6 7 8 | |
Room file index#
Files uploaded into a room are tracked in a per-room index so the client can show a "Files" tab.
| Method | Path | Purpose |
|---|---|---|
GET |
/v1/rooms/{room_id}/files |
List media attached in this room. |
DELETE |
/v1/rooms/{room_id}/files/{media_id} |
Remove from the index (doesn't delete the media). |
Storage#
All media goes to MinIO/S3 via the path tenant/{tenant_id}/{sha256}.
Content-addressable: uploading the same file twice (same sha256)
dedupes server-side.
Quotas#
Per-tenant max_storage_mb. Hit returns 413.
Signed URLs#
For clients that can't include auth headers (image tags, embedded
players), use /v1/media/signed/{media_id} to get a URL valid for
the next 5 minutes:
{
"data": {
"url": "https://...minio.../tenant/.../sha256?X-Amz-...",
"expires_at": "2026-05-17T14:05:00Z"
}
}