Docs / CLI and SDK

Tools

CLI and SDK

Two thin, typed layers over the API. The SDK for code that makes videos; the chasca CLI for your terminal, scripts and CI.

Base URL https://app.trychasca.com/api

Configure

Both read the same two environment variables:

Terminal
export CHASCA_API_URL=https://app.trychasca.com/api
export CHASCA_API_KEY=chk_live_...

CHASCA_API_URL is the API address, https://app.trychasca.com/api. Keys come from the app under Settings → API keys (Plus and above).

The chasca CLI

Terminal
# list voices (no key needed)
chasca voices

# create a 30-second vertical video and wait for it
chasca generate "How does a heat pump work?" --length 0:30 --aspect 9:16 --wait

# check on a video
chasca status 0b9c6f2e-5d1a-4c3e-9a47-2f8e1c7d4b60

# edit it in plain language and wait for the new version
chasca edit 0b9c6f2e-5d1a-4c3e-9a47-2f8e1c7d4b60 "make the title scene shorter" --wait

# your latest videos
chasca list --limit 20
  • --length takes M:SS in 30-second steps up to 6:00.
  • --aspect is 16:9, 9:16 or 1:1.
  • --wait keeps the command running until the video (or the new version) is ready.
  • --json prints the raw API response, handy for piping into jq.

Working in the Chasca repository itself, run the CLI straight from source with Bun:

Terminal
# from the root of the chasca-ai repository
bun packages/cli/src/index.ts voices
bun packages/cli/src/index.ts generate "Why do we have seasons?" --length 1:00 --wait --json

The TypeScript SDK

@chasca/sdk runs anywhere fetch exists (Bun, Node 20+). Every response is validated against the same contracts the API uses, and failures throw a single ChascaError type with a stable code. Your key is kept private and never appears in error messages.

make-a-video.ts
import { ChascaClient, ChascaError } from '@chasca/sdk';

const chasca = new ChascaClient({
  apiKey: process.env.CHASCA_API_KEY!,
  baseUrl: process.env.CHASCA_API_URL ?? 'https://app.trychasca.com/api',
});

// 1. queue a video (202) and wait until it is ready
const job = await chasca.createExplainer({
  input: 'How vaccines train the immune system',
  length: '1:30',
  aspect: '16:9',
  preset: 'chalkboard',
});
const video = await chasca.waitForExplainer(job.id, {
  onUpdate: (e) => console.log(e.status, e.stage, Math.round(e.progress * 100) + '%'),
});
console.log(video.videoUrl);

// 2. edit in plain language; only the affected scenes re-render
const version = await chasca.editExplainer(video.id, 'Use a castle and guards as the analogy in scene 2');
const updated = await chasca.waitForVersion(video.id, version.id);
console.log(updated.videoUrl);

// 3. errors are typed
try {
  await chasca.getExplainer('not-a-real-id');
} catch (err) {
  if (err instanceof ChascaError) console.error(err.status, err.code, err.message);
}

You can also edit the scene graph yourself and commit it as a new version:

edit-graph.ts
// edit the scene graph directly: rename a heading, then commit it as a new version
const current = await chasca.getExplainer(video.id);
const graph = structuredClone(current.sceneGraph!);
graph.scenes[0]!.heading = 'THE SNOWBALL EFFECT';
const v3 = await chasca.editExplainerGraph(video.id, graph);
await chasca.waitForVersion(video.id, v3.id);

Methods

ChascaClient methods
Method What it does
createExplainer(params) POST /v1/explainer. Queues a video; returns the queued record.
waitForExplainer(id, options?) Polls until ready (resolves) or failed (throws). Options: intervalMs, timeoutMs, onUpdate.
getExplainer(id) GET /v1/explainer/:id with the scene graph, scenes and versions.
listExplainers({ limit }) GET /v1/explainer, newest first (limit 1–100).
editExplainer(id, instruction) POST …/edit with a plain-language instruction; returns the queued version.
editExplainerGraph(id, sceneGraph) POST …/edit with an edited scene graph; returns the queued version.
waitForVersion(id, versionId, options?) Polls until that version is ready; resolves with the updated explainer.
revertExplainer(id, versionId) POST …/revert. Makes an earlier finished version current.
duplicateExplainer(id) POST …/duplicate. Returns the copy.
deleteExplainer(id) DELETE /v1/explainer/:id.
listVoices({ language }) GET /v1/voices. Every narrator, each with a preview.
listLanguages() GET /v1/languages.

The constructor is new ChascaClient({ apiKey, baseUrl }). All methods accept an optional { signal } so you can cancel with an AbortController.