# impartire API — Reference: Asset files

Every path is under `https://impartire.com/api/v1`. The machine-readable contract is https://impartire.com/api/v1/openapi.json (OpenAPI 3.1).

#### GET /api/v1/assets/{id}/files

List an asset's current files with their technical metadata

Every current file of the asset — the ones attached to a slot, then the ones the pipeline derived (proxy, thumbnail, captions…) — in the order `Asset.files` uses, each with its version chain (`root_file_id`), who added it, its version note and `technical`: what the pipeline measured (duration, dimensions, codec, loudness), null until the measure pass has run. A derived file's `size_bytes` may be null. Returned whole: `next_cursor` is always null.

Scopes: `assets:read`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).

Response 200 — `AssetFileList`

- `data` (array of AssetFileDetail, required)
  - `id` (string (uuid), required)
  - `slot` (object or null, required) — The slot a caller's file was attached to; null for a file the pipeline derived.
    - `id` (string (uuid), required)
    - `name` (string or null, required)
  - `role` (string or null, required) — null for a file attached to a slot; for a derived file, what the pipeline made: proxy, thumbnail, captions, conformed (more may be added).
  - `media_type` (string, required)
  - `mime_type` (string or null, required)
  - `extension` (string or null, required)
  - `size_bytes` (integer or null, required)
  - `version` (integer, required)
  - `uploaded_at` (string (date-time), required)
  - `root_file_id` (string (uuid), required) — The file's version chain: the id of its first version. Every version of the file shares it; GET /assets/{id}/files/{file_id} lists the chain.
  - `version_note` (string or null, required) — Why this version was added, as its uploader wrote it; null when none was given.
  - `uploaded_by` (object or null, required) — The person who added this version ({ id: their principal id, name }). Null for a file the pipeline derived and for one added with an API key (every key of an org acts as one service principal, so the key is not recoverable from the file).
    - `id` (string (uuid), required)
    - `name` (string, required)
  - `technical` (VideoInfo or AudioInfo or ImageInfo or null, required) — What the pipeline measured, by `media_type`: VideoInfo for video, AudioInfo for audio, ImageInfo for image. Null until the measure pass has run on the file, and always null for other media types (documents, subtitles).
    - `duration_seconds` (number or null, required)
    - `width` (integer or null, required)
    - `height` (integer or null, required)
    - `codec` (string or null, required) — The video codec, as the probe names it (h264, prores, …).
    - `frame_rate` (number or null, required)
    - `audio_codec` (string or null, required) — The codec of the file's interleaved audio, if any.
    - `audio_sample_rate` (integer or null, required)
    - `integrated_loudness` (number or null, required) — Integrated loudness of the interleaved audio, LUFS (EBU R128).
    - `color_primaries` (string or null, required)
    - `color_transfer` (string or null, required)
- `next_cursor` (string or null, required) — Always null: an asset's current files are few and are returned whole.

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope — the key lacks a required scope.
- 404 (Problem) — not-found.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.

#### POST /api/v1/assets/{id}/files

Attach an uploaded file to an asset, or replace one of its files with a new version

`upload_id` is a landed upload this credential made (POST /uploads, then PUT the bytes). With `replace_file_id` (a current file of the asset) the upload becomes the next version of that file's chain; the old version is kept and stays downloadable. Without it, a slot that holds one file gets a new version of that file, and a slot that holds several (`multiple`) gets a new file beside the others. The slot is `replace_file_id`'s, else `slot_id`, else the type's one slot matching the file's media type. The slot's pipeline (proxy, captions, QC…) starts as for a browser upload; GET the asset for its `runs`. An OAuth token's person needs edit on the asset. An asset under legal hold is refused with 409 `legal-hold`.

Scopes: `assets:write`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).
- `Idempotency-Key` (header, string) — Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request body — `AttachFileRequest`: Attach an uploaded file to an asset: a new file in a slot, or a new version of one.

- `upload_id` (string (uuid), required) — A landed upload this credential created with POST /api/v1/uploads.
- `slot_id` (string (uuid)) — The file slot (GET /api/v1/asset-types). Omit to use the slot of `replace_file_id`, or else the type's one slot that matches the file's media type.
- `replace_file_id` (string (uuid)) — A current file of this asset (an id from `files`) to replace: the upload becomes the next version of that file's chain, and the old version is kept. Without it, a slot that holds one file gets a new version of that file, and a slot that holds several (`multiple`) gets a new file beside the others.
- `version_note` (string) — Why this version exists ("re-grade per client note"); shown in the file's history.

