Skip to main content
This example reuses the fetchWithPayment helper from /quickstart to replay the x402 payment challenge automatically.

1. Request the video job

const baseUrl = process.env.HORIZON_BASE_URL ?? 'https://api.horizon.new/v1';

const videoResponse = await fetchWithPayment(`${baseUrl}/generate/videos`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    prompt: 'Camera glides through a floating lounge surrounded by aurora lights.',
    durationSeconds: 8,
    resolution: '1080p',
    webhookUrl: 'https://example.com/webhooks/horizon/generation',
  }),
});

const videoJob = await videoResponse.json();
console.log('video job', videoJob.jobId);

2. Handle synchronous completions

if (videoJob.status === 'completed' && videoJob.result) {
  console.log('Video artifacts ready', videoJob.result.artifacts);
}

3. Poll and collect the output

const statusResponse = await fetchWithPayment(videoJob.statusUrl);
const status = await statusResponse.json();

if (status.state === 'processing') {
  await new Promise((resolve) => setTimeout(resolve, 4000));
  // fetch again or rely on your webhook
}

if (status.state !== 'succeeded') {
  throw new Error(`Video generation failed: ${status.error?.code ?? 'unknown'}`);
}

const { artifacts } = status.result;
console.log('Primary asset URL', artifacts?.[0]?.url);

4. Distribute the clip

  • Store URLs or binary payloads in your asset pipeline.
  • Use your routing config (for example, campaign or channel identifiers) to send clips to schedulers automatically.
  • If you need multiple cuts, track variants in your datastore so you can fan out downstream jobs.