Skip to main content

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_limit
  • media.quarantined (451 or 403)
  • media.transcoding (409 — not yet ready)
  • ai.refused.safety, ai.refused.budget
  • rate.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).