Quickstart
You send live video to a room, a GPU edits each frame with your prompt, and the edited video comes back into the same room. Video goes through LiveKit, so any LiveKit SDK works: web, iOS, Android, Flutter, React Native, Unity.
Get an API key in your dashboard. Keep it on your server: your server asks for a session, your app joins with the token it gets back.
1.Create a session (on your server)
curl -X POST https://babaganoush-production.up.railway.app/v1/sessions \
-H "Authorization: Bearer $VIDEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "red leather jacket"}'{
"session_id": "6f1c...",
"livekit_url": "wss://....livekit.cloud",
"client_livekit_token": "eyJhbGciOi...",
"max_seconds": 120,
"cold_start_max_seconds": 300
}// Your server (Node). The API key never goes to the browser.
app.post("/start-edit", async (req, res) => {
const r = await fetch("https://babaganoush-production.up.railway.app/v1/sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.VIDEO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ prompt: req.body.prompt }),
});
res.status(r.status).json(await r.json()); // livekit_url + client_livekit_token, no secrets
});The first session after a quiet period waits for a GPU to start. That wait is free: the clock (max_seconds) starts when the edited video starts. Call POST /v1/warm when your user opens the page to start a GPU early.
2.Join the room and send video (in your app)
// Your web page. npm install livekit-client
import { Room, RoomEvent, Track, createLocalVideoTrack } from "livekit-client";
const session = await (await fetch("/start-edit", { method: "POST", /* prompt */ })).json();
const room = new Room();
room.on(RoomEvent.TrackSubscribed, (track) => {
if (track.kind === Track.Kind.Video) track.attach(document.querySelector("#edited"));
});
room.on(RoomEvent.DataReceived, (payload) => {
const msg = JSON.parse(new TextDecoder().decode(payload));
// {type: "status", state: "loading" | "streaming", ends_at} GPU starting / live, and when time is up
// {type: "error", message} something went wrong
// {type: "ended", reason} session over
});
await room.connect(session.livekit_url, session.client_livekit_token);
const camera = await createLocalVideoTrack({ resolution: { width: 848, height: 480, frameRate: 24 } });
await room.localParticipant.publishTrack(camera, {
source: Track.Source.Camera,
videoEncoding: { maxBitrate: 1_000_000, maxFramerate: 24 },
});3.Change the prompt while it runs
const send = (text) => room.localParticipant.publishData(
new TextEncoder().encode(JSON.stringify({ prompt: text })), { reliable: true });
send("cyberpunk neon city");4.End the session
curl -X DELETE https://babaganoush-production.up.railway.app/v1/sessions/$SESSION_ID -H "Authorization: Bearer $VIDEO_API_KEY"
# {"session_id": "6f1c...", "seconds": 42.3, "cost_usd": 0.2938}Leaving the room also ends it. Sessions stop by themselves after max_seconds.
5.Check usage and balance
curl https://babaganoush-production.up.railway.app/v1/usage -H "Authorization: Bearer $VIDEO_API_KEY"
# {"sessions": 12, "minutes": 9.4, "balance_usd": 21.08}Billing: $25 / hour of edited video (≈ $0.42 / minute), billed per second from your prepaid credits.
Errors
| 401 | Missing, wrong or revoked API key. |
| 402 | Out of credits: your balance must cover the longest possible session. Buy credits in the dashboard. |
| 429 | Daily limit for this API key reached. |
| 503 | All GPUs busy, or daily capacity reached. Try again shortly. |
| 502 | Could not start a GPU job. Try again shortly. |