Quick Start

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

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

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/v1/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"; // Replace with your Golpo API key

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

const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const response = await fetch(`${BASE_URL}/api/v1/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/v1/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}"; // 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/v1/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/v1/videos/{video_id}

Retrieve metadata for a single video by ID.

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/v1/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/v1/videos/{video_id}

Update video metadata. Only 'title' and 'is_public' 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" };

const response = await fetch(`${BASE_URL}/api/v1/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/v1/videos/{video_id}

Delete a generated video.

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/v1/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>

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

Poll the status endpoint to track generation progress.

job-status.js
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const JOB_ID = "job-id";

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

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

Request Body

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

Either prompt or audio_clip is required. All other parameters are optional.
ParameterTypeDefaultRequiredDescription
promptstringRequired
Main prompt/script for the video
upload_urlsarray[string]NoneOptional
URLs of uploaded documents/images or local file paths. Use /upload-file endpoint to get URLs, or provide local paths directly
voice_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".
just_return_scriptbooleanfalseOptional
Only generate script, don't create video/podcast
NOTE:This parameter will not work with audio_clip (own-narration mode). Requests will follow the standard own_narration workflow regardless of the parameter value.
new_scriptstringNoneOptional
Use your own script instead of generating one. Useful for creating a video or podcast from an existing script.
stylestring"solo-female-3"Optional
Content/Narration Style
Accepted values: "solo-female-3" (Female 1, default), "solo-female-4" (Female 2), "solo-male-3" (Male 1), "solo-male-4" (Male 2).
use_colorbooleantrueOptional
Enable color video generation
languagestring"en"Optional
Language code (e.g., 'en', 'es')
display_languagestringNoneOptional
Language for on-screen text in the video (e.g., 'English', 'Hindi', 'French'). Useful when the displayed text should differ from the narration language. Defaults to the value of language if omitted.
Example: language: "Hindi", display_language: "English" — the narrator speaks in Hindi while all on-screen text, titles, and labels are shown in English.
NOTE:This parameter only works with Golpo Canvas. To use it, set use_2_0_style: true.
language_variantsarray[string]NoneOptional
Generate additional language versions of the video alongside the primary `language`. Provide an array of supported languages (e.g. ['Spanish', 'French', 'hi']). A separate video will be generated for each specified language.
Each language version is billed as a separate render. For example, a 2-minute video with 2 additional languages is billed as 3 renders × 2 minutes. Duplicate languages, including the primary language, are not allowed and will return a 400 error.
NOTE:All language variants use the same prompt, duration, voice, and visual settings. Only the language changes for each variant.
variant_visuals_modestring"shared"Optional
Controls how visuals are generated across language variants. `shared` (default) reuses the primary video's visuals across all language variants. `per_language` generates separate visuals for each language variant.
bg_musicstringNoneOptional
Background music track
video_typestring"long"Optional
Video type: 'long' (horizontal) or 'short' (vertical)
audio_onlybooleanfalseOptional
If true, generate podcast/audio only (no video)
timingstringNoneOptional
Video/Podcast timing/duration in minutes (as a string) or 'auto' to let the system determine duration. Accepted values: '0.25', '0.5', '1', '2', '4', '8', '10', '15', 'auto'.
Examples: timing: "0.25" (15s), timing: "0.5" (30s), timing: "1" (1 min), timing: "2" (2 min), timing: "4" (4 min), timing: "8" (8 min), timing: "10" (10 min), timing: "15" (15 min), timing: "auto" (system-determined).
"15" is only available on the Enterprise Custom plan. Other plans receive a 403 when requesting 15-minute videos. Contact support@golpoai.com to upgrade.
include_watermarkbooleanfalseOptional
Include watermark in video
logostringNoneOptional
Custom logo for branding. Provide a URL (via /upload-file) or a local file path
logo_placementstring"tl"Optional
Controls where the logo is placed on the video when logo is provided and include_watermark is true. Valid values: 'tl' (top-left, default), 'tr' (top-right), 'bl' (bottom-left), 'br' (bottom-right).
video_instructionsstring""Optional
Visual instructions to guide how the video looks.
Examples: "Show more graphs and charts", "Include more stock footage", "Use cinematic transitions", "Dark moody aesthetic with neon accents".
use_lineart_2_stylestring"false"Optional
Golpo Sketch style selector. "false" (Classic, default), "true" (Improved), "advanced" (Formal), "whiteboard" (Dry Erase), "modern_minimal" (Professional Clean), "storytelling" (Crayon), "creative" (Creative), "vox" (Infographics), "chalkboard_black_on_white" (Chalkboard Black on White).
NOTE:Do not use this when use_2_0_style is enabled (Golpo Canvas).
audio_clipstringNoneOptional
URL to audio/video file or local file path to use instead of generating script and TTS. Use /upload-file endpoint to get URLs, or provide local paths directly.
Useful for generating a video from your own existing audio or video narration.
user_audio_in_videoarray[integer]NoneOptional
List of video numbers that should use AI-generated narration audio instead of their original audio (e.g., [1, 3] means videos 1 and 3 get AI narration; unlisted user videos keep their original audio)
Only applies when user_videos is provided. Videos in this list will use AI-generated audio instead of original audio. Videos not in this list keep their original audio. If omitted or empty, all user videos retain their original audio.
user_imagesarray[string]NoneOptional
List of image URLs or local file paths to insert into the video. Use /upload-file endpoint to get URLs, or provide local paths directly
user_images_descriptionsarray[string]NoneOptional
List of descriptions for user images (one per image)
Helps the AI understand what each image contains and where to place it in the video for the best visual context.
use_as_isarray[boolean]NoneOptional
List of booleans indicating whether to use images as-is without AI processing (one per image)
When true, the original image is used directly with no AI animation. When false, the AI generates an animated version of the image for the video.
skip_animationarray[boolean]NoneOptional
List of booleans indicating whether to skip animation for images (one per image)
When true, the image appears as a static frame with no drawing or transition animation. When false, the image gets animated transitions.
user_videosarray[string]NoneOptional
List of video URLs or local file paths to insert into the video. Use /upload-file endpoint to get URLs, or provide local paths directly
user_videos_descriptionarray[string]NoneOptional
List of descriptions for user videos (one per video)
Provides context to the AI about each video's content, helping it decide where and how to place each clip in the generated video.
is_publicbooleanfalseOptional
Whether the video should be public (true) or private (false). Public videos appear in the Golpo video gallery.
use_2_0_stylebooleanfalseOptional
Enable Golpo Canvas (Earlier Golpo 2.0) style video generation.
NOTE:Use image_style to set the visual style for Golpo Canvas — if not provided, the default style will be used. Do not pass use_lineart_2_style when this is enabled.
image_stylestringNoneOptional
Image style for Golpo Canvas (2.0): 'chalkboard_white' (white chalk on black), 'chalkboard_black_on_white' (black ink on white), 'neon', 'whiteboard', 'modern_minimal', 'playful', 'technical', 'editorial', 'marker', or 'vox' (Illustrations).
NOTE:Only applicable for Golpo Canvas (use_2_0_style). Do not use with Golpo Sketch.
input_imagesarray[string]NoneOptional
List of input image URLs or local file paths for Golpo Canvas. Use this when you want to solve a problem visually or base the video on specific images — the video will be generated around the provided images.
NOTE:Only applicable for Golpo Canvas (use_2_0_style). Do not use with Golpo Sketch.
pen_stylestringNoneOptional
Pen cursor style: 'stylus', 'marker', or 'pen'.
NOTE:Only applicable for Golpo Canvas (use_2_0_style). Do not use with Golpo Sketch.
show_pencil_cursorbooleanfalseOptional
Show a pencil cursor during sketch animations. If enabled, set pen_style to choose the cursor appearance.
NOTE:Only applicable for Golpo Canvas (use_2_0_style). Do not use with Golpo Sketch.
pacingstring"normal"Optional
Pacing level: 'normal' (15s max per frame), 'fast' (10s max per frame). Works with both Golpo Sketch and Golpo Canvas.

Parameter Groups

Parameters organized by purpose for easier discovery.

Content

promptaudio_clipnew_scriptupload_urlsstyleinput_images

Audio

bg_musicuser_audio_in_video

Voice

voice_instructionslanguagedisplay_languagelanguage_variantsvariant_visuals_mode

Visual

use_coloruse_lineart_2_styleuse_2_0_styleimage_styleuser_imagesuser_images_descriptionsuse_as_isskip_animationpen_styleshow_pencil_cursor

Video Assets

user_videosuser_videos_description

Duration

timingvideo_typeaudio_onlypacing

Branding

include_watermarklogologo_placement

Workflow

video_instructionsjust_return_scriptis_public

Upload File

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

NOTE:Maximum file size is 15 MB. Requests with larger files will be rejected.
NOTE:Document URLs are single-use. When you pass a document URL (PDF, DOCX, TXT, etc.) from /upload-file into upload_urls, 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 presigned URL)

