Create Generation
curl --request POST \
--url https://veogen.studio/api/v1/generations \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"aspect_ratio": "<string>",
"resolution": "<string>",
"duration": 123,
"mode": "<string>",
"style": "<string>",
"image_urls": [
{}
],
"video_urls": [
{}
],
"audio_urls": [
{}
],
"watermark": true,
"private": true
}
'import requests
url = "https://veogen.studio/api/v1/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"aspect_ratio": "<string>",
"resolution": "<string>",
"duration": 123,
"mode": "<string>",
"style": "<string>",
"image_urls": [{}],
"video_urls": [{}],
"audio_urls": [{}],
"watermark": True,
"private": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
aspect_ratio: '<string>',
resolution: '<string>',
duration: 123,
mode: '<string>',
style: '<string>',
image_urls: [{}],
video_urls: [{}],
audio_urls: [{}],
watermark: true,
private: true
})
};
fetch('https://veogen.studio/api/v1/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://veogen.studio/api/v1/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'aspect_ratio' => '<string>',
'resolution' => '<string>',
'duration' => 123,
'mode' => '<string>',
'style' => '<string>',
'image_urls' => [
[
]
],
'video_urls' => [
[
]
],
'audio_urls' => [
[
]
],
'watermark' => true,
'private' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://veogen.studio/api/v1/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://veogen.studio/api/v1/generations")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://veogen.studio/api/v1/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"status": "<string>",
"model": "<string>",
"type": "<string>",
"prompt": "<string>",
"parameters": {},
"output": {},
"error": {},
"created_at": "<string>",
"completed_at": {}
},
"price_usd": 123
}Generations
Create Generation
Submit a prompt (and optional image) to generate a video or image.
POST
/
api
/
v1
/
generations
Create Generation
curl --request POST \
--url https://veogen.studio/api/v1/generations \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"prompt": "<string>",
"aspect_ratio": "<string>",
"resolution": "<string>",
"duration": 123,
"mode": "<string>",
"style": "<string>",
"image_urls": [
{}
],
"video_urls": [
{}
],
"audio_urls": [
{}
],
"watermark": true,
"private": true
}
'import requests
url = "https://veogen.studio/api/v1/generations"
payload = {
"model": "<string>",
"prompt": "<string>",
"aspect_ratio": "<string>",
"resolution": "<string>",
"duration": 123,
"mode": "<string>",
"style": "<string>",
"image_urls": [{}],
"video_urls": [{}],
"audio_urls": [{}],
"watermark": True,
"private": True
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
prompt: '<string>',
aspect_ratio: '<string>',
resolution: '<string>',
duration: 123,
mode: '<string>',
style: '<string>',
image_urls: [{}],
video_urls: [{}],
audio_urls: [{}],
watermark: true,
private: true
})
};
fetch('https://veogen.studio/api/v1/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://veogen.studio/api/v1/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'prompt' => '<string>',
'aspect_ratio' => '<string>',
'resolution' => '<string>',
'duration' => 123,
'mode' => '<string>',
'style' => '<string>',
'image_urls' => [
[
]
],
'video_urls' => [
[
]
],
'audio_urls' => [
[
]
],
'watermark' => true,
'private' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://veogen.studio/api/v1/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://veogen.studio/api/v1/generations")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://veogen.studio/api/v1/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"prompt\": \"<string>\",\n \"aspect_ratio\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"mode\": \"<string>\",\n \"style\": \"<string>\",\n \"image_urls\": [\n {}\n ],\n \"video_urls\": [\n {}\n ],\n \"audio_urls\": [\n {}\n ],\n \"watermark\": true,\n \"private\": true\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "<string>",
"status": "<string>",
"model": "<string>",
"type": "<string>",
"prompt": "<string>",
"parameters": {},
"output": {},
"error": {},
"created_at": "<string>",
"completed_at": {}
},
"price_usd": 123
}Request
string
required
Bearer YOUR_TOKENstring
required
The model slug to use. See Models for all available slugs.Video models:
grok-video-1, veo-3.1-fast, sora-2, sora-2-pro, seedance-2.0, seedance-2.0-fastImage models: gpt-4o-image, seedream-4.5, seedream-5.0-lite, nano-banana-pro, nano-banana-2string
required
The text prompt describing what to generate. Maximum 2,000 characters.
string
The output aspect ratio. Defaults to the model’s first supported ratio.Common values:
16:9, 9:16, 1:1, 4:3string
Output resolution. Only applicable to models that support multiple resolutions.Video:
480p, 720p, 1080p, 4k (model-dependent)Image: 0.5K, 1K, 2K, 4K (model-dependent)Resolution multipliers increase the price. A
4k video on Veo 3.1 Fast costs 3× the base price. Seedance 2.0 720p costs ~2.15× the 480p rate. See Pricing.integer
Duration in seconds. Only for video models. Accepted values depend on the model:
grok-video-1: 6–30 seconds (billed per second at $0.03/s)sora-2: 10 or 15 secondssora-2-pro: 10, 15, or 25 secondsseedance-2.0: 4–15 seconds (billed per second at 0.132/sfor480p,0.284/s for 720p)seedance-2.0-fast: 4–15 seconds (billed per second at 0.1056/sfor480p,0.2288/s for 720p)
Seedance models have reduced pricing when a reference video is provided via
video_urls. See the video_urls parameter below.string
Generation mode. Model-specific:
grok-video-1:custom,normal,fun,spicyveo-3.1-fast:frame(image-to-video),ingredient(reference images)
string
Visual style preset. Only for
sora-2 and sora-2-pro.Values: none, thanksgiving, comic, news, selfie, nostalgic, animearray
Array of publicly accessible image URLs to use as input. Maximum count is model-dependent (up to 14 for image models).For video models, the first URL is used as the first frame. Additional images are treated as reference images.
array
Array of publicly accessible video URLs to use as reference input. Up to 3 URLs. Seedance 2.0 / 2.0 Fast only.When provided, the generation uses the reference video to guide output, and the price is discounted:
Supported formats: MP4, WebM, MOV.
| Model | 480p | 720p |
|---|---|---|
seedance-2.0 | 0.08/s(vs0.132/s) | 0.1712/s(vs0.284/s) |
seedance-2.0-fast | 0.0632/s(vs0.1056/s) | 0.136/s(vs0.2288/s) |
array
Array of publicly accessible audio URLs to use as reference input. Up to 3 URLs. Seedance 2.0 / 2.0 Fast only.Supported formats: MP3, WAV, M4A, OGG.
boolean
Whether to add a watermark to the output. Defaults to
false. Only for sora-2 and sora-2-pro.boolean
Whether the generation should be private. Only for
sora-2 and sora-2-pro.Response 201 Created
object
Show Generation object
Show Generation object
string
UUID of the generation. Use this to poll for status.
string
pending | processing | completed | failedstring
The model slug used.
string
video | imagestring
The prompt submitted.
object
Resolved parameters (aspect_ratio, duration, resolution, mode).
object | null
null until status is completed. Then contains url and content_type.string | null
Error message. Only present when
status is failed.string
ISO 8601 timestamp.
string | null
ISO 8601 timestamp when generation finished.
number
The exact USD amount charged for this generation.
Error Responses
{
"error": "Insufficient balance.",
"message": "This generation costs $0.30. Your balance is $0.05.",
"required": 0.30,
"balance": 0.05
}
{
"message": "The model field is required.",
"errors": {
"model": ["The model field is required."]
}
}
Examples
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-image",
"prompt": "A serene mountain landscape at sunset, photorealistic",
"aspect_ratio": "16:9"
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-fast",
"prompt": "Ocean waves crashing on a rocky shore, dramatic storm clouds",
"aspect_ratio": "16:9",
"resolution": "1080p"
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "grok-video-1",
"prompt": "A cat wearing sunglasses skateboarding down a city street",
"aspect_ratio": "16:9",
"duration": 10,
"resolution": "720p",
"mode": "fun"
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "Aerial drone shot over a misty mountain lake at sunrise",
"aspect_ratio": "21:9",
"duration": 10,
"resolution": "720p",
"generate_audio": true
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-fast",
"prompt": "A hummingbird hovering near a tropical flower, macro shot",
"aspect_ratio": "16:9",
"duration": 5,
"resolution": "480p"
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "Transform the input video into a cinematic slow-motion sequence",
"duration": 10,
"resolution": "480p",
"video_urls": ["https://example.com/reference-video.mp4"]
}'
curl -X POST https://veogen.studio/api/v1/generations \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1-fast",
"prompt": "Camera slowly zooms out to reveal the full panoramic view",
"aspect_ratio": "16:9",
"image_urls": ["https://example.com/landscape.jpg"]
}'
import requests
import time
token = "YOUR_TOKEN"
base_url = "https://veogen.studio/api/v1"
headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
# Submit generation
res = requests.post(f"{base_url}/generations", headers=headers, json={
"model": "gpt-4o-image",
"prompt": "A futuristic cityscape at night",
"aspect_ratio": "16:9"
})
data = res.json()
gen_id = data["data"]["id"]
print(f"Submitted: {gen_id} — charged ${data['price_usd']}")
# Poll until complete
while True:
res = requests.get(f"{base_url}/generations/{gen_id}", headers=headers)
generation = res.json()["data"]
if generation["status"] == "completed":
print(f"Done! URL: {generation['output']['url']}")
break
elif generation["status"] == "failed":
print(f"Failed: {generation['error']}")
break
time.sleep(3)
const fetch = require("node-fetch");
const token = "YOUR_TOKEN";
const baseUrl = "https://veogen.studio/api/v1";
const headers = {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
Accept: "application/json",
};
async function generate() {
const res = await fetch(`${baseUrl}/generations`, {
method: "POST",
headers,
body: JSON.stringify({
model: "gpt-4o-image",
prompt: "A futuristic cityscape at night",
aspect_ratio: "16:9",
}),
});
const { data, price_usd } = await res.json();
console.log(`Submitted ${data.id} — charged $${price_usd}`);
// Poll for result
while (true) {
await new Promise((r) => setTimeout(r, 3000));
const poll = await fetch(`${baseUrl}/generations/${data.id}`, { headers });
const { data: gen } = await poll.json();
if (gen.status === "completed") {
console.log("Done!", gen.output.url);
break;
}
if (gen.status === "failed") {
console.error("Failed:", gen.error);
break;
}
}
}
generate();