Quick Start

Everything you need to start generating videos with the Golpo REST API v2.

Auth header

x-api-key: YOUR_API_KEY

Content-Type

application/json

Best for

Server-to-server integrations, automation workflows, internal dashboards, partner apps

Prerequisites

Valid API plan · API key issued per workspace · HTTPS requests only · 15 MB max file upload

NOTE:POST /api/v2/videos/generate requires x-api-key. Returns 403 with the message “API v2 requires API key authentication. Provide ‘x-api-key’ header.” if the header is missing.
Your API base URL is provided when you create an API key in the dashboard. All requests must be made over HTTPS.

Endpoints

Five REST endpoints covering the full video lifecycle — generate, list, retrieve, update, and delete.

POST/api/v2/videos/generate

Generate a video from a prompt or script. JSON body, x-api-key required.

generate.js
import fetch from "node-fetch";

const API_KEY = "api-key"; // Replace with your Golpo API key

const payload = {
  prompt: "Explain the quarterly roadmap",
  background_track: "engaging"
};

const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

const data = await response.json();
console.log(data);

Run with: node --env-file=.env generate.js

GET/api/v2/videos

Retrieve videos belonging to the authenticated user. Supports limit and offset query params. x-api-key required.

list-videos.js
import fetch from "node-fetch";

const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

// Query params:
//   limit  — max number of videos to return (optional)
//   offset — number of videos to skip (optional, for pagination)
const response = await fetch(`${BASE_URL}/api/v2/videos?limit=10&offset=0`, {
  headers: {
    "x-api-key": "api-key"
  }
});

const data = await response.json();
console.log(data.videos); // array of video objects
console.log(data.total);  // total number of videos

Run with: node --env-file=.env list-videos.js

GET/api/v2/videos/{video_id}

Retrieve metadata for a single video by ID. x-api-key required.

get-video.js
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const VIDEO_ID = "video_id";

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  headers: { "x-api-key": "api-key" }
});
console.log(await response.json());

Run with: node --env-file=.env get-video.js <video_id>

PATCH/api/v2/videos/{video_id}

Update video metadata. Only 'title' and 'visibility' can be updated.

update-video.js
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const VIDEO_ID = "video_id";

const payload = { title: "Updated internal briefing", visibility: "private" };

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "api-key"
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env update-video.js <video_id>

DELETE/api/v2/videos/{video_id}

Delete a generated video (soft delete). x-api-key required.

delete-video.js
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const VIDEO_ID = "video_id";

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  method: "DELETE",
  headers: { "x-api-key": "api-key" }
});

console.log(await response.json());

Run with: node --env-file=.env delete-video.js <video_id>

Request Body

Full parameter reference for POST /api/v2/videos/generate.

