Your organization’s library is made of assets — videos, sounds, pictures,
documents and other files — and each asset is in exactly one workspace. The
API reads both, with a key carrying Read the library through the API
(assets.library.read); see Get started
to create one.
Every example below sends the key from the VIDEAS_API_KEY environment variable.
List the assets
curl https://api.videas.com/v1/assets \
-H "Authorization: Bearer $VIDEAS_API_KEY"
GET /v1/assets answers every visible asset of the organization whose first
upload has begun — an asset still being sent is listed, uploading — in every
workspace, oldest first. Folders and collections are not listed. Each row
carries:
| Field | |
|---|---|
id |
The asset’s identifier — stable for its whole life, and the one to store. |
name |
Its title. Never empty. |
type |
What kind of thing it is: video, audio, image, document, archive, file, subtitles, third_party or other. |
status |
Where it is in its processing: uploading, processing, ready or error. Only a ready asset can be played. |
workspace_id |
The workspace it is in — the id of one of GET /v1/workspaces. |
description |
Its description, or null. |
external_ref |
Your identifier for it, when one was recorded, or null. Not unique. |
language |
The language of its content as a BCP 47 tag (fr, en-GB), or null. |
duration_ms |
Its running time in milliseconds for a video or a sound, or null. |
created_at |
When it was created (RFC 3339). Lists are ordered by this instant, then by id. |
updated_at |
When it last changed (RFC 3339) — but for its tags and its custom fields: changing them does not move it. |
third_party |
For an asset of type third_party, the video it plays from another provider’s site: provider (youtube, vimeo, dailymotion or other), video_id, the video’s identifier there, and player_url, the address of its player to put in an <iframe>. null for every other type. |
thumbnail_url |
The address of its thumbnail — stable, anonymous, to put as it is in an <img> —, or null when it has none. An asset’s thumbnail gives its formats and sizes. |
The lists of type, status and third_party.provider values may grow:
read a value you do not know as one your code does not handle yet, not as an
error — an unknown provider as other.
Filter
Three filters narrow the list, and combine:
| Parameter | Keeps | Example |
|---|---|---|
type |
the assets of these types | ?type=video,audio |
workspace_id |
the assets of these workspaces | ?workspace_id=0192a6b1-…,0192a6b5-… |
external_ref |
the assets whose external_ref is exactly this, the spaces around it aside |
?external_ref=course-42%2Flecture-1 |
type and workspace_id take several values as one key, separated by
commas. external_ref takes one value, since your own identifiers may
contain commas: percent-encode it like any query value.
curl "https://api.videas.com/v1/assets?type=video&workspace_id=0192a6b1-7c3e-7d40-9a51-3f0e2b6c8d10" \
-H "Authorization: Bearer $VIDEAS_API_KEY"
A parameter the endpoint does not list is refused, and so is a key given
twice: ?typ=video or ?type=video&type=audio answers a 400, never a list
quietly unfiltered. A workspace_id of no concern to your organization simply
matches nothing.
Walk every page
A page holds data — the rows — and next, the cursor of the page after it.
Send next back as after, with the same filters, until it is null:
curl "https://api.videas.com/v1/assets?type=video&after=MDE5MmE2YjItNGYxYS03Yjkw…" \
-H "Authorization: Bearer $VIDEAS_API_KEY"
limitsets how many rows a page holds; a value above the endpoint’s cap is lowered to it rather than refused.order=descreads newest first;asc, oldest first, is the default.aftertakes only anextthe same endpoint answered: the cursor is opaque, and one that was not issued there is a400.- There is no offset and no total in a page: to know how many, count.
The whole walk, from Node.js and from Python:
async function allAssets(filters = {}) {
const assets = []
let after = null
do {
const query = new URLSearchParams({ ...filters, ...(after ? { after } : {}) })
const response = await fetch(`https://api.videas.com/v1/assets?${query}`, {
headers: { Authorization: `Bearer ${process.env.VIDEAS_API_KEY}` },
})
const page = await response.json()
if (!response.ok) throw new Error(`${page.code}: ${page.message}`)
assets.push(...page.data)
after = page.next
} while (after)
return assets
}
const videos = await allAssets({ type: 'video' })
import os
import requests
def all_assets(**filters):
headers = {"Authorization": f"Bearer {os.environ['VIDEAS_API_KEY']}"}
params = dict(filters)
while True:
response = requests.get("https://api.videas.com/v1/assets", headers=headers, params=params)
response.raise_for_status()
page = response.json()
yield from page["data"]
if page["next"] is None:
return
params["after"] = page["next"]
videos = list(all_assets(type="video"))
Count
GET /v1/assets/count counts what the listing would answer, under the same
filters — and takes no other parameter:
curl "https://api.videas.com/v1/assets/count?type=video" \
-H "Authorization: Bearer $VIDEAS_API_KEY"
# → { "count": 42 }
The count is taken when asked: a walk begun afterwards may meet assets created or deleted since.
Read one asset
GET /v1/assets/{asset_id} answers every field the listing answers about an
asset, under the same names, and the ones a listing leaves out:
curl https://api.videas.com/v1/assets/0192a6b2-4f1a-7b90-8e0d-51c3a7f2b046 \
-H "Authorization: Bearer $VIDEAS_API_KEY"
{
"id": "0192a6b2-4f1a-7b90-8e0d-51c3a7f2b046",
"name": "Opening lecture",
"type": "video",
"status": "ready",
"workspace_id": "0192a6b1-7c3e-7d40-9a51-3f0e2b6c8d10",
"description": null,
"external_ref": "course-42/lecture-1",
"language": "en",
"duration_ms": 2712000,
"created_at": "2026-09-26T09:12:44Z",
"updated_at": "2026-09-26T09:31:02Z",
"third_party": null,
"thumbnail_url": "https://app.videas.com/images/assets/0192a6b2-4f1a-7b90-8e0d-51c3a7f2b046/thumbnail.jpg",
"excerpt": null,
"copyright": null,
"seo_title": null,
"seo_description": null,
"tags": [{ "id": "0192a690-2c4d-7e8f-9a0b-1c2d3e4f5a6b", "name": "onboarding" }],
"custom_fields": [
{
"field_id": "0192a680-2e3f-7a4b-9c5d-6e7f8a9b0c1d",
"slug": "format",
"label": "Format",
"type": "choice",
"value": "0192a681-5b6c-7d7e-8f8a-9b0c1d2e3f4a"
}
]
}
| Field | |
|---|---|
excerpt |
A short summary, which a listing shows under its name where the description would not fit, or null. |
copyright |
The notice a reuser of it has to carry — who holds its rights, under what terms —, or null. |
seo_title |
The title a web page publishing it gives itself, in a browser’s tab and a search engine’s results, or null: the page then takes its name. |
seo_description |
The description a page publishing it gives search engines and link previews, or null: the page then takes its excerpt, else its description. |
tags |
The tags the organization files it under, ordered by name; empty when it has none. |
custom_fields |
Its values of the organization’s custom fields, in the order a form lays them out: field_id, slug, label, type and value, in the shape its type gives it. A field it holds no value of is not listed. |
A tag keeps its id when it is renamed; a tag a machine suggested and nobody
confirmed is not listed. An id the listing would not answer — a folder, a
collection, a hidden asset, another organization’s — is a 404, exactly like an
id that names nothing.
All these fields are written with a key carrying assets.library.edit:
Edit an asset says how.
The workspaces
GET /v1/workspaces lists the organization’s workspaces — what an asset’s
workspace_id names — one page at a time, with the same limit, after and
order, and no filter. GET /v1/workspaces/count counts them.
curl https://api.videas.com/v1/workspaces \
-H "Authorization: Bearer $VIDEAS_API_KEY"
{
"data": [
{
"id": "0192a6b1-7c3e-7d40-9a51-3f0e2b6c8d10",
"name": "Training",
"created_at": "2026-09-01T08:00:00Z",
"updated_at": "2026-09-01T08:00:00Z"
}
],
"next": null
}
A workspace’s id is also where a file you add
lands.
Keep your records in step
external_ref is the field that maps an asset of ours to a record of yours. Set
it when you add a file, and store the
asset’s id beside your record once you have it: the id never changes. The
reference is what finds the asset again when you do not have its id yet — after
an upload request whose answer was lost, for instance — with ?external_ref=. It
is not unique: the same reference may match several assets, or none.
A video hosted elsewhere is also found again by its identifier at its
provider: third_party.video_id, on every row of GET /v1/assets, is what to
match your records on when they have no external_ref —
Add a video hosted elsewhere
shows the walk.
To know what changed since your last read, updated_at is enough for an asset’s
words and its thumbnail, not for its tags or its custom fields, which do not move
it: compare them.
Next steps
- Add a file with the API, from a link, or a video hosted elsewhere.
- Edit an asset — its words, its tags, its custom fields and its thumbnail.
- Errors, limits and versions.
- The API reference: every field of every answer.