API Contracts
:::info Source
Sourced from services/media-service/API_CONTRACTS.md in the documentation repo.
:::
1. Endpoints
1.1 Upload
POST /api/v1/media/upload-url body: { sha256, sizeBytes, mime, filename, kind? }
returns: { assetId, uploadUrl, uploadFields, expiresAt }
POST /api/v1/media/{id}/finalize body: { etag } confirms upload
1.2 Asset Management
GET /api/v1/media/{id}
GET /api/v1/media ?filter[kind]=image&filter[status]=ready
DELETE /api/v1/media/{id}
GET /api/v1/media/{id}/variants
GET /api/v1/media/{id}/captions?lang=en-US
POST /api/v1/media/{id}/captions body: { language, content (vtt/srt) } (manual captions)
GET /api/v1/media/{id}/transcript?lang=en-US
1.3 AI Generation
POST /api/v1/media/ai/generate-image body: { prompt, size, style?, aspectRatio? }
POST /api/v1/media/ai/generate-audio body: { text, voice, language, format? }
POST /api/v1/media/ai/generate-caption body: { assetId, language, reviewRequired? }
1.4 Streaming
GET /api/v1/media/{id}/stream/hls/{variant}/index.m3u8 (signed URL)
GET /api/v1/media/{id}/stream/dash/{variant}.mpd
2. Request / Response
CreateUploadURL response
{
"data": {
"assetId": "mda_01H...",
"uploadUrl": "https://...s3...amazonaws.com/...",
"uploadFields": { "Content-Type": "video/mp4", "key": "..." },
"expiresAt": "..."
}
}
MediaAsset response
{
"data": {
"id": "mda_01H...",
"kind": "video",
"source": "upload",
"status": "ready",
"mime": "video/mp4",
"width": 1920, "height": 1080, "durationSeconds": 600,
"sha256": "...",
"sizeBytes": 450000000,
"variants": [ ... ],
"captions": [ { "language": "en-US", "url": "...", "approved": true } ],
"transcript": { "language": "en-US", "url": "..." }
}
}
3. Error Model
validation.mime.unsupported,validation.size.exceeds_limitmedia.quarantined(451 or 403)media.transcoding(409 — not yet ready)ai.refused.safety,ai.refused.budgetrate.limited
4. Pagination
Cursor; page[size] max 200.
5. Rate Limits
- Upload URL creation: 30/min per user.
- AI image gen: per-tenant budget.
- Caption generation: 10/min per user.
6. Security
- Uploads via signed URLs; 15-min TTL.
- Stream URLs signed per-user + per-asset.
- Per-tenant prefix enforced in signing.
- AI generation subject to prompt moderation.
7. Idempotency
- Upload idempotent on SHA-256 (dedup within tenant).
- AI generation idempotent on (prompt hash, model, tenant).
8. SLOs
- Upload URL p95 < 200ms.
- Stream URL p95 < 100ms.
- Transcode start p95 < 30s after upload.
- Caption generation p95 < 5 min (for 60-min video).