JavaScript video API

Node 18+ or any runtime with fetch. File: /examples/javascript/generate.mjs.

/**
 * Minimal VideoGenAPI client for Node 18+ (native fetch).
 * Last reviewed: 16 August 2026.
 */
const BASE = 'https://videogenapi.com/api/v1';
const KEY = process.env.VIDEOGENAPI_KEY || '';

export async function generate(prompt, model = 'kling-3', duration = 5) {
  const res = await fetch(`${BASE}/generate`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ model, prompt, duration }),
  });
  if (!res.ok) {
    throw new Error(`generate failed: ${res.status} ${await res.text()}`);
  }
  return res.json();
}

export async function wait(generationId, timeoutMs = 300000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const res = await fetch(`${BASE}/status/${generationId}`, {
      headers: { Authorization: `Bearer ${KEY}` },
    });
    if (!res.ok) {
      throw new Error(`status failed: ${res.status}`);
    }
    const data = await res.json();
    const status = (data.status || data.data?.status || '').toLowerCase();
    if (['completed', 'success', 'failed', 'error'].includes(status)) {
      return data;
    }
    await new Promise((r) => setTimeout(r, 3000));
  }
  throw new Error('generation timed out');
}

if (import.meta.url === `file://${process.argv[1]}`) {
  if (!KEY) {
    console.error('Set VIDEOGENAPI_KEY');
    process.exit(1);
  }
  const prompt = process.argv[2] || 'A ceramic mug on a sunlit table, slow camera push-in';
  const job = await generate(prompt);
  const id = job.generation_id || job.id || job.data?.id;
  console.log('queued', id);
  console.log(await wait(id));
}
Reviewed by Enzo Lanne · Founder, VideoGenAPI ·