Response 201 — `AssetFile`: A current file of the asset: one attached to a slot, or one the pipeline derived from it. GET /assets/{id}/files/{file_id}/download signs a URL for its bytes.

- `id` (string (uuid), required)
- `slot` (object or null, required) — The slot a caller's file was attached to; null for a file the pipeline derived.
  - `id` (string (uuid), required)
  - `name` (string or null, required)
- `role` (string or null, required) — null for a file attached to a slot; for a derived file, what the pipeline made: proxy, thumbnail, captions, conformed (more may be added).
- `media_type` (string, required)
- `mime_type` (string or null, required)
- `extension` (string or null, required)
- `size_bytes` (integer or null, required)
- `version` (integer, required)
- `uploaded_at` (string (date-time), required)
- `root_file_id` (string (uuid), required) — The file's version chain: the id of its first version. Every version of the file shares it; GET /assets/{id}/files/{file_id} lists the chain.
- `version_note` (string or null, required) — Why this version was added, as its uploader wrote it; null when none was given.
- `uploaded_by` (object or null, required) — The person who added this version ({ id: their principal id, name }). Null for a file the pipeline derived and for one added with an API key (every key of an org acts as one service principal, so the key is not recoverable from the file).
  - `id` (string (uuid), required)
  - `name` (string, required)

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope, or insufficient-permission — an OAuth token's person may see the asset but not edit it.
- 404 (Problem) — not-found.
- 409 (Problem) — legal-hold — the asset is under legal hold; or idempotency-in-flight.
- 422 (Problem) — validation (upload_id, slot_id, replace_file_id — not a current file of this asset, a derived file, or in another slot — version_note), upload-not-landed, or idempotency-mismatch.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.
- 503 (Problem) — storage-unavailable.

#### GET /api/v1/assets/{id}/files/{file_id}

Get one file of an asset, any version, with its version chain

By any version's id — current or not. `versions` lists the whole chain, newest first; download any of them with …/download. A file replaced (POST …/files with `replace_file_id`, or in the app) or restored (…/restore) is a new version in the same chain.

Scopes: `assets:read`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).
- `file_id` (path, string (uuid), required) — A file id from the asset's `files`, or any version's id from a file's `versions`.
- `If-None-Match` (header, string) — An ETag from a previous response; 304 if unchanged.

Response 200 — `AssetFileVersions`: One file of an asset — any version — with its technical metadata and its whole version chain.

- `id` (string (uuid), required)
- `slot` (object or null, required) — The slot a caller's file was attached to; null for a file the pipeline derived.
  - `id` (string (uuid), required)
  - `name` (string or null, required)
- `role` (string or null, required) — null for a file attached to a slot; for a derived file, what the pipeline made: proxy, thumbnail, captions, conformed (more may be added).
- `media_type` (string, required)
- `mime_type` (string or null, required)
- `extension` (string or null, required)
- `size_bytes` (integer or null, required)
- `version` (integer, required)
- `uploaded_at` (string (date-time), required)
- `root_file_id` (string (uuid), required) — The file's version chain: the id of its first version. Every version of the file shares it; GET /assets/{id}/files/{file_id} lists the chain.
- `version_note` (string or null, required) — Why this version was added, as its uploader wrote it; null when none was given.
- `uploaded_by` (object or null, required) — The person who added this version ({ id: their principal id, name }). Null for a file the pipeline derived and for one added with an API key (every key of an org acts as one service principal, so the key is not recoverable from the file).
  - `id` (string (uuid), required)
  - `name` (string, required)
- `technical` (VideoInfo or AudioInfo or ImageInfo or null, required) — What the pipeline measured, by `media_type`: VideoInfo for video, AudioInfo for audio, ImageInfo for image. Null until the measure pass has run on the file, and always null for other media types (documents, subtitles).
  - `duration_seconds` (number or null, required)
  - `width` (integer or null, required)
  - `height` (integer or null, required)
  - `codec` (string or null, required) — The video codec, as the probe names it (h264, prores, …).
  - `frame_rate` (number or null, required)
  - `audio_codec` (string or null, required) — The codec of the file's interleaved audio, if any.
  - `audio_sample_rate` (integer or null, required)
  - `integrated_loudness` (number or null, required) — Integrated loudness of the interleaved audio, LUFS (EBU R128).
  - `color_primaries` (string or null, required)
  - `color_transfer` (string or null, required)
