videas-sdk is the official Python client for the Videas External API. It
wraps every endpoint in a small, resource-grouped client so you don’t have to
build URLs, set headers or parse responses by hand. It uses only the Python
standard library — no third-party dependency — and works on Python 3.9+.
Installation
pip install videas-sdk
# or: uv add videas-sdk
Quick start
Create a client with your organization’s API key, then call any resource:
from videas_sdk import VideasClient
client = VideasClient(api_key="sk_your_key_here")
# List the "ready" videos in your organization
page = client.videos.list(status="ready", limit=50)
print(page["count"], "videos")
for video in page["results"]:
print(video["uid"], video["name"])
You create an API key from Settings → API keys — see Creating an API key. The key both identifies the organization the client acts on and defines the scopes it may use.
Authentication
The key you pass to VideasClient is sent as a Bearer token on every
request. Each client is bound to one key, so you can create several clients
with different keys in the same process.
Client options: timeouts & retries
Besides api_key, VideasClient also accepts:
timeout— per-request timeout in seconds (None, the default, means no timeout). Applies to every request, including the upload transfer.retries— retry idempotent (GET/HEAD) requests this many extra times on connection errors or429/503, with a short back-off. Mutating calls (create/update/delete/upload) are never retried.
client = VideasClient(
api_key="sk_your_key_here",
timeout=10, # seconds
retries=2,
)
Working with videos
Every method returns the parsed JSON body (a dict), or raises on error.
# Get one video
video = client.videos.get("vid_123")
# Update editorial fields (partial — pass only what changes)
client.videos.update("vid_123", name="Onboarding — v2", tags=["onboarding"])
# Delete (moves it to the trash)
client.videos.delete("vid_123")
# Player metadata + a signed playback token
player = client.videos.get_player("vid_123")
videos.list() accepts the same filters as the REST endpoint: search,
status, tag, created_after, created_before, ordering, plus limit
(1–100) and offset.
Other resources
# Assets — every media type (video, audio, image, document)
client.assets.list(limit=20)
client.assets.get("ast_123")
# Folders inside a workspace
client.folders.list("ws_123")
client.folders.create("ws_123", name="Courses")
client.folders.update("ws_123", "fld_1", name="Archived courses")
client.folders.delete("ws_123", "fld_1")
# Workspaces and their embed-domain settings
client.workspaces.list()
client.workspaces.get_embed_settings("ws_123")
client.workspaces.add_embed_domain("ws_123", domain="example.com")
URL fields are absolute. Response fields like
thumbnail_urlcome back as fully-qualified URLs, resolved against the Videas API base URL — use them directly, no host to prefix.
Resolving playback URLs
Playback is a two-step flow: get a signed token from the player endpoint, then
exchange it for the actual stream URLs. The resolve_playback helper does both
in one call:
info = client.videos.resolve_playback("vid_123")
print(info["hls_url"]) # signed, time-limited HLS URL
assets.resolve_playback(uid) does the same for any asset type. Prefer these
helpers; if you need the token itself, run the two steps by hand:
player = client.videos.get_player("vid_123")
info = client.playback.resolve(
asset_id="vid_123",
playback_token=player["playback_token"],
)
Uploading a file
upload.upload_file() handles the whole resumable (TUS) flow: it creates the
session and transfers the bytes, then returns the created asset metadata
(including asset_uid, available immediately).
with open("intro.mp4", "rb") as fh:
data = fh.read()
created = client.upload.upload_file(
workspace_uid="ws_123",
filename="intro.mp4",
data=data,
content_type="video/mp4",
asset_name="Onboarding intro", # optional
parent_folder_uid="fld_1", # optional — defaults to the workspace root
)
print("New asset:", created["asset_uid"])
Large files & progress
The byte transfer is chunked automatically — 32 MiB per request by default, safely under the server’s 50 MiB per-chunk limit — so multi-gigabyte videos upload with no extra work. Tune the chunk size and follow progress:
client.upload.upload_file(
workspace_uid="ws_123",
filename="lecture.mp4",
data=data,
chunk_size=16 * 1024 * 1024, # optional — default 32 MiB, must stay <= 50 MiB
on_progress=lambda sent, total: print(f"{round(sent / total * 100)}%"),
)
Need to drive the transfer yourself? upload.create_session(headers=...)
exposes the low-level session-creation call.
Error handling
Any non-2xx response raises VideasAPIError, which carries the HTTP status,
the machine-readable code and the parsed error body:
from videas_sdk import VideasAPIError
try:
client.videos.get("does-not-exist")
except VideasAPIError as err:
print(err.status) # 404
print(err.code) # "NOT_FOUND"
print(err) # human-readable message
See the REST API guide for the full list of status codes.
Current limitations
- No cross-call resume yet.
upload.upload_file()uploads in chunks, but an interrupted call restarts from the first chunk — resuming a partially-uploaded session isn’t exposed yet. For custom resume logic, drive the transfer with a TUS client againstupload.create_session()— see Upload with the REST API.
Next steps
- JavaScript / TypeScript SDK
- Creating an API key
- Using the REST API
- Try any endpoint live with Try it out in the API reference.