Skip to main content
POST
/
api
/
v1
/
assets
/
upload-url
Create Upload Url
curl --request POST \
  --url https://roughy-api-staging.fly.dev/api/v1/assets/upload-url \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "content_type": "audio/mpeg",
  "type": "audio_input"
}
'
{
  "asset": {
    "content_type": "audio/mpeg",
    "created_at": "2026-05-02T08:54:52.423000Z",
    "id": "019de7f7-3a52-74d1-9eeb-323e0bfb7bb9",
    "state": "pending_upload",
    "type": "audio_input"
  },
  "upload": {
    "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..."
  }
}

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.

Authorizations

Authorization
string
header
required

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

application/json

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).

type
enum<string>
required
Available options:
audio,
video,
rendered_video,
cut_file
content_type
string | null
Required string length: 1 - 255

Response

Successful Response

POST /assets/upload-url response: asset id + how to push bytes.

asset
AssetSummary · object
required

Public projection of an assets row (no signed URLs).

Example:
{
  "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"
}
upload
UploadTargetResponse · object
required
Example:
{
  "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..."
}