Only prompt is required. All other parameters are optional.
ParameterTypeDefaultRequiredDescription
promptstringRequired
Main prompt/topic for the video.
reference_sourcearray[string]NoneOptional
List of document URLs (https/s3) used as reference material. Use /upload-file to obtain URLs; server-side callers may also pass local file paths.
narration_instructionsstring""Optional
Describe how the narration voice should sound — accent, tone, pace, and delivery style.
Examples: "Speak in a warm British accent with a calm, professorial tone", "Fast-paced sports commentator style".
enable_script_only_modebooleanfalseOptional
Only generate the script — skip TTS and video rendering. Status response returns script_text.
custom_scriptstringNoneOptional
Use a script you supply instead of generating one. Capped at approximately 15 estimated minutes.
NOTE:Scripts longer than ~15 estimated minutes are rejected with 422. If timing is also set, it must be greater than or equal to the estimated script duration.
Embedding paired [START][IMAGE N]...[END][IMAGE N] and [START][VIDEO N]...[END][VIDEO N] markers in your script controls where your uploaded custom_images and custom_videos appear. See the Inserting Images in Script and Inserting Videos in Script sections for the placement rules — markers that violate the format are silently dropped.
narration_voicestring"female-1"Optional
Narration voice.
Allowed values: "female-1" (default), "female-2", "male-1", "male-2".
enable_colorbooleantrueOptional
Enable color video generation pipeline.
narration_languagestring"en"Optional
Language for narration. Lowercase only — accepts language keywords (e.g. "english", "hindi"), ISO 639-1 codes (e.g. "en", "hi"), or code-switch variants (e.g. "hi-en").
background_trackstringNoneOptional
Background music track.
Allowed values: "jazz", "lofi", "dramatic", "engaging", "hyper", "inspirational", "documentary".
video_orientationstring"horizontal"Optional
Video orientation: "horizontal" (16:9) or "vertical" (9:16).
enable_podcast_enginebooleanfalseOptional
When true, generate audio-only podcast output (no video). Status response returns podcast_url.
timingstring"1"Optional
Video/podcast duration in minutes (as string) or "auto" to let the system determine it.
Supported values: "0.25", "0.5", "1", "2", "4", "8", "10", "15", "auto".
NOTE:"15" is only available on the Enterprise Custom plan. Other plans receive a 403 when requesting 15-minute videos. Contact founders@golpoai.com to upgrade.
watermarkbooleanfalseOptional
Include a watermark in the video.
custom_logostringNoneOptional
Custom logo URL (https/s3). Use /upload-file first; server-side callers may also pass local file paths.
logo_positionstringNoneOptional
Logo placement. Allowed values: "tl" (top-left), "tr" (top-right), "bl" (bottom-left), "br" (bottom-right).
NOTE:Only valid when watermark=true or custom_logo is provided. Setting logo_position without either is rejected with 422, since no logo or watermark would render.
visual_instructionsstring""Optional
Visual instructions to guide how the video looks.
Examples: "Show more graphs and charts", "Cinematic transitions", "Dark moody aesthetic with neon accents".
golpo_video_enginestring"golpo_canvas"Optional
Video generation engine: "golpo_canvas" (default) or "golpo_sketch".
NOTE:When using golpo_canvas, canvas_style_variant is required. When using golpo_sketch, sketch_style_variant is required. Setting either to null is rejected with 422.
canvas_style_variantstring"chalkboard_color"Optional
Golpo Canvas style variant.
Allowed values: "chalkboard_bw", "chalkboard_color" (default), "whiteboard", "modern_minimal", "technical", "sharpie", "playful", "editorial", "illustrations". Required when golpo_video_engine is "golpo_canvas".
sketch_style_variantstring"classic"Optional
Golpo Sketch style variant.
Allowed values: "classic" (default), "improved(beta)", "formal", "crayon", "dry_erase", "professional_clean", "creative", "infographics". Required when golpo_video_engine is "golpo_sketch".
own_narration_sourcestringNoneOptional
URL (https/s3) to an audio or video file to use instead of generating script and TTS. Server-side callers may also pass local file paths.
Useful for generating a video from your own existing audio or video narration.
use_ai_audio_atarray[integer]NoneOptional
List of 1-indexed positions in custom_videos whose original audio should be replaced with AI-generated narration. Videos not listed keep their original audio.
NOTE:Only valid when custom_videos is provided. Length must not exceed the number of custom_videos.
custom_imagesarray[string]NoneOptional
List of image URLs (https/s3) to insert into the video. Server-side callers may also pass local file paths.
custom_images_descriptionarray[string]NoneOptional
List of descriptions for custom images (one per image).
NOTE:Required when custom_images is provided. Must have the same length as custom_images.
Descriptions tell the Golpo AI what each image shows, so it can place each image at the right moment in the script and reference it in the narration. More specific descriptions produce more contextually accurate videos.
keep_original_imagesarray[boolean]NoneOptional
List of booleans indicating whether to use each image as-is without AI processing (one per image).
NOTE:Only valid when custom_images is provided. Length must not exceed the number of custom_images.
disable_image_animationarray[boolean]NoneOptional
List of booleans indicating whether to skip animation for each image (one per image).
NOTE:Only valid when custom_images is provided. Length must not exceed the number of custom_images.
custom_videosarray[string]NoneOptional
List of video URLs (https/s3) to insert into the video. Server-side callers may also pass local file paths.
custom_videos_descriptionarray[string]NoneOptional
List of descriptions for custom videos (one per video).
NOTE:Required when custom_videos is provided. Must have the same length as custom_videos.
Descriptions tell the Golpo AI what each video shows, so it can cut to each clip at the right moment in the script and frame the surrounding narration. More specific descriptions produce more contextually accurate videos.
visibilitystringNoneOptional
Video visibility. Allowed values: "public" (appears in the Golpo gallery) or "private".
video_idstringNoneOptional
Optional custom video/job id assigned by the caller.
reference_imagesarray[string]NoneOptional
List of reference image URLs (https/s3) for problem-solving mode. The video is generated around the provided images. Server-side callers may also pass local file paths.
Best suited for explaining math, science, or any problem captured as an image — pair with timing: "auto" so the Golpo AI picks a duration that matches the complexity of the problem.
pen_animation_stylestringNoneOptional
Pen cursor animation style. Allowed values: "stylus", "marker", "pen".
NOTE:Only supported with the Golpo Canvas engine. Setting this field with "golpo_video_engine": "golpo_sketch" is rejected with 422.
own_narration_video_modebooleanNoneOptional
When true, the user's own narration video is overlaid as a picture-in-picture thumbnail. Requires own_narration_source to point to a video file.
NOTE:Setting own_narration_video_mode=true with a non-video own_narration_source returns 422.
own_narration_video_positionstring"left-top"Optional
Corner for the picture-in-picture overlay. Allowed values: "left-top" (default), "right-top", "left-bottom", "right-bottom".
scene_pacingstring"normal"Optional
Pacing level: "normal" (15s max per scene) or "fast" (10s max per scene). Works with both Golpo Canvas and Golpo Sketch.
onscreen_text_languagestringNoneOptional
Language for on-screen text. Same value space as narration_language. Useful when displayed text should differ from the narration language.
NOTE:Only supported with the Golpo Canvas engine. Setting this field with "golpo_video_engine": "golpo_sketch" is rejected with 422.
If omitted, on-screen text uses the same language as narration_language.
Example: narration_language: "hindi", onscreen_text_language: "english" — narration in Hindi, on-screen text in English.

Parameter Groups

Parameters organized by purpose for easier discovery.

Content

promptcustom_scriptenable_script_only_modereference_sourcereference_images

Narration