Documents

PDF · DOCX · PPTX · TXT

Audio

MP3 · WAV · M4A · OGG

Video

MP4 · MOV · AVI · MKV

Images

JPG · PNG · GIF · WEBP

upload-response.json
// Response from POST /api/v1/videos/upload-file
{
  "upload_url":   "https://...",  // Presigned PUT URL — upload the file here
  "file_url":     "https://...",  // Pass this into /generate
  "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/v1/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 file to 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

User Assets

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

NOTE:user_images and user_videos accept the file_url returned by /upload-file. local_path is also accepted for server-side usage. Descriptions are strongly recommended for best visual results.
generate-with-user-assets.js
const API_KEY = "api-key";
const BASE_URL = "{BASE_URL}";

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

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

  const { file_url } = await response.json();
  return file_url;
}

// Step 1: Upload images
const image1Url = await uploadFile(imageFile1);
const image2Url = await uploadFile(imageFile2);

// Step 2: Upload video
const video1Url = await uploadFile(videoFile1);

// Step 3: Generate video with user assets
const generatePayload = {
  prompt: "Create a product showcase video",
  user_images: [image1Url, image2Url],
  user_images_descriptions: [
    "Product front view with logo",
    "Product in use by customer"
  ],
  use_as_is: [false, false], // Process both images with AI
  skip_animation: [false, true], // Animate first image, skip animation for second
  user_videos: [video1Url],
  user_videos_description: ["Customer testimonial video"],
  video_type: "long",
  include_watermark: false
};

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

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

