Skip to main content
POST
https://api.pictory.ai
/
pictoryapis
/
v2
/
video
/
render
Render Video with Modifications
curl --request POST \
  --url https://api.pictory.ai/pictoryapis/v2/video/render \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: <content-type>'
{
  "success": true,
  "data": {
    "jobId": "95e2ee80-g3gf-64h5-c749-0dhe2d68dfc1"
  }
}

Overview

The Render Video API generates a final video from storyboard elements that can be modified before rendering. This endpoint uses the renderParams property returned from a completed Create Storyboard Preview job, allowing you to make changes to scenes, visuals, text, and other elements before producing the final video.
This endpoint requires the renderParams object from a completed preview job. First create a preview, retrieve the job output to get renderParams, modify as needed, then submit to this endpoint.
Use this endpoint when you need to modify the preview - change scenes, update visuals, adjust timing, or customize content before final render.

Render Workflow Options

WorkflowAPIWhen to Use
Create PreviewCreate Storyboard PreviewGenerate preview to review scenes before rendering
Render from PreviewRender from PreviewRender preview as-is without modifications
Render with ModificationsThis APIModify preview elements before rendering
Render Saved ProjectRender ProjectRender existing project created in App or via API
Direct RenderRender Storyboard VideoSkip preview, render directly from input

When to Use This Endpoint

Scene Modifications

Add, remove, or reorder scenes from the preview

Visual Replacements

Replace AI-selected backgrounds with custom visuals

Text Updates

Modify subtitle text or scene content

Timing Adjustments

Change scene durations or transitions

API Endpoint

POST https://api.pictory.ai/pictoryapis/v2/video/render

Request Parameters

Headers

Authorization
string
required
API key for authentication
Authorization: YOUR_API_KEY
Content-Type
string
required
Must be application/json

Request Body

The request body should contain the values from the renderParams object returned in a completed preview job response. Send the renderParams content directly as the request body (not wrapped in a renderParams property). You can modify any properties before submitting.

Getting renderParams from Preview Job

After creating a storyboard preview, retrieve the job output using the Get Job API. The response includes a renderParams object containing the complete storyboard configuration:
{
  "job_id": "2cc183fc-f07a-4bf1-b7a0-92ec999b22f3",
  "success": true,
  "data": {
    "status": "completed",
    "renderParams": {
      "output": {
        "width": 1920,
        "height": 1080,
        "format": "mp4",
        "name": "my_video.mp4",
        "title": "my_video",
        "description": ""
      },
      "elements": [
        {
          "type": "audio",
          "id": "voiceOver",
          "elementType": "audioElement",
          "url": "https://...",
          "segments": [...]
        },
        {
          "type": "audio",
          "id": "bgMusic",
          "elementType": "audioElement",
          "url": "https://...",
          "segments": [...]
        },
        {
          "id": "backgroundElement_1",
          "elementType": "backgroundElement",
          "type": "video",
          "url": "https://...",
          "visualUrl": "https://...",
          "startTime": 0,
          "duration": 10.53
        },
        {
          "id": "SceneText_1_1",
          "elementType": "SceneText",
          "type": "text",
          "text": "Your subtitle text here...",
          "fontFamily": "Arial",
          "fontSize": "24",
          "startTime": 0,
          "duration": 10.53
        }
      ],
      "sceneMarkers": [...],
      "subtitles": [...],
      "projectId": "1767054556293"
    },
    "previewUrl": "https://video.pictory.ai/v2/preview/...",
    "projectUrl": "https://app.pictory.ai/v2/storyboard/...",
    "projectId": "1767054556293"
  }
}
Use the contents of renderParams directly as the request body for this API:
{
  "output": {
    "width": 1920,
    "height": 1080,
    "format": "mp4",
    "name": "my_video.mp4",
    "title": "my_video"
  },
  "elements": [...],
  "sceneMarkers": [...],
  "subtitles": [...],
  "projectId": "1767054556293"
}

Modifiable Elements

Within renderParams, you can modify:
ElementDescription
outputVideo output settings (width, height, format, name, title)
elementsArray of all video elements - audio, backgrounds, and text
elements[].urlChange background video/image URL for backgroundElement types
elements[].textUpdate subtitle text for SceneText elements
elements[].durationAdjust element timing
elements[].fontFamily, fontSize, fontColorModify text styling
sceneMarkersScene timing and markers
subtitlesSubtitle text content