narration_voicenarration_instructionsnarration_languageonscreen_text_languageown_narration_sourceown_narration_video_modeown_narration_video_position

Visual

golpo_video_enginecanvas_style_variantsketch_style_variantenable_colorvisual_instructionspen_animation_stylescene_pacing

User Media

custom_imagescustom_images_descriptionkeep_original_imagesdisable_image_animationcustom_videoscustom_videos_descriptionuse_ai_audio_at

Audio

background_track

Format

timingvideo_orientationenable_podcast_engine

Branding

watermarkcustom_logologo_position

Workflow

visibilityvideo_id

Upload File

Use /api/v2/videos/upload-file to get a hosted URL before calling /generate.

NOTE:Maximum file size is 15 MB. Larger files are rejected with HTTP 413. The upload endpoint is gated to Plus and above plans — Free, Starter, Beginner, Growth, Business, and Creator return 403.
NOTE:Document URLs are single-use. When you pass a document URL (PDF, DOCX, TXT, etc.) from /upload-file into reference_source, the file is permanently deleted from storage after its text is extracted during generation. The same URL cannot be reused for another video or podcast — you must upload the document again via /upload-file to get a fresh URL for each new generation.
Content-Type:multipart/form-data
FieldTypeRequiredDescription
fileFileYesSingle file to upload (file metadata is used to generate a presigned URL).

Documents

PDF · DOC · DOCX · TXT · MD · CSV · XLSX · XLS · PPT · PPTX

Audio

MP3 · WAV · M4A · OGG · FLAC

Video

MP4 · MOV · M4V · AVI · MKV · WEBM

Images

JPG · JPEG · PNG · GIF · WEBP

upload-response.json
// Response from POST /api/v2/videos/upload-file
{
  "upload_url":   "https://...",  // Presigned PUT URL — upload the file here
  "file_url":     "https://...",  // Pass this into /generate
  "file_name":    "document.pdf",
  "content_type": "application/pdf"
}
upload-file.js
const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

// Step 1: Get presigned URL
async function uploadFile(file) {
  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch(`${BASE_URL}/api/v2/videos/upload-file`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY },
    body: formData
  });

  const { upload_url, file_url, content_type } = await response.json();

  // Step 2: Upload bytes to the presigned URL
  await fetch(upload_url, {
    method: 'PUT',
    headers: { 'Content-Type': content_type },
    body: file
  });

  // Step 3: Return file_url for use in /generate
  return file_url;
}

// Usage
const fileInput = document.querySelector('#file-input');
const fileUrl = await uploadFile(fileInput.files[0]);
console.log('File uploaded, URL:', fileUrl);
// Use fileUrl in your /generate request (reference_source, custom_logo, etc.)

User Assets

Upload images or videos to embed directly into the generated video.

NOTE:custom_images and custom_videos accept the file_url returned by /upload-file. Server-side callers may pass local file paths directly. Description arrays (custom_images_description, custom_videos_description) are required and must match the length of their image/video arrays.
generate-with-user-assets.js
const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

async function uploadFile(file) {
  const formData = new FormData();
  formData.append('file', file);

  const presign = await fetch(`${BASE_URL}/api/v2/videos/upload-file`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY },
    body: formData
  });
  const { upload_url, file_url, content_type } = await presign.json();

  await fetch(upload_url, {
    method: 'PUT',
    headers: { 'Content-Type': content_type },
    body: file
  });

  return file_url;
}

// Step 1: Upload images and videos
const image1Url = await uploadFile(imageFile1);
const image2Url = await uploadFile(imageFile2);
const video1Url = await uploadFile(videoFile1);
const video2Url = await uploadFile(videoFile2);

// Step 2: Generate with custom images and videos
const generatePayload = {
  prompt: "Create a product showcase video",
  custom_images: [image1Url, image2Url],
  custom_images_description: [
    "Product front view with logo",
    "Product in use by customer"
  ],
  keep_original_images: [false, false],
  disable_image_animation: [false, true],
  custom_videos: [video1Url, video2Url],
  custom_videos_description: [
    "Customer testimonial",
    "Product walkthrough"
  ],
  // 1-indexed positions in custom_videos whose original audio
  // should be replaced with AI-generated narration.
  use_ai_audio_at: [2],
  video_orientation: "horizontal",
  watermark: false
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': API_KEY
  },
  body: JSON.stringify(generatePayload)
});

const result = await response.json();
console.log('Job ID:', result.job_id);

Local Paths

Pass absolute or relative file paths directly from server-side environments — the v2 backend uploads them transparently.

NOTE:Local paths are only supported in server-side environments where the API server has filesystem access. For remote clients, upload via /upload-file first.
generate-with-local-paths.js
import fetch from "node-fetch";

const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

