What is an asset
An asset is a piece of source media you upload — audio or video. It’s the thing every operation runs against: a cut attaches to it, and renders read from it. Every asset belongs to exactly one project; listings, uploads, and lifecycle events flow through that parent. Cuts, subtitles, and renders are their own entities — not asset types. An asset is only ever the source media.Types and states
| Type | Meaning |
|---|---|
video | Video source you uploaded. |
audio | Audio source you uploaded directly. |
| State | Meaning |
|---|---|
pending_upload | Asset row exists; bytes are still uploading. |
processing | Upload finished; Roughy is preparing the asset (analysing it and getting it ready to cut). The per-minute charge settles here, once preparation finishes. Not usable yet. |
pending_payment | Prepared, but your balance didn’t cover the charge. Bytes are kept; the asset activates automatically on your next top-up. |
ready | Prepared and paid for — cuttable and renderable. |
failed | Preparation permanently failed (e.g. unreadable or corrupt media); terminal. Nothing is charged. error_code / error_message carry the reason. |
Billing
Roughy charges once per source asset — 1 credit per source minute, rounded up (a 4 m 10 s file costs 5 credits). The charge settles after the asset is processed, so a file that can’t be processed is never charged. Everything downstream (cuts, re-cuts, renders, re-renders) is free. A positive credit balance is required to start an upload (POST /v1/assets rejects a zero-or-below balance with 402). If your
balance doesn’t cover the charge once processing finishes, the asset
lands in pending_payment (bytes retained) and activates on your next
top-up. See Credit ledger.
Fields
language is an optional hint for the spoken language of the media
(e.g. de); null auto-detects. Set once in the POST /v1/assets body
and immutable thereafter.
script is not an asset field — you supply the cut’s reference
script per POST /v1/cuts, so the
same asset can be re-cut against a different script without re-uploading.
type, content_type, and extension are derived from the uploaded
bytes once the first chunk arrives — null before then, never
user-settable.
size_bytes is filled when the upload finalises; duration_seconds is
measured while the asset is processing, so it is always present by the
time the asset is ready.
Reading
GET /v1/assets/{id} returns the asset detail; for ready assets it
includes a short-lived signed download_url and a cuttable boolean.
GET /v1/assets lists your assets newest-first — ?project_id=<id>
narrows to one project, ?state=ready filters by state.
Immutability
An asset has no editable fields:language is set once at
POST /v1/assets, and everything else is derived from the bytes. There
is no PATCH — to change the language, delete the asset and re-upload.
Deleting
DELETE /v1/assets/{id} removes the asset and everything derived from
it (cuts, subtitles, renders) via cascade — the rows disappear
immediately and the stored bytes are purged. Irreversible.
Related concepts
- Project — the container every asset belongs to.
- Cut / Render — what attaches to an asset.
- Credit ledger — the per-asset charge.