Reserve an asset row + return a signed URL the client PUTs bytes to.
Type whitelist enforced server-side: only audio and video are
accepted. cut_file and rendered_video are processor-generated
only and return 409.
Documentation Index
Fetch the complete documentation index at: https://docs.roughy.ai/llms.txt
Use this file to discover all available pages before exploring further.
Either your Supabase session JWT (UI flows) or an API key minted via POST /api-keys (programmatic flows). Pass it as Authorization: Bearer <token>. The server inspects the token format and routes to JWT or API-key verification automatically.
Body for POST /assets/upload-url.
duration_seconds is intentionally absent: ffprobe runs in the
cpu-worker after confirm_upload and writes the authoritative
value to the row. See ADR / work-plan §3.3 for the rationale on
why we don't accept a client hint anymore (single source of truth,
no client-trust gap on cost-estimation).
Successful Response
POST /assets/upload-url response: asset id + how to push bytes.
Public projection of an assets row (no signed URLs).
{
"content_type": "audio/mpeg",
"created_at": "2026-05-02T08:54:52.423000Z",
"duration_seconds": "324.412",
"id": "019de7f7-3a52-74d1-9eeb-323e0bfb7bb9",
"size_bytes": 4823572,
"state": "ready",
"type": "audio_input"
}
{
"expires_at": "2026-05-02T09:09:52.423000Z",
"headers": { "Content-Type": "audio/mpeg" },
"method": "PUT",
"url": "https://example.supabase.co/storage/v1/object/sign/assets/019de7f7-3a52-74d1-9eeb-323e0bfb7bb9?token=eyJhbGciOi..."
}