// Server-side only: when the API server has filesystem access
// to these files, it uploads them transparently before generation.
const payload = {
  prompt: "Create a comprehensive product demo video",
  reference_source: [
    "./documents/product-spec.pdf",
    "C:\\Users\\Documents\\brief.docx",
    "/home/user/documents/slides.pptx"
  ],
  custom_logo: "./assets/company-logo.png",
  custom_images: [
    "./images/product-front.jpg",
    "./images/product-in-use.jpg"
  ],
  custom_images_description: [
    "Product front view with branding",
    "Product being used by customer"
  ],
  keep_original_images: [false, false],
  disable_image_animation: [false, true],
  own_narration_source: "./audio/founder-narration.mp3",
  narration_voice: "female-1",
  background_track: "engaging",
  video_orientation: "horizontal",
  watermark: false,
  enable_color: true,
  narration_language: "en",
  timing: "5"
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

const data = await response.json();
console.log("Job ID:", data.job_id);

Local paths only work when the API server can access these files. Remote clients must upload via /upload-file first.

Language Quickstarts

Ready-to-run examples for the most common video generation patterns.

Upload Workflow

Full pattern: upload supporting files via /upload-file, then call /generate with the returned URLs in reference_source.

generateVideoWithUploads.js
const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

// Step 1: Helper to upload a file via /upload-file
async function uploadFile(file) {
  const formData = new FormData();
  formData.append('file', file);

  const presign = await fetch(`${BASE_URL}/api/v2/videos/upload-file`, {
    method: 'POST',
    headers: { 'x-api-key': API_KEY },
    body: formData
  });
  const { upload_url, file_url, content_type } = await presign.json();

  await fetch(upload_url, {
    method: 'PUT',
    headers: { 'Content-Type': content_type },
    body: file
  });

  return file_url;
}

// Step 2: Upload all reference docs and collect URLs
const fileInput = document.querySelector('#uploads');
const referenceUrls = await Promise.all(
  Array.from(fileInput.files).map((f) => uploadFile(f))
);

// Step 3: Generate the video with the uploaded references
const generatePayload = {
  prompt: 'Summarize this slide deck for executives',
  reference_source: referenceUrls,
  narration_voice: 'female-1',
  narration_language: 'spanish'
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': API_KEY
  },
  body: JSON.stringify(generatePayload)
});

const result = await response.json();
console.log('Generation started:', result);

Attach files via <input id="uploads" type="file" multiple /> before calling this helper.

Golpo Sketch

golpo_video_engine: golpo_sketch

Whiteboard-style sketch animation. Pick a sketch_style_variant and optionally tune scene_pacing (normal/fast).

golpo-sketch.js
import fetch from "node-fetch";

const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

const payload = {
  prompt: "Explain how neural networks work",
  golpo_video_engine: "golpo_sketch",
  // sketch_style_variant options:
  //   "classic" (default), "improved(beta)", "formal",
  //   "crayon", "dry_erase", "professional_clean",
  //   "creative", "infographics"
  sketch_style_variant: "improved(beta)",
  scene_pacing: "fast",              // "normal" (15s max) | "fast" (10s max)
  background_track: "engaging",
  watermark: false
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env golpo-sketch.js

Golpo Canvas

golpo_video_engine: golpo_canvas

Canvas-based video with rich style variants (chalkboard, whiteboard, editorial…) plus pen_animation_style and scene_pacing.

golpo-canvas.js
import fetch from "node-fetch";

const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

const payload = {
  prompt: "Create a product overview video",
  golpo_video_engine: "golpo_canvas",
  // canvas_style_variant options:
  //   "chalkboard_bw", "chalkboard_color" (default), "whiteboard",
  //   "modern_minimal", "technical", "sharpie", "playful", "editorial",
  //   "illustrations"
  canvas_style_variant: "modern_minimal",
  pen_animation_style: "stylus",       // "stylus" | "marker" | "pen"
  scene_pacing: "normal",              // "normal" (15s max) | "fast" (10s max)
  watermark: false
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env golpo-canvas.js

Display Language

Generate a video where the narration and the on-screen text are in different languages. Only supported with the Golpo Canvas engine.

Display Language

onscreen_text_language

Generate a video where the narration and the on-screen text are in different languages — e.g. Hindi voice-over with English text displayed in the video. Only supported with the Golpo Canvas engine; setting onscreen_text_language with golpo_video_engine: golpo_sketch is rejected with 422.

display-language.js
import fetch from "node-fetch";

const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

// Narrator speaks Hindi; on-screen text, titles, and labels are in English.
const payload = {
  prompt: "Explain the water cycle",
  narration_language: "hindi",
  onscreen_text_language: "english",
  narration_voice: "female-1",
  watermark: false
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env display-language.js

Generate Video

POST /api/v2/videos/generate

Generate a video from a prompt or script with customizable voice, visuals, music, and branding.

generate.js
import fetch from "node-fetch";

const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

const payload = {
  prompt: "Explain the quarterly roadmap",
  background_track: "engaging"
};

const response = await fetch(`${BASE_URL}/api/v2/videos/generate`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env generate.js

List Videos

GET /api/v2/videos

Retrieve videos belonging to the authenticated user. Supports limit and offset query params.

list-videos.js
import fetch from "node-fetch";

const BASE_URL = "{BASE_URL}";

// Query params:
//   limit  — max number of videos to return (optional)
//   offset — number of videos to skip (optional, for pagination)
const response = await fetch(`${BASE_URL}/api/v2/videos?limit=10&offset=0`, {
  headers: { "x-api-key": "api-key" }
});

const data = await response.json();
console.log(data.videos);
console.log(data.total);

Run with: node --env-file=.env list-videos.js

Get Video

GET /api/v2/videos/{video_id}

Retrieve metadata for a single video by ID.

get-video.js
const BASE_URL = "{BASE_URL}";
const VIDEO_ID = "video_id";

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  headers: { "x-api-key": "api-key" }
});
console.log(await response.json());

Run with: node --env-file=.env get-video.js <video_id>

Update Video

PATCH /api/v2/videos/{video_id}

Update video metadata. Only 'title' and 'visibility' can be updated.

update-video.js
const BASE_URL = "{BASE_URL}";
const VIDEO_ID = "video_id";

// Only 'title' and 'visibility' are accepted.
const payload = { title: "Updated internal briefing", visibility: "private" };

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  method: "PATCH",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": "api-key"
  },
  body: JSON.stringify(payload)
});