Local Paths

Pass absolute or relative file paths directly from server-side environments — no upload step required.

NOTE:Local paths are only supported in server-side environments where the API server has filesystem access.
generate-with-local-paths.js
import fetch from "node-fetch";
import path from "path";

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

// Example: Using local file paths (server-side only)
// Paths are relative to where the script runs or absolute paths
const payload = {
  prompt: "Create a comprehensive product demo video",
  upload_urls: [
    "./documents/product-spec.pdf",        // Relative path (Linux/Mac/Windows)
    "C:\\Users\\Documents\\brief.docx",  // Windows absolute path
    "/home/user/documents/slides.pptx",    // Linux/Mac absolute path
    "~/Documents/research.txt"             // Home directory expansion (Linux/Mac)
  ],
  logo: "./assets/company-logo.png",
  user_images: [
    "./images/product-front.jpg",
    "./images/product-in-use.jpg"
  ],
  user_images_descriptions: [
    "Product front view with branding",
    "Product being used by customer"
  ],
  use_as_is: [false, false],
  skip_animation: [false, true],
  style: "solo-female-3",
  bg_music: "engaging",
  video_type: "long",
  include_watermark: false,
  use_color: true,
  language: "en",
  timing: "4"
};

const response = await fetch(`${BASE_URL}/api/v1/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);

Note: Local paths work when the API server can access these files. For remote clients, use /upload-file endpoint first.

Language Quickstarts

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

Upload Workflow

Full pattern: upload supporting files, then generate a video in any language.

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

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

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

  const { file_url } = await response.json();
  return file_url;
}

// Step 2: Upload all files and get URLs
const fileInput = document.querySelector('#uploads');
const uploadPromises = Array.from(fileInput.files).map(file => uploadFile(file));
const uploadUrls = await Promise.all(uploadPromises);

// Step 3: Generate video with uploaded files
const generatePayload = {
  prompt: 'Summarize this slide deck for executives',
  upload_urls: uploadUrls,
  style: 'solo-female-3',
  language: 'Spanish'
};

const response = await fetch(`${BASE_URL}/api/v1/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

use_lineart_2_style

Whiteboard-style sketch animation with pacing control — normal (15s/frame) or fast (10s/frame).

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

const API_KEY = "api-key"; // Replace with your Golpo API key
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

const payload = {
  prompt: "Explain how neural networks work",
  use_lineart_2_style: "true", // Options: "advanced" (Formal), "whiteboard" (Dry Erase), "modern_minimal" (Professional Clean), "storytelling" (Crayon)
  pacing: "normal",            // "normal" (15s max) or "fast" (10s max)
  bg_music: "engaging",
  include_watermark: false
};

const response = await fetch(`${BASE_URL}/api/v1/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);

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

Golpo Canvas

use_2_0_style

Canvas-based video with rich image styles (neon, whiteboard, editorial…) and optional pencil cursor.

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

const API_KEY = "api-key"; // Replace with your Golpo API key
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

const payload = {
  prompt: "Create a product overview video",
  use_2_0_style: true,
  image_style: "modern_minimal", // "neon", "whiteboard", "modern_minimal", "playful", "technical", "editorial"
  include_watermark: false
};

const response = await fetch(`${BASE_URL}/api/v1/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);

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.

Display Language

display_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.

Note: This parameter only works with Golpo Canvas. To use it, set use_2_0_style: true.
display-language.js
import fetch from "node-fetch";

const API_KEY = "api-key"; // Replace with your Golpo API key
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

// The narrator speaks in Hindi, but all on-screen text,
// titles, and labels are displayed in English.
const payload = {
  prompt: "Explain the water cycle",
  language: "Hindi",         // Voice / narration language
  display_language: "English", // Language for on-screen text & visuals
  style: "solo-female-4",
  image_style: "editorial",
  use_2_0_style: true,
  include_watermark: false
};

const response = await fetch(`${BASE_URL}/api/v1/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);

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

Multi-Language Variants

Generate multiple language versions of the same video in a single request. Set the primary language and add extra languages in language_variants. The response returns the generated video IDs in variant_video_ids.

The table below shows the maximum number of languages you can generate per request for each timing value — both the total (primary + variants) and how many you can list in language_variants.

timingMax languagesprimary + variantsMax language_variants
0.250.51
109
2
54
4
32
81015
21
auto
21

2–10

Max languages

depends on timing (≤1 min: 10; 2 min: 5; 4 min: 3; ≥8 min: 2)

1

API request

generates a separate render for each provided language_variants value

2 modes

Visuals

shared (default) reuses the primary's visuals across every language · per_language regenerates visuals separately for each language

shared (default)

Same visuals for every variant — only the audio changes per language.

  • All variants use the primary video's visuals

per_language

Generate separate visuals for each language variant, with on-screen text in that language.

  • Podcasts (audio_only: true) always use this mode, since there are no visuals to share

Variant status lifecycle

queued_for_variantgeneratingcompleted/failedPoll GET /api/v1/videos/status/{video_id}
NOTE:Billing. Each variant bills as a full render — a 2-minute primary + 2 extra languages bills as 3 × 2-minute renders. Duplicate languages or duplicates of the primary are rejected with 400.

Example payload for each visuals mode

shared.json
{
  "prompt": "Explain photosynthesis",
  "language": "english", // Primary language
  "language_variants": ["spanish", "french"],
  // Uses the same visuals across all language variant videos
  "variant_visuals_mode": "shared"
}
per_language.json
{
  "prompt": "Explain photosynthesis",
  "language": "english", // Primary language
  "language_variants": ["spanish", "french"],
  // Generate separate visuals for each language
  "variant_visuals_mode": "per_language"
}

Multi-Language Variants

language_variants

Submit one prompt; receive one video per language. The example below renders English + Spanish + French in shared visuals mode.

multi-language-variants.js
import fetch from "node-fetch";

const API_KEY = "api-key"; // Replace with your Golpo API key
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

// Generate the same video in English (primary) + Spanish + French.
// Each variant is fully translated narration; "shared" visuals mode reuses
// the primary's frames so it costs less and renders faster.
const payload = {
  prompt: "Explain how photosynthesis works in simple terms.",
  language: "English",         // Primary narration language
  display_language: "English",
  style: "solo-female-3",
  image_style: "playful",
  use_2_0_style: true,
  timing: "4",

  // Extra languages (max depends on timing — 2 here at timing "4")
  language_variants: ["Spanish", "French"],
  variant_visuals_mode: "shared", // "shared" or "per_language"
};

const response = await fetch(`${BASE_URL}/api/v1/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("Primary job_id   :", data.job_id);
console.log("Variant video IDs:", data.variant_video_ids); // parallel to language_variants

// Poll the primary AND each variant independently.
for (const id of [data.job_id, ...data.variant_video_ids]) {
  const s = await fetch(`${BASE_URL}/api/v1/videos/status/${id}`, {
    headers: { "x-api-key": API_KEY },
  }).then(r => r.json());
  console.log(id, "→", s.status, s.video_url ?? "");
}

Run with: node --env-file=.env multi-language-variants.js

Generate Video

POST /api/v1/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"; // Replace with your Golpo API key
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key

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

const response = await fetch(`${BASE_URL}/api/v1/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

List Videos

GET /api/v1/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}"; // 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/v1/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 Video

GET /api/v1/videos/{video_id}

Retrieve metadata for a single video by ID.

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/v1/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/v1/videos/{video_id}

Update video metadata. Only 'title' and 'is_public' 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" };

const response = await fetch(`${BASE_URL}/api/v1/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/v1/videos/{video_id}

Delete a generated video.

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/v1/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/v1/videos/status/{job_id}

Poll the status endpoint to track generation progress.

job-status.js
const BASE_URL = "{BASE_URL}"; // You will receive this when creating an API key
const JOB_ID = "job-id";

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

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

Timing

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

ValueDuration
0.2515 seconds
0.530 seconds
11 minute
22 minutes
44 minutes
88 minutesBeta
1010 minutesBeta
1515 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 support@golpoai.com to upgrade.
When to use "auto" timing: Use auto timing when the content complexity should determine the video length. This is especially useful for problem-solving — for example, if you pass a math or physics problem via input_images, the engine will analyze the complexity and generate a script of the appropriate length (e.g., a simple problem may produce a 1-minute video, while a complex one may need 4+ minutes to explain thoroughly).

Example: Auto Timing with Problem Solving

Pass a problem image via input_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",
  "input_images": [
    "https://your-bucket.s3.amazonaws.com/calculus-problem.png"
  ],
  "use_2_0_style": true,
  "image_style": "whiteboard",
  "timing": "auto",
  "style": "solo-male-3",
  "video_type": "long"
}

Video Type

Controls the video aspect ratio and orientation.

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

short

1024×1536 px

16:9

long (default)

1536×1024 px

Style & Voices

The style parameter controls both script format and voice selection.

Voice Selection

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

Background Music

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

bg_music 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 an instructions in the voice_instructions field to guide voice generation. The AI will adjust accent, tone, pace, and delivery accordingly.

voice-instructions-example.json
{
  "prompt": "Explain quantum computing basics",
  "voice_instructions": "Speak in a warm British accent with a calm, professorial tone. Pause slightly between key concepts for emphasis.",
  "style": "solo-male-3"
}

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 an instructions in the video_instructions field to guide the visual generation. The AI will adjust scene composition, imagery, and visual style accordingly.

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

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

Inserting Images in Script

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

When you supply your own script via new_script and also upload user_images, wrap a sentence in paired markers to control where each image appears. [IMAGE 1] refers to the first image in user_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 user_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
{
  "new_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.",
  "user_images": [
    "https://example.com/beach.png",
    "https://example.com/mountain.png"
  ],
  "user_images_descriptions": [
    "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 user_images array.

You can also use other image control parameters alongside the markers: use_as_is (boolean array — skip AI processing and place the image untouched) and skip_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
{
  "new_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]"
{
  "new_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
{
  "new_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"
{
  "new_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 new_script so your uploaded user_videos play for the right span of narration.

When you supply your own script via new_script and also upload user_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 user_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 user_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
{
  "new_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.",
  "user_videos": [
    "https://example.com/mountain-clip.mp4",
    "https://example.com/coastal-clip.mp4"
  ],
  "user_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 user_videos array. To control whether the video plays with its original audio or AI narration, see user_audio_in_video.

Golpo Sketch Styles

The use_lineart_2_style parameter controls the whiteboard sketch animation style.

ValueStyle NameDescription
"false"Classic (Default)Original Golpo Sketch — classic whiteboard line-art animation
"true"Improved BetaImproved line-art with cleaner strokes and a more polished look
"advanced"FormalAdvanced sketch generation with higher detail and refined aesthetics
"whiteboard"Dry EraseClean whiteboard presentation style with smooth marker-like strokes
"modern_minimal"Professional CleanModern minimalist design with clean geometric shapes and indigo accent
"storytelling"CrayonHand-drawn crayon and colored pencil illustration with bold ink outlines
"creative"CreativeAfter Skool whiteboard-marker variant with bold colorful strokes
"vox"InfographicsVox-style editorial explainer with paper-textured infographic look
"chalkboard_black_on_white"Chalkboard (Black on White)Black ink on a white background
Do not combine use_lineart_2_style with use_2_0_style. Use one or the other.

Golpo Canvas Styles

Enable Golpo Canvas with use_2_0_style and configure image_style and pen_style.

Set use_2_0_style: true to enable Golpo Canvas. Then use image_style to set the visual look and optionally pen_style to add a drawing cursor effect.

Pen Style

ValueDescription
"none"No pen cursor (Default)
"stylus"Thin stylus pen cursor
"marker"Thick marker cursor
"pen"Classic pen cursor
NOTE:pen_style and image_style are only applicable for Golpo Canvas (use_2_0_style: true). Do not use with Golpo Sketch.

Image Style

Controls the visual style of Golpo Canvas videos. Only applicable when use_2_0_style is true.

ValueLabelDescription
"chalkboard_white"Chalkboard (White on Black)White chalk on a black background (Default)
"chalkboard_black_on_white"Chalkboard (Black on White)Black ink on a white background
"neon"Chalkboard ColorColorful neon chalkboard style
"whiteboard"WhiteboardClean whiteboard illustrations
"modern_minimal"Modern MinimalSleek, minimal modern aesthetic
"playful"PlayfulFun, colorful playful illustrations
"technical"TechnicalTechnical diagram style
"editorial"EditorialMagazine/editorial illustration style
"marker"SharpieBold marker/sharpie drawn style
"vox"IllustrationsVox-style editorial explainer with paper-textured infographic look
golpo-canvas-example.json
{
  "prompt": "How solar panels convert sunlight to electricity",
  "use_2_0_style": true,
  "image_style": "modern_minimal",
  "pen_style": "stylus",
  "timing": 2
}

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 authenticationRefresh token / validate API key
403Plan does not allow requested actionUpgrade plan or contact support
404Video / job not foundVerify identifiers belong to the account
422Validation failure (bad payload)Inspect detail array 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.

Schema validation — invalid parameter type or value returns detail as a structured array (one entry per failed field).

validation-error.json
{
  "detail": [
    {
      "type": "literal_error",
      "loc": ["body", "style"],
      "msg": "Input should be 'solo-female-3', 'solo-female-4', 'solo-male-3' or 'solo-male-4'",
      "input": "formal",
      "ctx": {
        "expected": "'solo-female-3', 'solo-female-4', 'solo-male-3' or 'solo-male-4'"
      }
    }
  ]
}

Application errors — auth, missing files, etc. return detail as a flat string.

error.json
{
  "detail": "File not found at local path: /tmp/missing.png."
}

Language Support

44+ languages supported via the language parameter.

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

API Only Tier

Usage-based pricing with volume discounts.

This plan is for using Golpo within your program or application. You won't be able to generate videos manually via the Golpo dashboard.

Usage-based, with a minimum commitment of $200. Built for developers and businesses that need programmatic access at scale.

Platform access isn't included. For both platform and API access, consider an enterprise plan or a business plan with the API add-on.

Credit
$1 = 1 credit
1 min video
2 credits · $2.00
Minimum entry
$200 · ~100 min

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