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

401Missing, wrong or revoked API key.
402Out of credits: your balance must cover the longest possible session. Buy credits in the dashboard.
429Daily limit for this API key reached.
503All GPUs busy, or daily capacity reached. Try again shortly.
502Could not start a GPU job. Try again shortly.
Plotin — Real-time AI video editing API