Generate Video
curl --request POST \
--url https://api.pictory.ai/pictoryapis/v1/aistudio/videos \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"prompt": "<string>",
"model": "<string>",
"aspectRatio": "<string>",
"duration": "<string>",
"firstFrameImageUrl": "<string>",
"extendVideoUrl": "<string>",
"referenceImageUrls": [
{}
],
"webhook": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v1/aistudio/videos"
payload = {
"prompt": "<string>",
"model": "<string>",
"aspectRatio": "<string>",
"duration": "<string>",
"firstFrameImageUrl": "<string>",
"extendVideoUrl": "<string>",
"referenceImageUrls": [{}],
"webhook": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
prompt: '<string>',
model: '<string>',
aspectRatio: '<string>',
duration: '<string>',
firstFrameImageUrl: '<string>',
extendVideoUrl: '<string>',
referenceImageUrls: [{}],
webhook: '<string>'
})
};
fetch('https://api.pictory.ai/pictoryapis/v1/aistudio/videos', 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://api.pictory.ai/pictoryapis/v1/aistudio/videos",
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([
'prompt' => '<string>',
'model' => '<string>',
'aspectRatio' => '<string>',
'duration' => '<string>',
'firstFrameImageUrl' => '<string>',
'extendVideoUrl' => '<string>',
'referenceImageUrls' => [
[
]
],
'webhook' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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://api.pictory.ai/pictoryapis/v1/aistudio/videos"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pictory.ai/pictoryapis/v1/aistudio/videos")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v1/aistudio/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "4a09edf9-d071-4847-bda5-8dea913d80fe"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "prompt",
"message": "\"prompt\" is required"
}
]
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "extendVideoUrl",
"message": "\"extendVideoUrl\" is not allowed"
}
]
}
{
"message": "Unauthorized"
}
{
"message": "Internal Server Error"
}
AI Studio
Generate Video
Generate an AI video from a text prompt using a selection of AI video models
POST
/
pictoryapis
/
v1
/
aistudio
/
videos
Generate Video
curl --request POST \
--url https://api.pictory.ai/pictoryapis/v1/aistudio/videos \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"prompt": "<string>",
"model": "<string>",
"aspectRatio": "<string>",
"duration": "<string>",
"firstFrameImageUrl": "<string>",
"extendVideoUrl": "<string>",
"referenceImageUrls": [
{}
],
"webhook": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v1/aistudio/videos"
payload = {
"prompt": "<string>",
"model": "<string>",
"aspectRatio": "<string>",
"duration": "<string>",
"firstFrameImageUrl": "<string>",
"extendVideoUrl": "<string>",
"referenceImageUrls": [{}],
"webhook": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
prompt: '<string>',
model: '<string>',
aspectRatio: '<string>',
duration: '<string>',
firstFrameImageUrl: '<string>',
extendVideoUrl: '<string>',
referenceImageUrls: [{}],
webhook: '<string>'
})
};
fetch('https://api.pictory.ai/pictoryapis/v1/aistudio/videos', 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://api.pictory.ai/pictoryapis/v1/aistudio/videos",
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([
'prompt' => '<string>',
'model' => '<string>',
'aspectRatio' => '<string>',
'duration' => '<string>',
'firstFrameImageUrl' => '<string>',
'extendVideoUrl' => '<string>',
'referenceImageUrls' => [
[
]
],
'webhook' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$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://api.pictory.ai/pictoryapis/v1/aistudio/videos"
payload := strings.NewReader("{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pictory.ai/pictoryapis/v1/aistudio/videos")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v1/aistudio/videos")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"prompt\": \"<string>\",\n \"model\": \"<string>\",\n \"aspectRatio\": \"<string>\",\n \"duration\": \"<string>\",\n \"firstFrameImageUrl\": \"<string>\",\n \"extendVideoUrl\": \"<string>\",\n \"referenceImageUrls\": [\n {}\n ],\n \"webhook\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "4a09edf9-d071-4847-bda5-8dea913d80fe"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "prompt",
"message": "\"prompt\" is required"
}
]
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "extendVideoUrl",
"message": "\"extendVideoUrl\" is not allowed"
}
]
}
{
"message": "Unauthorized"
}
{
"message": "Internal Server Error"
}
Overview
The Generate Video API creates an AI-generated video based on a text prompt. You can choose from multiple AI video models, specify an aspect ratio and duration, and optionally provide a first frame image, a video to extend, or reference images to guide the output. The API returns a job ID that you can use to poll for the result once the video generation is complete.A valid API key is required to use this endpoint. Obtain your API key from the API Access page in your Pictory dashboard.
API Endpoint
POST https://api.pictory.ai/pictoryapis/v1/aistudio/videos
Request Headers
string
required
API key for authentication (starts with
pictai_)Authorization: YOUR_API_KEY
string
required
Must be
application/jsonRequest Body
string
required
A text description of the video you want to generate. The prompt must be between 5 and 5,000 characters.Example:
"A drone flying over a lush green forest with sunlight filtering through the canopy"string
The AI model to use for video generation. Each model offers different quality levels, durations, and aspect ratios. Defaults to
pixverse5.5 if not specified.Supported models: veo3.1, veo3.1_fast, pixverse5.5Model Capabilities and Pricing:| Model | Supported Aspect Ratios | Supported Durations | AI Credits per Second |
|---|---|---|---|
veo3.1 | 16:9, 9:16 | 4s, 6s, 8s | 20 |
veo3.1_fast | 16:9, 9:16 | 4s, 6s, 8s | 10 |
pixverse5.5 | 16:9, 9:16, 1:1, 3:4, 4:3 | 5s, 8s, 10s | 1.6 |
string
The aspect ratio for the generated video. The available values depend on the selected model. Defaults to the first supported aspect ratio of the chosen model. Refer to the model table above for supported aspect ratios per model.
string
The duration of the generated video. The available values depend on the selected model. Defaults to the first supported duration of the chosen model. Refer to the model table above for supported durations per model.
string
An optional URL of an image to use as the first frame of the video. This guides the visual starting point for the generation. The URL must be a valid, publicly accessible URI.
This parameter cannot be used together with
extendVideoUrl or referenceImageUrls.string
An optional URL of an existing video to extend. The AI model will generate additional content that continues from the end of the provided video. The URL must be a valid, publicly accessible URI.
This parameter cannot be used together with
firstFrameImageUrl.array
An optional array of image URLs (1 to 3) to use as visual references for the generated video. The AI model will use these images to influence the style and content of the output. Each URL must be a valid, publicly accessible URI.
This parameter cannot be used together with
firstFrameImageUrl or extendVideoUrl.string
An optional webhook URL that will receive a notification when the video generation job completes. The URL must be a valid URI.
Response
Success Response (200)
boolean
true when the job has been created successfullyobject
string
The unique identifier (UUID) of the video generation job. Use this ID to poll for the result using the Get Video Generation Job endpoint.
Response Examples
{
"success": true,
"data": {
"jobId": "4a09edf9-d071-4847-bda5-8dea913d80fe"
}
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "prompt",
"message": "\"prompt\" is required"
}
]
}
{
"code": "INVALID_REQUEST_BODY",
"message": "Request body validation failed.",
"fields": [
{
"field": "extendVideoUrl",
"message": "\"extendVideoUrl\" is not allowed"
}
]
}
{
"message": "Unauthorized"
}
{
"message": "Internal Server Error"
}
Status Codes
| Status Code | Description |
|---|---|
| 200 | Job created successfully. Use the returned jobId to poll for the result. |
| 400 | Invalid request body. Check the fields array for specific validation errors. This also occurs when mutually exclusive parameters are used together. |
| 401 | Unauthorized. The API key in the Authorization header is missing or invalid. |
| 500 | Internal server error. Retry the request after a brief delay. |
Parameter Exclusivity
ThefirstFrameImageUrl, extendVideoUrl, and referenceImageUrls parameters are mutually exclusive. You may use only one of these in a single request. Providing more than one will result in a 400 validation error.
| Parameter | Can be combined with |
|---|---|
firstFrameImageUrl | prompt, model, aspectRatio, duration, webhook only |
extendVideoUrl | prompt, model, aspectRatio, duration, webhook only |
referenceImageUrls | prompt, model, aspectRatio, duration, webhook only |
Code Examples
Replace
YOUR_API_KEY with your actual API key from the API Access page.curl --request POST \
--url 'https://api.pictory.ai/pictoryapis/v1/aistudio/videos' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "A drone flying over a lush green forest with sunlight filtering through the canopy",
"model": "pixverse5.5",
"aspectRatio": "16:9",
"duration": "8s"
}'
import requests
url = "https://api.pictory.ai/pictoryapis/v1/aistudio/videos"
headers = {
"Authorization": "YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"prompt": "A drone flying over a lush green forest with sunlight filtering through the canopy",
"model": "pixverse5.5",
"aspectRatio": "16:9",
"duration": "8s"
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
if data.get("success"):
job_id = data["data"]["jobId"]
print(f"Video generation job created: {job_id}")
else:
print(f"Error: {data}")
const url = 'https://api.pictory.ai/pictoryapis/v1/aistudio/videos';
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
prompt: 'A drone flying over a lush green forest with sunlight filtering through the canopy',
model: 'pixverse5.5',
aspectRatio: '16:9',
duration: '8s'
})
});
const data = await response.json();
if (data.success) {
console.log(`Video generation job created: ${data.data.jobId}`);
} else {
console.log('Error:', data);
}
<?php
$url = "https://api.pictory.ai/pictoryapis/v1/aistudio/videos";
$payload = json_encode([
"prompt" => "A drone flying over a lush green forest with sunlight filtering through the canopy",
"model" => "pixverse5.5",
"aspectRatio" => "16:9",
"duration" => "8s"
]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: YOUR_API_KEY',
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if ($data['success']) {
echo "Video generation job created: " . $data['data']['jobId'] . "\n";
} else {
echo "Error: " . json_encode($data) . "\n";
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
url := "https://api.pictory.ai/pictoryapis/v1/aistudio/videos"
payload := map[string]string{
"prompt": "A drone flying over a lush green forest with sunlight filtering through the canopy",
"model": "pixverse5.5",
"aspectRatio": "16:9",
"duration": "8s",
}
jsonPayload, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload))
req.Header.Set("Authorization", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var data map[string]interface{}
json.Unmarshal(body, &data)
if success, ok := data["success"].(bool); ok && success {
jobData := data["data"].(map[string]interface{})
fmt.Printf("Video generation job created: %s\n", jobData["jobId"])
} else {
fmt.Println("Error:", string(body))
}
}
Next Steps
After receiving thejobId, poll for the video generation result using the Get Video Generation Job endpoint. Use a polling interval of 10–30 seconds to check the job status.Was this page helpful?
