Skip to main content
GET
/
v1
/
assets
/
{asset_id}
Get an asset
curl --request GET \
  --url https://roughy-api-staging.fly.dev/v1/assets/{asset_id} \
  --header 'Authorization: Bearer <token>'
{
  "id": "019de7f7-3a52-74d1-9eeb-323e0bfb7bb9",
  "project_id": "019de7f5-7e21-7402-92a8-1c0e1fa84411",
  "type": "audio",
  "state": "ready",
  "extension": "mp3",
  "size_bytes": 4823572,
  "content_type": "audio/mpeg",
  "duration_seconds": "324.412",
  "language": "de",
  "error_code": null,
  "error_message": null,
  "created_at": "2026-05-02T08:54:52.423000Z",
  "upload_url": null,
  "download_url": "https://fly.storage.tigris.dev/assets/projects/019de7f5-7e21-7402-92a8-1c0e1fa84411/019de7f7-3a52-74d1-9eeb-323e0bfb7bb9?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&X-Amz-Signature=<sig>"
}

Authorizations

Authorization
string
header
required

Pass your API key as Authorization: Bearer sk_…. Mint a key from your dashboard's API-keys page.

Path Parameters

asset_id
string<uuid>
required

Identifier of the asset.

Response

The asset's metadata plus a fresh signed download_url.

An asset with a short-lived signed download URL.

id
string<uuid>
required

Stable unique identifier for the asset.

project_id
string<uuid>
required

Identifier of the project that owns this asset.

type
enum<string> | null
required

What kind of media this asset holds: audio or video, derived from the uploaded bytes once the first chunk is received. null before then.

Available options:
audio,
video
state
enum<string>
required

Lifecycle state: pending_upload while bytes are uploading, processing while Roughy prepares the asset (the per-minute charge settles here, once preparation finishes), pending_payment if your balance didn't cover the charge (bytes kept; auto-activates on your next top-up), ready once prepared and paid for (cuttable and renderable), and failed if preparation permanently failed (see error_code / error_message; nothing is charged on a failure).

Available options:
pending_upload,
processing,
pending_payment,
ready,
failed
extension
string | null
required

File extension without the leading dot (e.g. mp3, mp4), derived from the uploaded bytes once the first chunk is received. null before then.

size_bytes
integer | null
required

Total stored size in bytes. null while in pending_upload.

content_type
string | null
required

MIME type of the stored bytes (e.g. audio/mpeg, video/mp4), derived from the uploaded bytes once the first chunk is received. null before then.

duration_seconds
string | null
required

Duration in seconds, measured while the asset is processing. null while pending_upload or processing (before it is measured) and on a failed asset; always present once ready or pending_payment.

Pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
language
string | null
required

Optional ISO 639-1 hint for the spoken language of the media, set at create and immutable. null means auto-detect.

created_at
string<date-time>
required

When the asset row was created.

download_url
string | null
required

Short-lived signed URL for downloading the asset's bytes. Present only when the asset is ready; null in every other state (the bytes are only downloadable once ingested and paid for). The URL expires within minutes — re-fetch the asset when you need a fresh one rather than caching it.

cuttable
boolean
required

Whether a cut can be produced now. true once the asset is processed and paid for — i.e. ready. false while it is still being prepared, unpaid (pending_payment), or failed. While this is false, POST /cuts returns 409 with asset_processing, asset_payment_required, or asset_failed.

error_code
string | null

Machine-readable failure reason. Set only when state is failed; null otherwise.

error_message
string | null

Human-readable failure detail. Set only when state is failed.

upload_url
string | null

TUS transfer URL for resuming this asset's source upload. Present only while state is pending_upload; null once the upload finalises. Hand it to a TUS client (tus-js-client / tus-py-client) as the upload URL — the client issues a HEAD against it to read the authoritative Upload-Offset, then resumes. While pending_upload, this is the same transfer URL the create response carries in its Location header.