Skip to main content

Read the library

List and count your organization's assets and workspaces with the Videas API, read one asset with its tags and its custom fields, filter by type, workspace or your own reference, and walk every page with a cursor.

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"
  • limit sets how many rows a page holds; a value above the endpoint’s cap is lowered to it rather than refused.
  • order=desc reads newest first; asc, oldest first, is the default.
  • after takes only a next the same endpoint answered: the cursor is opaque, and one that was not issued there is a 400.
  • 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