console.log(await response.json());

Run with: node --env-file=.env update-video.js <video_id>

Delete Video

DELETE /api/v2/videos/{video_id}

Soft-delete a generated video.

delete-video.js
const BASE_URL = "{BASE_URL}";
const VIDEO_ID = "video_id";

const response = await fetch(`${BASE_URL}/api/v2/videos/${VIDEO_ID}`, {
  method: "DELETE",
  headers: { "x-api-key": "api-key" }
});

console.log(await response.json());

Run with: node --env-file=.env delete-video.js <video_id>

Job Status

GET /api/v2/videos/status/{job_id}

Poll the status endpoint to track generation progress. Response shape depends on the original /generate request — script_text, podcast_url, or video_url.

job-status.js
const BASE_URL = "{BASE_URL}";
const JOB_ID = "job-id";

const response = await fetch(`${BASE_URL}/api/v2/videos/status/${JOB_ID}`, {
  headers: { "x-api-key": "api-key" }
});

const body = await response.json();
console.log(body);
// Three response shapes (depending on original generate request):
//   { job_id, status, created_at, script_text }   // enable_script_only_mode=true
//   { job_id, status, created_at, podcast_url }   // enable_podcast_engine=true
//   { job_id, status, created_at, video_url }     // default (video)

Run with: node --env-file=.env job-status.js <job_id>

Style Previews

Short sample videos for every canvas_style_variant and sketch_style_variant. Click any tile to play.

Golpo Canvas

Use with golpo_video_engine: "golpo_canvas".

Chalkboard B&Wchalkboard_bw
Chalkboard Colorchalkboard_color
Whiteboardwhiteboard
Modern Minimalmodern_minimal
Technicaltechnical
Sharpiesharpie
Playfulplayful
Editorialeditorial
Illustrationsillustrations

Golpo Sketch

Use with golpo_video_engine: "golpo_sketch".

Classicclassic
Improved (Beta)improved(beta)
Formalformal
Crayoncrayon
Dry Erasedry_erase
Professional Cleanprofessional_clean
Creativecreative
Infographicsinfographics

Timing

Timing parameter reference — provide duration in minutes as a string, or "auto" to let the system determine the optimal duration.

ValueDuration
"0.25"15 seconds
"0.5"30 seconds
"1"1 minute
"2"2 minutes
"4"4 minutes
"8"8 minutesBeta
"10"10 minutesBeta
"15"15 minutesBeta
"auto"System-determined
Supported values: "0.25", "0.5", "1", "2", "4", "8", "10", "15", "auto".
NOTE:"15" is restricted: 15-minute videos are only available on the Enterprise Custom plan. Other plans receive a 403 when requesting 15-minute videos. Contact founders@golpoai.com to upgrade.
When to use "auto" timing: Use auto timing when the content complexity should determine the video length. Especially useful for problem-solving — pass a math or physics problem via reference_images and the golpo engine will analyze the complexity and generate a script of the appropriate length.

Example: Auto Timing with Problem Solving

Pass a problem image via reference_images with Golpo Canvas and let the engine decide how long the explanation should be.

auto-timing-example.json
{
  "prompt": "Solve and explain this calculus problem step by step",
  "reference_images": [
    "https://your-bucket.s3.amazonaws.com/calculus-problem.png"
  ],
  "golpo_video_engine": "golpo_canvas",
  "canvas_style_variant": "whiteboard",
  "timing": "auto",
  "narration_voice": "male-1",
  "video_orientation": "horizontal"
}

Video Orientation

Controls the video aspect ratio and orientation.

ValueFormatDimensionsUse Cases
"vertical"Vertical / Portrait1024×1536 pxTikTok, Instagram Reels, YouTube Shorts
"horizontal"Horizontal / Landscape (Default)1536×1024 pxYouTube, standard video content
9:16

vertical

1024×1536 px

16:9

horizontal (default)

1536×1024 px

Narration Voices

Pick the voice that narrates your video. Pass your choice in the narration_voice parameter — two female voices and two male voices are available, each with its own tone and style.

ValueVoice TypeDescription
"female-1"Female 1Female narrator voice (Default)
"female-2"Female 2Alternative female narrator voice
"male-1"Male 1Male narrator voice
"male-2"Male 2Alternative male narrator voice

Background Music

Send the background_track field in your JSON body using one of the following keys.

