The library — everything your services have produced and you have uploaded. Reads and uploads on assets; renaming, moving, deleting and folders on assets:write.
When and why to call these: the assets guide.
List assets
Section titled “List assets”GET /v1/assets
Everything your organisation’s services have produced, newest first unless sort and order say otherwise. Paginated by cursor: pass the next_cursor from one response as cursor on the next, with the same sort, and stop when it comes back null.
curl "https://api.lumavox.ai/v1/assets" \ -H "Authorization: Bearer $API_KEY"Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | How many to answer, 1 to 200. 1–200. Default 50. | |
cursor | string | The next_cursor of the page before. At least 1 characters. | |
kind | "input", "output" | ||
media_type | "audio", "image", "video", "data" | ||
capability | "tts", "image", "video", "stt", "skybox" | Which capability produced it | |
request_id | string | req_… — one call’s output | |
search | string | Match anywhere in the name, whatever the case At most 120 characters. | |
sort | "created_at", "name", "size_bytes", "duration_seconds" | Default "created_at". | |
order | "asc", "desc" | Default "desc". |
Responses
| Status | Description |
|---|---|
200 |
application/json — One page of the library, newest first |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
data |
array of AssetSummary | |
data[].id |
string | ast_… |
data[].name |
string | |
data[].kind |
"input", "output" |
input if you uploaded it, output if a service made it |
data[].media_type |
"audio", "image", "video", "data" |
What to do with the bytes — coarser than content_type, and what the library filters on. data is a lip-sync control track |
data[].content_type |
string | The MIME type |
data[].size_bytes |
integer | Size of the stored object |
data[].duration_seconds |
number or null | How long the audio or video runs; null for a still |
data[].width |
integer or null | |
data[].height |
integer or null | |
data[].peaks |
array of integer or null | Waveform magnitudes, 0-100, for a mirrored strip. Empty means silent or unreadable; null means never computed. |
data[].folder_id |
string or null | fld_…, or null at the library root |
data[].capability |
"tts", "image", "video", "stt", "skybox" or null |
Which capability produced it. Null for an upload |
data[].origin |
"api", "console", "end_user", "platform" or null |
Which door it came through. Null for older rows |
data[].thumbnail_url |
string or null | A short-lived link to a 512px square preview, for visual media only. Null for audio, for anything not yet converted, and for anything stored before previews existed. |
data[].status |
"pending", "ready", "failed" |
pending while an upload converts, then ready or failed. Everything a service produces is ready immediately. |
data[].error |
string or null | Why an upload could not be converted. Null otherwise. |
data[].created_at |
string (date-time) | |
next_cursor |
string or null | Pass as cursor for the next page; null when this is the last. |
Ask where to upload a file
Section titled “Ask where to upload a file”POST /v1/assets/upload-url
Returns a short-lived URL to PUT the file to, with the Content-Type you name, and the asset_id to confirm it with afterwards. The bytes never pass through this API.
Nothing is created by this call. Confirm with POST /v1/assets/uploaded once the PUT succeeds.
An image may weigh up to the platform’s limits.uploads.image_bytes, a recording its limits.uploads.audio_bytes (GET /v1/platform/limits); the confirm refuses a larger file.
curl -X POST "https://api.lumavox.ai/v1/assets/upload-url" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"content_type":"image/png"}'Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
content_type | string | Required | What you are about to upload. Signed into the URL, so the upload must send exactly this Content-Type, and checked against the stored object when you confirm. |
Responses
| Status | Description |
|---|---|
200 |
application/json — Where to PUT the bytes, and until when |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
402 |
Out of credits, or the organisation is suspended — nothing was charged |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
409 |
The library holds the platform’s limits.org.asset_uploads uploaded files |
422 |
The request failed validation |
429 |
Rate limit exceeded |
503 |
Object storage is unavailable |
200 response body
| Field | Type | Description |
|---|---|---|
asset_id |
string | Pass this back to confirm the upload. |
url |
string | PUT the file here, unmodified, with the Content-Type you asked for and no authentication headers — the URL carries its own. It expires; ask for another if it does. |
expires_at |
string (date-time) | When url stops accepting the upload. |
Confirm an uploaded file
Section titled “Confirm an uploaded file”POST /v1/assets/uploaded
Call this once the PUT from upload-url has succeeded. The stored object’s size and type are checked, the asset row is created and the conversion is queued. The asset comes back pending; poll GET /v1/assets/{id} until it is ready, or failed with the reason in error.
curl -X POST "https://api.lumavox.ai/v1/assets/uploaded" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"asset_id":"ast_a1B2c3D4e5F6g7H8","content_type":"image/png"}'Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
asset_id | string | Required | From the ticket. |
content_type | string | Required | What was uploaded. |
filename | string | The file’s own name; the asset is called this, less its extension, when name is not given. | |
name | string | What to call the asset. | |
folder_id | string or null | fld_… — the folder to file it in; omit it, or null, for the root. A folder that is not yours is a 404. |
Responses
| Status | Description |
|---|---|
202 |
application/json — Accepted. The asset is pending until it converts |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
402 |
Out of credits, or the organisation is suspended — nothing was charged |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
409 |
The upload has not arrived — the PUT has not landed — or it was confirmed already |
422 |
The request failed validation |
429 |
Rate limit exceeded |
503 |
Object storage is unavailable |
202 response body
| Field | Type | Description |
|---|---|---|
id |
string | ast_… |
name |
string | |
kind |
"input", "output" |
input if you uploaded it, output if a service made it |
media_type |
"audio", "image", "video", "data" |
What to do with the bytes — coarser than content_type, and what the library filters on. data is a lip-sync control track |
content_type |
string | The MIME type |
size_bytes |
integer | Size of the stored object |
duration_seconds |
number or null | How long the audio or video runs; null for a still |
width |
integer or null | |
height |
integer or null | |
peaks |
array of integer or null | Waveform magnitudes, 0-100, for a mirrored strip. Empty means silent or unreadable; null means never computed. |
folder_id |
string or null | fld_…, or null at the library root |
capability |
"tts", "image", "video", "stt", "skybox" or null |
Which capability produced it. Null for an upload |
origin |
"api", "console", "end_user", "platform" or null |
Which door it came through. Null for older rows |
thumbnail_url |
string or null | A short-lived link to a 512px square preview, for visual media only. Null for audio, for anything not yet converted, and for anything stored before previews existed. |
status |
"pending", "ready", "failed" |
pending while an upload converts, then ready or failed. Everything a service produces is ready immediately. |
error |
string or null | Why an upload could not be converted. Null otherwise. |
created_at |
string (date-time) | |
request_id |
string or null | req_… — the call that produced this |
end_user_id |
string or null | |
meta |
map of any or null | |
url |
string or null | Time-limited link to the bytes. Null when object storage is unavailable. |
url_expires_at |
string (date-time) or null | When url, the variants’ links and preview_url stop working; null when there is no url. Fetch the asset again for fresh ones. |
preview_url |
string or null | A displayable copy, when url is not displayable. Set for skyboxes, whose url is a Radiance .hdr; null otherwise. |
variants |
array of VariantInfo | Smaller copies of the same image, largest first. Empty for audio and for anything that has none. |
variants[].name |
string | 50, 25 or 12.5 — the percentage of the original |
variants[].width |
integer | |
variants[].height |
integer | |
variants[].size_bytes |
integer | |
variants[].url |
string or null | Time-limited link to this copy, good until the asset’s url_expires_at. |
Delete several assets
Section titled “Delete several assets”POST /v1/assets/delete
Needs assets:write. Soft-deletes a selection and reports how many rows it changed; ids that are not yours, or already deleted, are skipped.
curl -X POST "https://api.lumavox.ai/v1/assets/delete" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"asset_ids":[]}'Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
asset_ids | array of string | Required | 1–500 items. |
Responses
| Status | Description |
|---|---|
200 |
application/json — How many assets were removed |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
affected |
integer |
Move several assets
Section titled “Move several assets”POST /v1/assets/move
Needs assets:write. Into one folder, or to the root with folder_id: null; ids that are not yours are skipped.
curl -X POST "https://api.lumavox.ai/v1/assets/move" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"asset_ids":[],"folder_id":"..."}'Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
asset_ids | array of string | Required | 1–500 items. |
folder_id | string or null | Required | fld_…, or null for the root |
Responses
| Status | Description |
|---|---|
200 |
application/json — How many assets moved |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
affected |
integer |
Get one asset
Section titled “Get one asset”GET /v1/assets/{asset_id}
Includes a time-limited url for the bytes.
curl "https://api.lumavox.ai/v1/assets/$ASSET_ID" \ -H "Authorization: Bearer $API_KEY"Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
asset_id | string | Required |
Responses
| Status | Description |
|---|---|
200 |
application/json — The asset, with signed links to its content and variants |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
id |
string | ast_… |
name |
string | |
kind |
"input", "output" |
input if you uploaded it, output if a service made it |
media_type |
"audio", "image", "video", "data" |
What to do with the bytes — coarser than content_type, and what the library filters on. data is a lip-sync control track |
content_type |
string | The MIME type |
size_bytes |
integer | Size of the stored object |
duration_seconds |
number or null | How long the audio or video runs; null for a still |
width |
integer or null | |
height |
integer or null | |
peaks |
array of integer or null | Waveform magnitudes, 0-100, for a mirrored strip. Empty means silent or unreadable; null means never computed. |
folder_id |
string or null | fld_…, or null at the library root |
capability |
"tts", "image", "video", "stt", "skybox" or null |
Which capability produced it. Null for an upload |
origin |
"api", "console", "end_user", "platform" or null |
Which door it came through. Null for older rows |
thumbnail_url |
string or null | A short-lived link to a 512px square preview, for visual media only. Null for audio, for anything not yet converted, and for anything stored before previews existed. |
status |
"pending", "ready", "failed" |
pending while an upload converts, then ready or failed. Everything a service produces is ready immediately. |
error |
string or null | Why an upload could not be converted. Null otherwise. |
created_at |
string (date-time) | |
request_id |
string or null | req_… — the call that produced this |
end_user_id |
string or null | |
meta |
map of any or null | |
url |
string or null | Time-limited link to the bytes. Null when object storage is unavailable. |
url_expires_at |
string (date-time) or null | When url, the variants’ links and preview_url stop working; null when there is no url. Fetch the asset again for fresh ones. |
preview_url |
string or null | A displayable copy, when url is not displayable. Set for skyboxes, whose url is a Radiance .hdr; null otherwise. |
variants |
array of VariantInfo | Smaller copies of the same image, largest first. Empty for audio and for anything that has none. |
variants[].name |
string | 50, 25 or 12.5 — the percentage of the original |
variants[].width |
integer | |
variants[].height |
integer | |
variants[].size_bytes |
integer | |
variants[].url |
string or null | Time-limited link to this copy, good until the asset’s url_expires_at. |
Rename or move an asset
Section titled “Rename or move an asset”PATCH /v1/assets/{asset_id}
Needs assets:write. folder_id is tri-state: omitted leaves it alone, null moves the asset to the root, and an id moves it there.
curl -X PATCH "https://api.lumavox.ai/v1/assets/$ASSET_ID" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{}'Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
asset_id | string | Required |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | 1–200 characters. | |
folder_id | string or null | fld_…, or null for the root; omit it to leave it |
Responses
| Status | Description |
|---|---|
200 |
application/json — The asset as it now stands |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
id |
string | ast_… |
name |
string | |
kind |
"input", "output" |
input if you uploaded it, output if a service made it |
media_type |
"audio", "image", "video", "data" |
What to do with the bytes — coarser than content_type, and what the library filters on. data is a lip-sync control track |
content_type |
string | The MIME type |
size_bytes |
integer | Size of the stored object |
duration_seconds |
number or null | How long the audio or video runs; null for a still |
width |
integer or null | |
height |
integer or null | |
peaks |
array of integer or null | Waveform magnitudes, 0-100, for a mirrored strip. Empty means silent or unreadable; null means never computed. |
folder_id |
string or null | fld_…, or null at the library root |
capability |
"tts", "image", "video", "stt", "skybox" or null |
Which capability produced it. Null for an upload |
origin |
"api", "console", "end_user", "platform" or null |
Which door it came through. Null for older rows |
thumbnail_url |
string or null | A short-lived link to a 512px square preview, for visual media only. Null for audio, for anything not yet converted, and for anything stored before previews existed. |
status |
"pending", "ready", "failed" |
pending while an upload converts, then ready or failed. Everything a service produces is ready immediately. |
error |
string or null | Why an upload could not be converted. Null otherwise. |
created_at |
string (date-time) | |
request_id |
string or null | req_… — the call that produced this |
end_user_id |
string or null | |
meta |
map of any or null | |
url |
string or null | Time-limited link to the bytes. Null when object storage is unavailable. |
url_expires_at |
string (date-time) or null | When url, the variants’ links and preview_url stop working; null when there is no url. Fetch the asset again for fresh ones. |
preview_url |
string or null | A displayable copy, when url is not displayable. Set for skyboxes, whose url is a Radiance .hdr; null otherwise. |
variants |
array of VariantInfo | Smaller copies of the same image, largest first. Empty for audio and for anything that has none. |
variants[].name |
string | 50, 25 or 12.5 — the percentage of the original |
variants[].width |
integer | |
variants[].height |
integer | |
variants[].size_bytes |
integer | |
variants[].url |
string or null | Time-limited link to this copy, good until the asset’s url_expires_at. |
Delete an asset
Section titled “Delete an asset”DELETE /v1/assets/{asset_id}
Needs assets:write. Removes the asset from the library, and its bytes — every variant, the thumbnail — from storage shortly after.
curl -X DELETE "https://api.lumavox.ai/v1/assets/$ASSET_ID" \ -H "Authorization: Bearer $API_KEY"Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
asset_id | string | Required |
Responses
| Status | Description |
|---|---|
204 |
Deleted |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
List folders at one level
Section titled “List folders at one level”GET /v1/asset-folders
One level of the tree — the top level unless parent_id names a folder — alphabetically, with what each holds. A level holds at most 500 folders, so it is always one page: next_cursor is null.
curl "https://api.lumavox.ai/v1/asset-folders" \ -H "Authorization: Bearer $API_KEY"Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
parent_id | string | fld_…; omit it for the top level |
Responses
| Status | Description |
|---|---|
200 |
application/json — The folders at that level |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
data |
array of FolderSummary | |
data[].id |
string | fld_… |
data[].name |
string | |
data[].parent_id |
string or null | |
data[].created_at |
string (date-time) | |
data[].asset_count |
integer or null | Live assets directly in this folder |
data[].folder_count |
integer or null | Subfolders directly in this folder |
next_cursor |
string or null | Pass as cursor for the next page; null when this is the last. |
Create a folder
Section titled “Create a folder”POST /v1/asset-folders
Needs assets:write. At the top level, or under parent_id. Two siblings cannot share a name (409).
curl -X POST "https://api.lumavox.ai/v1/asset-folders" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"..."}'Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Required | 1–120 characters. |
parent_id | string or null | fld_…; omit it, or null, for the top level |
Responses
| Status | Description |
|---|---|
201 |
application/json — The new folder |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
409 |
A folder beside it already has that name |
422 |
The request failed validation |
429 |
Rate limit exceeded |
201 response body
| Field | Type | Description |
|---|---|---|
id |
string | fld_… |
name |
string | |
parent_id |
string or null | |
created_at |
string (date-time) | |
asset_count |
integer or null | Live assets directly in this folder |
folder_count |
integer or null | Subfolders directly in this folder |
Get one folder and its trail
Section titled “Get one folder and its trail”GET /v1/asset-folders/{folder_id}
curl "https://api.lumavox.ai/v1/asset-folders/$FOLDER_ID" \ -H "Authorization: Bearer $API_KEY"Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
folder_id | string | Required |
Responses
| Status | Description |
|---|---|
200 |
application/json — The folder and its ancestors |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
id |
string | fld_… |
name |
string | |
parent_id |
string or null | |
created_at |
string (date-time) | |
asset_count |
integer or null | Live assets directly in this folder |
folder_count |
integer or null | Subfolders directly in this folder |
ancestors |
array of FolderSummary | The folders above it, top level first |
ancestors[].id |
string | fld_… |
ancestors[].name |
string | |
ancestors[].parent_id |
string or null | |
ancestors[].created_at |
string (date-time) | |
ancestors[].asset_count |
integer or null | Live assets directly in this folder |
ancestors[].folder_count |
integer or null | Subfolders directly in this folder |
Rename or move a folder
Section titled “Rename or move a folder”PATCH /v1/asset-folders/{folder_id}
Needs assets:write. parent_id is tri-state: omitted leaves it, null moves it to the top level.
curl -X PATCH "https://api.lumavox.ai/v1/asset-folders/$FOLDER_ID" \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{}'Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
folder_id | string | Required |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | 1–120 characters. | |
parent_id | string or null | fld_…, or null for the top level; omit it to leave it |
Responses
| Status | Description |
|---|---|
200 |
application/json — The folder as it now stands |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
id |
string | fld_… |
name |
string | |
parent_id |
string or null | |
created_at |
string (date-time) | |
asset_count |
integer or null | Live assets directly in this folder |
folder_count |
integer or null | Subfolders directly in this folder |
Delete a folder
Section titled “Delete a folder”DELETE /v1/asset-folders/{folder_id}
Needs assets:write. Its contents move up to the parent; nothing is deleted but the folder itself.
curl -X DELETE "https://api.lumavox.ai/v1/asset-folders/$FOLDER_ID" \ -H "Authorization: Bearer $API_KEY"Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
folder_id | string | Required |
Responses
| Status | Description |
|---|---|
200 |
application/json — What moved up to the parent; the folder itself is gone |
400 |
The request could not be read: malformed JSON |
401 |
Missing or invalid credentials |
403 |
The key is valid but its scopes do not cover this capability — a key limited to tts gets this from /v1/images rather than a 401 |
404 |
No such asset or folder |
422 |
The request failed validation |
429 |
Rate limit exceeded |
200 response body
| Field | Type | Description |
|---|---|---|
moved_assets |
integer | Assets that moved up to the parent rather than being deleted |
moved_folders |
integer | Subfolders that moved up to the parent |