Element Types

elementTypeDescription
audioElementVoice-over or background music audio
backgroundElementScene background video or image
SceneTextSubtitle/caption text overlay

Response

The API returns a job ID for tracking the video rendering progress.
{
  "success": true,
  "data": {
    "jobId": "95e2ee80-g3gf-64h5-c749-0dhe2d68dfc1"
  }
}

Monitoring Render Progress

After receiving the job ID, use the Get Job API to monitor rendering progress:
GET https://api.pictory.ai/pictoryapis/v1/jobs/{jobId}
The job will transition through these statuses:
  • pending - Job is queued
  • in-progress - Video is being rendered
  • completed - Video is ready with videoURL in the response
  • failed - Rendering failed with error details

Code Examples

Replace YOUR_API_KEY with your actual API key.

Basic Render with Modified Elements

curl --request POST \
  --url https://api.pictory.ai/pictoryapis/v2/video/render \
  --header 'Authorization: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "output": {
      "width": 1920,
      "height": 1080,
      "format": "mp4",
      "name": "modified_video.mp4",
      "title": "modified_video"
    },
    "elements": [...],
    "sceneMarkers": [...],
    "subtitles": [...],
    "projectId": "1767054556293"
  }' | python -m json.tool

Complete Workflow: Preview, Modify, Render

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 job and get renderParams
async function getJobResult(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') {
      return data.data;
    }

    if (data.data.status === 'failed') {
      throw new Error('Job failed');
    }

    await new Promise(resolve => setTimeout(resolve, 5000));
  }
}

// Step 3: Modify renderParams and render
async function renderWithModifications(renderParams) {
  // Example modifications:

  // Change output title
  renderParams.output.title = 'modified_video';
  renderParams.output.name = 'modified_video.mp4';

  // Modify a background element's URL (find backgroundElement by id)
  // const bgElement = renderParams.elements.find(el => el.id === 'backgroundElement_1');
  // if (bgElement) bgElement.url = 'https://example.com/new-bg.mp4';

  // Submit renderParams directly as the request body
  const response = await fetch(`${API_BASE}/v2/video/render`, {
    method: 'POST',
    headers: {
      'Authorization': API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(renderParams)
  });

  const data = await response.json();
  return data.data.jobId;
}

// Execute workflow
async function main() {
  try {
    // Create preview
    console.log('Creating preview...');
    const previewJobId = await createPreview();
    console.log('Preview Job ID:', previewJobId);

    // Wait for preview and get renderParams
    console.log('Waiting for preview...');
    const previewResult = await getJobResult(previewJobId);
    console.log('Preview completed!');

    const renderParams = previewResult.renderParams;

    // Modify and render
    console.log('Rendering with modifications...');
    const renderJobId = await renderWithModifications(renderParams);
    console.log('Render Job ID:', renderJobId);

    // Wait for render
    const renderResult = await getJobResult(renderJobId);
    console.log('Video URL:', renderResult.videoURL);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

main();

Example: Replace Scene Background

// Get renderParams from preview job
const renderParams = previewJobResponse.data.renderParams;

// Find and replace background for first scene (backgroundElement_1)
const bgElement = renderParams.elements.find(el => el.id === 'backgroundElement_1');
if (bgElement) {
  bgElement.url = 'https://your-domain.com/custom-background.mp4';
  bgElement.visualUrl = 'https://your-domain.com/custom-background.mp4';
}

// Render with new background - send renderParams directly
const response = await fetch('https://api.pictory.ai/pictoryapis/v2/video/render', {
  method: 'POST',
  headers: {
    'Authorization': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(renderParams)
});

Error Handling

{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "elements is required"
  }
}
Solution: Ensure your request body contains all required fields from the preview job’s renderParams including output, elements, sceneMarkers, and projectId. Send the renderParams content directly as the request body.
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Invalid request structure"
  }
}
Solution: Ensure the request body maintains the required structure from the preview job’s renderParams. Only modify specific properties, don’t remove required fields.
{
  "success": false,
  "error": {
    "message": "Invalid element configuration at index 0"
  }
}
Solution: Check that modified elements have valid configurations. Ensure URLs are accessible and properly formatted. Each element must have valid id, elementType, and type properties.
{
  "message": "Unauthorized"
}
Solution: Check your API key is valid and correctly formatted in the Authorization header.