background_track keyMood / Usage
"jazz"Warm, neutral bed
"lofi"Calm, study vibes
"dramatic"Cinematic tension
"engaging"Subtle corporate pulse
"hyper"High-energy electronic
"inspirational"Uplifting orchestral
"documentary"Serious factual tone

Voice Instructions

Describe how the voice should sound — accent, tone, or pronunciation style.

Pass instructions in the narration_instructions field to guide voice generation. The AI will adjust accent, tone, pace, and delivery accordingly.

narration-instructions-example.json
{
  "prompt": "Explain quantum computing basics",
  "narration_instructions": "Speak in a warm British accent with a calm, professorial tone. Pause slightly between key concepts for emphasis.",
  "narration_voice": "male-1"
}

More examples

Talk in a French accent
Use an enthusiastic, energetic tone
Talk like a professor — measured and articulate
Speak slowly and clearly, like a meditation guide
Fast-paced sports commentator style
Friendly and casual, like chatting with a friend

Video Instructions

Describe how the video should look — visuals, style, and scene direction.

Pass instructions in the visual_instructions field to guide the visual generation. The AI will adjust scene composition, imagery, and visual style accordingly.

visual-instructions-example.json
{
  "prompt": "Company quarterly results overview",
  "visual_instructions": "Use clean corporate visuals with data charts and graphs. Include stock footage of modern office environments. Prefer blue and white color palette.",
  "narration_voice": "female-1"
}

More examples

Show more graphs and charts
Include more stock footage
Use cinematic transitions
Female presenter in an office setting
Urban background with modern architecture
Dark moody aesthetic with neon accents

Golpo Engine

Pick the video generation pipeline. golpo_canvas is the default; golpo_sketch produces whiteboard-style line-art animations.

ValueEngineDescription
"golpo_canvas"Golpo Canvas (Default)Canvas-based video with rich style variants. Requires canvas_style_variant.
"golpo_sketch"Golpo SketchWhiteboard line-art animation. Requires sketch_style_variant.
NOTE:Setting canvas_style_variant to null with golpo_canvas(or sketch_style_variant to null with golpo_sketch) is rejected with HTTP 422.

Canvas Style Variant

canvas_style_variant controls the visual style for golpo_video_engine: "golpo_canvas".

ValueLabelDescription
"chalkboard_bw"Chalkboard (B/W)Black & white chalkboard style
"chalkboard_color"Chalkboard ColorColorful neon chalkboard style (Default)
"whiteboard"WhiteboardClean whiteboard illustrations
"modern_minimal"Modern MinimalSleek, minimal modern aesthetic
"technical"TechnicalTechnical diagram style
"sharpie"SharpieBold marker/sharpie drawn style
"playful"PlayfulFun, colorful playful illustrations
"editorial"EditorialMagazine/editorial illustration style
"illustrations"IllustrationsVox-style editorial explainer with paper-textured infographic look
golpo-canvas-example.json
{
  "prompt": "How solar panels convert sunlight to electricity",
  "golpo_video_engine": "golpo_canvas",
  "canvas_style_variant": "modern_minimal",
  "pen_animation_style": "stylus",
  "scene_pacing": "normal",
  "timing": "2"
}

Sketch Style Variant

sketch_style_variant controls the look for golpo_video_engine: "golpo_sketch".

ValueLabelDescription
"classic"ClassicOriginal Golpo Sketch — classic whiteboard line-art animation (Default)
"improved(beta)"ImprovedImproved line-art with cleaner strokes and a more polished look
"formal"FormalAdvanced sketch generation with higher detail and refined aesthetics
"crayon"CrayonStorytelling crayon sketch look
"dry_erase"Dry EraseWhiteboard dry-erase aesthetic
"professional_clean"Professional CleanClean, minimal professional sketch
"creative"CreativeAfter Skool whiteboard-marker variant with bold colorful strokes
"infographics"InfographicsVox-style editorial explainer with paper-textured infographic look
scene_pacing applies to both engines: "normal" caps frames at 15s; "fast" caps frames at 10s.

Pen Animation Style

pen_animation_style adds a drawing cursor effect to the animation. Only supported with the Golpo Canvas engine — setting it with golpo_video_engine: "golpo_sketch" is rejected with 422.

ValueDescription
nullNo pen cursor (Default)
"stylus"Thin stylus pen cursor
"marker"Thick marker cursor
"pen"Classic pen cursor

Inserting Images in Script

How to place paired [START][IMAGE N] and [END][IMAGE N] markers inside custom_script so your uploaded custom_images land at the right moment in the narration.

When you supply your own script via custom_script and also upload custom_images, wrap a sentence in paired markers to control where each image appears. [IMAGE 1] refers to the first image in custom_images, [IMAGE 2] to the second, and so on (marker numbers start at 1, not 0). The image displays for the duration of the spoken text between [START][IMAGE N] and [END][IMAGE N].