- `is_current` (boolean, required) — Whether this is the chain's current version. Any version's id can be read and downloaded.
- `versions` (array of FileVersion, required) — Every version in the file's chain, newest first (current or not). Chains are short; returned whole.
  - `id` (string (uuid), required)
  - `version` (integer, required)
  - `is_current` (boolean, required)
  - `size_bytes` (integer or null, required)
  - `uploaded_at` (string (date-time), required)
  - `uploaded_by` (object or null, required) — As on AssetFile: the person, or null for the pipeline and for an API key.
    - `id` (string (uuid), required)
    - `name` (string, required)
  - `version_note` (string or null, required)

Other responses:

- 304 — Not modified — the ETag in If-None-Match is current.
- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope — the key lacks a required scope.
- 404 (Problem) — not-found.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.

#### POST /api/v1/assets/{id}/files/{file_id}/restore

Make an earlier version of a file current again

`file_id` is an earlier version (an id from the file's `versions` whose `is_current` is false). Restoring appends: the chain gets a NEW version carrying that version's bytes, and every earlier row stays as it was. The body is optional; `version_note` defaults to "Restored v<n>". No pipeline runs (the bytes were processed when they first arrived). A derived file cannot be restored. An OAuth token's person needs edit on the asset. An asset under legal hold is refused with 409 `legal-hold`.

Scopes: `assets:write`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).
- `file_id` (path, string (uuid), required) — A file id from the asset's `files`, or any version's id from a file's `versions`.
- `Idempotency-Key` (header, string) — Makes a retry safe: the same key and request within 24 hours replays the first response. 1–255 characters.

Request body — `RestoreFileRequest`: The body is optional; an empty body restores with the default note.

- `version_note` (string) — Why the earlier version is coming back. Default: "Restored v<n>".

Response 201 — `AssetFile`: A current file of the asset: one attached to a slot, or one the pipeline derived from it. GET /assets/{id}/files/{file_id}/download signs a URL for its bytes.

- `id` (string (uuid), required)
- `slot` (object or null, required) — The slot a caller's file was attached to; null for a file the pipeline derived.
  - `id` (string (uuid), required)
  - `name` (string or null, required)
- `role` (string or null, required) — null for a file attached to a slot; for a derived file, what the pipeline made: proxy, thumbnail, captions, conformed (more may be added).
- `media_type` (string, required)
- `mime_type` (string or null, required)
- `extension` (string or null, required)
- `size_bytes` (integer or null, required)
- `version` (integer, required)
- `uploaded_at` (string (date-time), required)
- `root_file_id` (string (uuid), required) — The file's version chain: the id of its first version. Every version of the file shares it; GET /assets/{id}/files/{file_id} lists the chain.
- `version_note` (string or null, required) — Why this version was added, as its uploader wrote it; null when none was given.
- `uploaded_by` (object or null, required) — The person who added this version ({ id: their principal id, name }). Null for a file the pipeline derived and for one added with an API key (every key of an org acts as one service principal, so the key is not recoverable from the file).
  - `id` (string (uuid), required)
  - `name` (string, required)

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope, or insufficient-permission — an OAuth token's person may see the asset but not edit it.
- 404 (Problem) — not-found.
- 409 (Problem) — legal-hold — the asset is under legal hold; or idempotency-in-flight.
- 422 (Problem) — already-current — that version is the chain's current one; validation (a derived file, version_note); or idempotency-mismatch.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.

#### GET /api/v1/assets/{id}/files/{file_id}/download

Get a short-lived URL for one of an asset's files, any version

A presigned GET for a file of the asset — slotted or derived, the current version or any earlier one (an id from `versions`) — valid for 5 minutes. A download is an export: an OAuth token's person needs export on the asset (else 404). A JSON body, not a redirect; fetch `url` directly (no Authorization header). A file with no bytes in storage yet is a 404.

Scopes: `assets:read`

Parameters:

- `id` (path, string (uuid), required) — The asset's id: its current version's id or its root id (an older version's id is not found).
- `file_id` (path, string (uuid), required) — A file id from the asset's `files`, or any version's id from a file's `versions`.

Response 200 — `DownloadUrl`: A short-lived URL for one file's bytes.

- `url` (string, required) — A presigned GET for the file's bytes. Do not store it: it stops working at expires_at.
- `expires_at` (string (date-time), required) — When url stops working (5 minutes after issue). Ask again for a fresh one.
- `filename` (string, required) — The stored object's file name.
- `content_type` (string or null, required)
- `size_bytes` (integer or null, required)

Other responses:

- 401 (Problem) — unauthenticated — no key, or an unknown, revoked or expired one.
- 403 (Problem) — insufficient-scope — the key lacks a required scope.
- 404 (Problem) — not-found.
- 429 (Problem) — rate-limited — the key's request budget is spent; wait Retry-After seconds.
- 500 (Problem) — internal.
- 503 (Problem) — storage-unavailable.
