Render Video from Preview
curl --request PUT \
--url https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid} \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"webhook": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}"
payload = { "webhook": "<string>" }
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({webhook: '<string>'})
};
fetch('https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}', 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/v2/video/render/{storyboardjobid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'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/v2/video/render/{storyboardjobid}"
payload := strings.NewReader("{\n \"webhook\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"webhook\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"webhook\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "265a7c1a-4985-4058-9208-68114f131a2b"
}
}
{
"message": "Unauthorized"
}
Videos
Render Video from Preview
Render final video from an existing storyboard preview job output
PUT
/
pictoryapis
/
v2
/
video
/
render
/
{storyboardjobid}
Render Video from Preview
curl --request PUT \
--url https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid} \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"webhook": "<string>"
}
'import requests
url = "https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}"
payload = { "webhook": "<string>" }
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({webhook: '<string>'})
};
fetch('https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}', 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/v2/video/render/{storyboardjobid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'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/v2/video/render/{storyboardjobid}"
payload := strings.NewReader("{\n \"webhook\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"webhook\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"webhook\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"jobId": "265a7c1a-4985-4058-9208-68114f131a2b"
}
}
{
"message": "Unauthorized"
}
Overview
The Render from Preview API generates the final video file from an existing storyboard preview. This endpoint is part of the recommended two-step workflow: first create a preview to review and validate content, then render the final video once approved.This endpoint requires a completed storyboard preview job ID. First use the Create Storyboard Preview API to generate a preview, then use this endpoint to render the final video.
Recommended Workflow: Create Preview → Review Scenes → Make Adjustments (optional) → Render Final Video
Render Workflow Options
| Workflow | API | When to Use |
|---|---|---|
| Create Preview | Create Storyboard Preview | Generate preview to review scenes before rendering |
| Render from Preview | This API | Render preview as-is without modifications |
| Render with Modifications | Render Video | Modify preview elements before rendering |
| Render Saved Project | Render Project | Render existing project created in App or via API |
| Direct Render | Render Storyboard Video | Skip preview, render directly from input |
Benefits of Two-Step Workflow
Content Validation
Review scenes, visuals, and timing before committing to render
Cost Optimization
Only render videos that have been reviewed and approved
Iterative Refinement
Make adjustments to the preview before final render
Quality Assurance
Ensure content meets requirements before production
API Endpoint
PUT https://api.pictory.ai/pictoryapis/v2/video/render/{storyboardjobid}
Request Parameters
Path Parameters
string
required
The job ID returned from a completed Create Storyboard Preview request. This ID identifies the storyboard configuration to render.
Headers
string
required
API key for authentication
Authorization: YOUR_API_KEY
string
required
Must be
application/jsonRequest Body Parameters
The request body allows you to override or add settings from the original storyboard preview. All parameters are optional - if not provided, the original preview settings are used.string
URL where the completed video output will be sent via POST request when finished (max 500 characters). Overrides the webhook from the preview.
Response
When the render request is successfully submitted, a job is created and a job ID is returned.boolean
Indicates whether the request was successful
object
string
Unique identifier for the render job. Use this to track the job status and retrieve results via the Get Video Render Job by ID endpoint.
{
"success": true,
"data": {
"jobId": "265a7c1a-4985-4058-9208-68114f131a2b"
}
}
{
"message": "Unauthorized"
}
Next Steps
Once you have thejobId, poll the Get Video Render Job by ID endpoint to check the render status and retrieve the output URLs when complete. Use a polling interval of 10–30 seconds.
Code Examples
Replace
YOUR_API_KEY with your actual API key and STORYBOARD_JOB_ID with the job ID from your preview request.Basic Render from Preview
curl --request PUT \
--url https://api.pictory.ai/pictoryapis/v2/video/render/74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9 \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{}' | python -m json.tool
const storyboardJobId = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9';
const response = await fetch(
`https://api.pictory.ai/pictoryapis/v2/video/render/${storyboardJobId}`,
{
method: 'PUT',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({})
}
);
const data = await response.json();
console.log('Render Job ID:', data.data.jobId);
import requests
storyboard_job_id = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9'
response = requests.put(
f'https://api.pictory.ai/pictoryapis/v2/video/render/{storyboard_job_id}',
headers={
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={}
)
data = response.json()
print('Render Job ID:', data['data']['jobId'])
<?php
$storyboardJobId = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9';
$url = "https://api.pictory.ai/pictoryapis/v2/video/render/{$storyboardJobId}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([]));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
echo 'Render Job ID: ' . $data['data']['jobId'] . PHP_EOL;
} else {
echo 'Request failed with status ' . $httpCode . PHP_EOL;
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
storyboardJobId := "74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9"
url := fmt.Sprintf("https://api.pictory.ai/pictoryapis/v2/video/render/%s", storyboardJobId)
requestBody, _ := json.Marshal(map[string]interface{}{})
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody))
if err != nil {
panic(err)
}
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 {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
data := result["data"].(map[string]interface{})
fmt.Println("Render Job ID:", data["jobId"])
}
Render with Webhook Notification
const storyboardJobId = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9';
const response = await fetch(
`https://api.pictory.ai/pictoryapis/v2/video/render/${storyboardJobId}`,
{
method: 'PUT',
headers: {
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
webhook: 'https://your-server.com/video-complete'
})
}
);
const data = await response.json();
console.log('Render Job ID:', data.data.jobId);
import requests
storyboard_job_id = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9'
response = requests.put(
f'https://api.pictory.ai/pictoryapis/v2/video/render/{storyboard_job_id}',
headers={
'Authorization': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'webhook': 'https://your-server.com/video-complete'
}
)
data = response.json()
print('Render Job ID:', data['data']['jobId'])
<?php
$storyboardJobId = '74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9';
$url = "https://api.pictory.ai/pictoryapis/v2/video/render/{$storyboardJobId}";
$payload = [
'webhook' => 'https://your-server.com/video-complete'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$data = json_decode($response, true);
echo 'Render Job ID: ' . $data['data']['jobId'] . PHP_EOL;
} else {
echo 'Request failed with status ' . $httpCode . PHP_EOL;
}
?>
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
storyboardJobId := "74c0cc68-e1ed-42f3-a527-8bfc0b46bdb9"
url := fmt.Sprintf("https://api.pictory.ai/pictoryapis/v2/video/render/%s", storyboardJobId)
payload := map[string]interface{}{
"webhook": "https://your-server.com/video-complete",
}
requestBody, _ := json.Marshal(payload)
req, err := http.NewRequest("PUT", url, bytes.NewBuffer(requestBody))
if err != nil {
panic(err)
}
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 {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
data := result["data"].(map[string]interface{})
fmt.Println("Render Job ID:", data["jobId"])
}
Complete Two-Step Workflow
const API_KEY = 'YOUR_API_KEY';
const API_BASE = 'https://api.pictory.ai/pictoryapis';
// Step 1: Create storyboard preview
async function createPreview() {
const response = await fetch(`${API_BASE}/v2/video/storyboard`, {
method: 'POST',
headers: {
'Authorization': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
videoName: 'my_video',
voiceOver: {
enabled: true,
aiVoices: [{ speaker: 'Brian', speed: 100 }]
},
scenes: [{
story: 'Welcome to our product demo. We will show you amazing features.',
createSceneOnEndOfSentence: true
}]
})
});
const data = await response.json();
return data.data.jobId;
}
// Step 2: Wait for preview to complete
async function waitForJob(jobId) {
while (true) {
const response = await fetch(`${API_BASE}/v1/jobs/${jobId}`, {
headers: { 'Authorization': API_KEY }
});
const data = await response.json();
if (data.data.status === 'completed') {
console.log('Preview ready!');
return data.data;
}
if (data.data.status === 'failed') {
throw new Error('Job failed');
}
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
// Step 3: Render final video from preview
async function renderFromPreview(storyboardJobId) {
const response = await fetch(`${API_BASE}/v2/video/render/${storyboardJobId}`, {
method: 'PUT',
headers: {
'Authorization': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
webhook: 'https://your-server.com/video-complete'
})
});
const data = await response.json();
return data.data.jobId;
}
// Execute workflow
async function main() {
// Create preview
const previewJobId = await createPreview();
console.log('Preview Job ID:', previewJobId);
// Wait for preview
await waitForJob(previewJobId);
// Render final video
const renderJobId = await renderFromPreview(previewJobId);
console.log('Render Job ID:', renderJobId);
// Wait for render
const result = await waitForJob(renderJobId);
console.log('Video URL:', result.videoURL);
}
main();
import requests
import time
API_KEY = 'YOUR_API_KEY'
API_BASE = 'https://api.pictory.ai/pictoryapis'
def create_preview():
"""Step 1: Create storyboard preview"""
response = requests.post(
f'{API_BASE}/v2/video/storyboard',
headers={
'Authorization': API_KEY,
'Content-Type': 'application/json'
},
json={
'videoName': 'my_video',
'voiceOver': {
'enabled': True,
'aiVoices': [{'speaker': 'Brian', 'speed': 100}]
},
'scenes': [{
'story': 'Welcome to our product demo. We will show you amazing features.',
'createSceneOnEndOfSentence': True
}]
}
)
data = response.json()
return data['data']['jobId']
def wait_for_job(job_id):
"""Step 2: Wait for job to complete"""
while True:
response = requests.get(
f'{API_BASE}/v1/jobs/{job_id}',
headers={'Authorization': API_KEY}
)
data = response.json()
status = data['data']['status']
if status == 'completed':
print('Job completed!')
return data['data']
if status == 'failed':
raise Exception('Job failed')
time.sleep(5)
def render_from_preview(storyboard_job_id):
"""Step 3: Render final video from preview"""
response = requests.put(
f'{API_BASE}/v2/video/render/{storyboard_job_id}',
headers={
'Authorization': API_KEY,
'Content-Type': 'application/json'
},
json={
'webhook': 'https://your-server.com/video-complete'
}
)
data = response.json()
return data['data']['jobId']
def main():
# Create preview
preview_job_id = create_preview()
print(f'Preview Job ID: {preview_job_id}')
# Wait for preview
wait_for_job(preview_job_id)
# Render final video
render_job_id = render_from_preview(preview_job_id)
print(f'Render Job ID: {render_job_id}')
# Wait for render
result = wait_for_job(render_job_id)
print(f'Video URL: {result["videoURL"]}')
if __name__ == '__main__':
main()
Error Handling
400 - Invalid Storyboard Job ID
400 - Invalid Storyboard Job ID
{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "Invalid storyboard job ID format"
}
}
404 - Storyboard Not Found
404 - Storyboard Not Found
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Storyboard job not found"
}
}
400 - Preview Not Completed
400 - Preview Not Completed
{
"success": false,
"error": {
"message": "Storyboard preview is not yet completed"
}
}
401 - Unauthorized
401 - Unauthorized
{
"message": "Unauthorized"
}
Related APIs
Create Storyboard Preview
Generate preview before rendering (Step 1)
Render Storyboard Video
Direct render without preview step
Get Render Job Status
Monitor rendering progress
Get Projects
List saved video projects
Was this page helpful?