Follow these rules to make sure your image inserts are never silently skipped:

  • Use 1 for your first uploaded image, 2 for the second, and so on. [IMAGE 1] → first item in custom_images. If you write [IMAGE 3] but only uploaded 2 images, that image won’t appear.
  • Every [START][IMAGE N] needs a matching [END][IMAGE N] with the same number. Missing or mismatched closing tags drop the marker.
  • Put whitespace around marker tags when they sit next to sentence punctuation. Always leave a space (or newline) between the preceding sentence's period and [START], and between [END][IMAGE N] and the next sentence. Write story. [START][IMAGE 2] and [END][IMAGE 1] Next sentence. — never story.[START][IMAGE 2] or [END][IMAGE 1]Next sentence.. Without these spaces the sentence splitter cannot find a clean break and the marker is dropped.
  • Wrap a complete, simple sentence of 8–15 plain words between the markers. Shorter than 5 words is fragile; longer than 20 holds the image on-screen too long.
  • Avoid colons (:), em-dashes (), semicolons (;), and parentheses inside the marker span.
  • Keep commas inside the marker to at most one or two. Stacked lists like "not X, not Y, not Z" confuse the matcher.
NOTE:Image markers that violate any of these rules are silently dropped — no error, no warning. The frame at that position falls back to an AI-generated visual and your uploaded image never appears.

Example 1 — Good shape (use as a template):

image-markers-good-shape.json
{
  "custom_script": "Travel changes how we see the world. [START][IMAGE 1] This is a quiet beach at sunset with golden waves rolling onto soft sand. [END][IMAGE 1] Coastal trips help us slow down and breathe deeply for a few days. [START][IMAGE 2] This is a mountain village tucked between tall green peaks and clouds. [END][IMAGE 2] Highland trips reward you with cool air and stunning scenic views.",
  "custom_images": [
    "https://example.com/beach.png",
    "https://example.com/mountain.png"
  ],
  "custom_images_description": [
    "A quiet beach at sunset",
    "A mountain village among green peaks"
  ]
}

Each wrapped sentence is ~10–12 plain words, contains no colons or em-dashes, has a single space after each preceding period, and the marker numbers (1, 2) match the 2-item custom_images array.

You can also use other image control parameters alongside the markers: keep_original_images (boolean array — skip AI processing and place the image untouched) and disable_image_animation (boolean array — render as a static frame instead of an animated drawing).

Example 2 — Common mistakes and their fixes:

image-markers-missing-space.json
// ❌ Mistake A: no space BEFORE [START] — IMAGE 2 won't appear
{
  "custom_script": "...each region tells a unique story.[START][IMAGE 2] Rajasthan glows proudly with royal forts and deserts[END][IMAGE 2]."
}

// ✅ Fix A: add a single space between "story." and "[START][IMAGE 2]"
{
  "custom_script": "...each region tells a unique story. [START][IMAGE 2] Rajasthan glows proudly with royal forts and deserts[END][IMAGE 2]."
}

// ❌ Mistake B: no space AFTER [END] — IMAGE 1 won't appear
{
  "custom_script": "[START][IMAGE 1] A coastal town glows at sunset by the harbor. [END][IMAGE 1]The next morning brings calm waters and a quiet beach."
}

// ✅ Fix B: add a single space between "[END][IMAGE 1]" and "The"
{
  "custom_script": "[START][IMAGE 1] A coastal town glows at sunset by the harbor. [END][IMAGE 1] The next morning brings calm waters and a quiet beach."
}

Inserting Videos in Script

How to place paired [START][VIDEO N]...[END][VIDEO N] markers inside custom_script so your uploaded custom_videos play for the right span of narration.

When you supply your own script via custom_script and also upload custom_videos, wrap the narration that should play over video N with a paired [START][VIDEO N] ... [END][VIDEO N] block — the same shape used for image markers. [VIDEO 1] refers to the first video in custom_videos, [VIDEO 2] to the second, and so on (marker numbers start at 1, not 0). The narration text between the [START] and [END] markers determines the on-screen duration of the user video — the engine cuts to your clip at the START marker and returns to AI-generated visuals at the END marker.

Follow these rules to make sure your video inserts are never silently skipped:

  • Use 1 for your first uploaded video, 2 for the second, and so on. [VIDEO 1] → first item in custom_videos. If you write [VIDEO 3] but only uploaded 2 videos, that video won’t appear.
  • Every video needs a matching [START] and [END] pair. Use the shape [START][VIDEO N] ... narration ... [END][VIDEO N]. Writing a bare [VIDEO N] without the wrappers causes the engine to start the video but never stop it — it will keep playing over all subsequent narration and block any later [VIDEO N] blocks from rendering.
  • Spelling and casing must be exact. Use uppercase VIDEO with a single space before the number — typos like [VEIDO 1] or [VDIEO 1] are silently dropped.
  • Always put whitespace around each marker. Write Welcome. [START][VIDEO 1] Here is the footage. [END][VIDEO 1] Up next. — never glue markers to surrounding words.
  • Place markers at sentence boundaries, not mid-sentence. Put [START][VIDEO N] right before the first word of the sentence the video should cover, and [END][VIDEO N] right after the closing punctuation of the last sentence in that block.
  • Match the narration length to the user video’s original duration. The engine treats the uploaded clip’s natural length as authoritative — [END][VIDEO N] does not force a hard cut. If the clip is longer than the narration wrapped inside the block, the video keeps playing past [END] and the next narration line is delayed until the clip finishes, producing a visible silent gap. Either pre-trim the clip before uploading, or expand the narration inside the block to cover the clip’s full runtime.
  • Each [VIDEO N] appears exactly once. One [START] and one [END] per video — do not reuse the same N later in the script.
  • Do not nest video blocks. [START][VIDEO 1] ... [START][VIDEO 2] ... [END][VIDEO 1] [END][VIDEO 2] is invalid; each block must fully close before the next one opens.
NOTE:Video markers that violate any of these rules are silently dropped — no error, no warning. The position falls back to the engine's normal narration without your uploaded video.
NOTE:Heads up — clip duration vs. narration duration. The user video plays for its full uploaded length regardless of how much narration you wrap between [START][VIDEO N] and [END][VIDEO N]. If the clip is longer than the wrapped narration, the video keeps playing past [END] silently, and the next narration line is held back until the clip ends. To avoid this silent gap, either trim the clip to roughly the spoken duration of the wrapped sentences before uploading, or write enough narration inside the block to cover the clip’s full runtime.

Example — Good shape (use as a template):

video-markers-good-shape.json
{
  "custom_script": "Welcome to today's nature tour. [START][VIDEO 1] Here is a stunning view of the mountain ridge captured from the air. [END][VIDEO 1] Now let us head down to the coast. [START][VIDEO 2] These calming waves close out our journey. [END][VIDEO 2] Thanks for watching.",
  "custom_videos": [
    "https://example.com/mountain-clip.mp4",
    "https://example.com/coastal-clip.mp4"
  ],
  "custom_videos_description": [
    "Aerial view of a mountain ridge",
    "Coastal waves rolling onto a beach"
  ]
}

Each [VIDEO N] appears twice — once with [START] at the beginning of its sentence and once with [END] at the end. Video 1 plays only over “Here is a stunning view… from the air.”, then the engine returns to AI-generated visuals for “Now let us head down to the coast.”, then video 2 plays only over “These calming waves close out our journey.” Marker numbers (1, 2) match the 2-item custom_videos array. To control whether the video plays with its original audio or AI narration, see use_ai_audio_at.

Language Support

44+ languages supported via the narration_language and onscreen_text_language parameters.

LanguageAccepted valuesNote
Englishenglish or enDefault when omitted
Hindihindi or hi
Spanishspanish or es
Frenchfrench or fr
Germangerman or de
Italianitalian or it
Portugueseportuguese or pt
Russianrussian or ru
Japanesejapanese or ja
Koreankorean or ko
Chinese / Mandarinchinese, mandarin, or zhBoth map to zh
Arabicarabic or ar
Dutchdutch or nl
Polishpolish or pl
Turkishturkish or tr
Swedishswedish or sv
Danishdanish or da
Norwegiannorwegian or no
Finnishfinnish or fi
Greekgreek or el
Czechczech or cs
Hungarianhungarian or hu
Romanianromanian or ro
Thaithai or th
Vietnamesevietnamese or vi
Indonesianindonesian or id
Malaymalay or ms
Tamiltamil or ta
Telugutelugu or te
Bengalibengali or bn
Marathimarathi or mr
Gujaratigujarati or gu
Kannadakannada or kn
Malayalammalayalam or ml
Punjabipunjabi or pa
Urduurdu or ur

HTTP Status Codes

Standard HTTP codes returned by all endpoints.

CodeMeaningRecovery
200Successful request (GET, POST, PATCH, or DELETE)Consume response payload
400Bad request (invalid fields or file types)Check request body and field values
401Missing or invalid authenticationVerify the x-api-key header is set and valid
403Plan does not allow requested actionUpgrade plan or contact support
404Video / job not foundVerify identifiers belong to the account
413Uploaded file exceeds 15 MBCompress or split the file before retrying
422Validation failure (bad payload)Inspect detail field in response
429Rate limit exceededBack off and retry with exponential delay
500Unexpected server errorRetry later; contact support if persistent

Error Response Format

All 4xx and 5xx responses return a JSON body with a detail field.

String detail

Most errors return detail as a single human-readable string describing what went wrong. Surface it directly in your UI or logs.

error-response-string.json
{
  "detail": "'canvas_style_variant' is required when using 'golpo_canvas' engine."
}

Array detail

When the request body fails validation, detail is an array of error objects — one per failing field. Each object includes the failing field path (loc) and a human-readable message (msg).

error-response-array.json
{
  "detail": [
    {
      "type": "value_error",
      "loc": ["body"],
      "msg": "Value error, 'custom_videos_description' is required when 'custom_videos' is provided. Provide one description per video (2 expected)."
    }
  ]
}
Usage-Based Plan

API Only Tier

Usage-based pricing with volume discounts

About this plan

This plan is for using Golpo within your program or application. You will not be able to use the Golpo platform to generate videos manually.

This is a usage-based plan with a minimum cost of $200 to enter. Perfect for developers and businesses who need programmatic access to video generation.

Pay only for what you use — volume-based pricing that gets better as you scale.

Platform access (manual video creation via the dashboard) is not included in this plan. If you need both platform + API access, please consider buying an enterprise plan or business plan with an API add-on.

Pricing Rates

Credit Conversion

$1

USD

1 Credit

Golpo credit

ResourceCost
1 min videoVideo generation2 Credits= $2.00

Volume discounts apply at higher usage tiers. Contact us for enterprise rates.

Minimum entry: $200 (200 credits = ~100 minutes of video)