PROPERVID|

API Documentation

Introduction

The ProperVid API lets you programmatically create professional property marketing videos from images. Upload your property photos, provide a description, and the API generates a polished video with AI voiceover, background music, and captions.

Base URL

https://www.propervid.io/api/v1

Version

v1

Content Type

application/json

All requests and responses use JSON. Provide an Authorization header with your API key on every request.

Video generation is asynchronous — you submit a job and poll for completion, or configure a webhook to be notified when your video is ready.

Use the dashboard to create reusable templates, design brand kit end frames, and connect social media accounts for automatic posting — then reference them in your API calls.

Authentication

All API requests require a Bearer token in the Authorization header. API keys are generated from your dashboard under Settings.

Authorization Header
Authorization: Bearer vg_live_your_api_key_here

Example Request

curl https://www.propervid.io/api/v1/health \
  -H "Authorization: Bearer vg_live_abc123..."

Response

{
  "status": "ok",
  "timestamp": "2025-02-07T12:00:00.000Z",
  "version": "1.0.0",
  "database": "configured"
}

Warning

Keep your API key secret. Do not expose it in client-side code, public repositories, or share it with untrusted parties. If compromised, regenerate your key immediately from the dashboard.

Quick Start

Create your first property video in 3 steps. Provide your listing photos and a description, and ProperVid generates a professional marketing video with AI voiceover and music.

Step 1: Create a Property Video

Submit your property images and listing description. ProperVid generates the voiceover, sequences the images, and starts video processing.

curl -X POST https://www.propervid.io/api/v1/properties \
  -H "Authorization: Bearer vg_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "images": [
      { "url": "https://example.com/front.jpg" },
      { "url": "https://example.com/living.jpg" },
      { "url": "https://example.com/kitchen.jpg" },
      { "url": "https://example.com/bedroom.jpg" },
      { "url": "https://example.com/garden.jpg" }
    ],
    "productDescription": "Stunning 4-bedroom family home at 12 Oak Avenue. Open-plan kitchen and living area, landscaped garden, two bathrooms, double garage.",
    "voiceId": "eldrin"
  }'

Returns a jobId immediately (HTTP 202). Video processing continues in the background (~2-8 minutes).

Tip

ProperVid automatically analyses each image using AI vision to identify its contents, so labels are helpful but not essential. Descriptive filenames (e.g. front-exterior.jpg) and labels improve matching accuracy, but the AI will work with unlabelled images too.

Step 2: Poll for Completion

Poll the job status endpoint. The response includes retryAfter to tell you how long to wait before the next poll.

curl https://www.propervid.io/api/v1/properties/YOUR_JOB_ID \
  -H "Authorization: Bearer vg_live_your_key"

Response (processing)

{
  "id": "708a3c36-...",
  "status": "processing",
  "progress": 45,
  "retryAfter": 30,
  "estimatedCompletionAt": "2025-02-07T19:44:00.000Z"
}

Step 3: Download Your Video

When status is "completed", the response includes download URLs for each output format.

{
  "id": "708a3c36-...",
  "status": "completed",
  "progress": 100,
  "outputs": {
    "landscape": {
      "url": "https://blob.vercel-storage.com/videos/708a3c36-.../landscape.mp4",
      "size": 10969861
    },
    "srt": {
      "url": "https://blob.vercel-storage.com/videos/708a3c36-.../captions.srt"
    }
  },
  "createdAt": "2025-02-07T19:36:14.124Z",
  "completedAt": "2025-02-07T19:38:28.343Z"
}

Polling Example

async function waitForVideo(jobId, apiKey) {
  const headers = { Authorization: `Bearer ${apiKey}` };

  while (true) {
    const res = await fetch(
      `https://www.propervid.io/api/v1/properties/${jobId}`,
      { headers }
    );
    const job = await res.json();

    if (job.status === "completed") return job.outputs;
    if (job.status === "failed") throw new Error(job.error.message);

    // Wait the recommended interval
    const wait = (job.retryAfter || 30) * 1000;
    await new Promise(r => setTimeout(r, wait));
  }
}

Tip

For production use, configure a webhook instead of polling. You will receive a POST request when your video is ready.

Optional: Save a Template

Save your preferred voice, music, and output settings as a reusable template. Pass the template ID as presetId when creating videos to apply your saved configuration automatically.

curl -X POST https://www.propervid.io/api/v1/templates \
  -H "Authorization: Bearer vg_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Luxury Property Tour",
    "config": {
      "voiceId": "eldrin",
      "voiceEmotion": "warm",
      "backgroundMusic": { "trackId": "apricity", "volume": 20 },
      "captions": { "enabled": true },
      "outputs": {
        "landscape": { "enabled": true, "resolution": "1080p" }
      }
    }
  }'

Then use the template: "presetId": "YOUR_TEMPLATE_ID" in your video creation requests. See Templates for full details.

Property Videos

Submit your listing photos and a description, and ProperVid handles the rest — AI vision analyses each image, generates a professional voiceover script, sequences your images, and produces a polished video.

Endpoints

POST/api/v1/properties
GET/api/v1/properties
GET/api/v1/properties/:jobId
DELETE/api/v1/properties/:jobId
POST

/api/v1/properties

Create a property video with AI-generated voiceover, background music, and professional timing.

Request Body

ParameterTypeRequiredDescription
imagesarrayRequiredProperty images (1-40)
images[].urlstringRequiredImage URL
images[].labelstringOptionalShort description of the image. If omitted, ProperVid uses AI vision to identify image contents automatically.
imageOrdernumber[]OptionalDisplay order as array of image indices. Defaults to the order provided.
productDescriptionstringRequiredProperty listing description (max 50000 chars)
contentTypeenumOptionalContent type (see categories below)
scriptStyleenumOptionalpunchy (short, snappy), flowery (eloquent), factual (direct)
languageenumOptionalen, fr, es, or ro
voiceIdstringOptionalVoice ID (see Voices reference). Required unless provided by preset.
voiceEmotionenumOptionalneutral, warm, energetic, calm, cheerful
backgroundMusicUrlstringOptionalBackground music URL or relative path
backgroundMusicVolumenumberOptionalMusic volume (0-100)
outputsobjectOptionalAt least one output format (landscape, square, portrait). Defaults to landscape 1080p if not provided by request or preset.
scalingModeenumOptionalcover or blur-fill
captionsobjectOptional{ enabled: boolean, textColor: '#FFFFFF', highlightColor: '#FFD700' }
endFrameobjectOptional{ brandKitId: 'uuid' } — Reference a brand kit created in the dashboard, or pass { enabled: true, logoUrl, website, phone } to generate on the fly
motionEffectenumOptionalMotion applied to images: zoom (slow zoom in), zoomOut (slow zoom out), kenBurns (cinematic zoom & pan)
webhookUrlstringOptionalWebhook URL for completion notification
presetIduuidOptionalTemplate ID — merges saved config (per-call values override)
externalIdstringOptionalYour reference ID (max 255 chars)
customerMetadataobjectOptionalCustom key-value data

Categories

real_estateholiday_rentalhotel_roomvenueboatcarmotorhomejewellerywatchart_antiqueproductgeneral

Response (202 Accepted)

{
  "success": true,
  "jobId": "708a3c36-1965-44ab-82fc-9c79a2ac8d37",
  "status": "pending",
  "script": "Presenting this stunning four-bedroom family home...",
  "estimatedDuration": 36.5
}

Info

Use the jobId to poll for the video output via GET /api/v1/properties/:jobId, or configure a webhook to be notified on completion.
GET

/api/v1/properties

List recent video jobs for the authenticated user.

Query Parameters

ParameterTypeRequiredDescription
limitnumberOptionalMax results to return (1-100)
offsetnumberOptionalNumber of results to skip (for pagination)
externalIdstringOptionalFilter by your external reference ID

Response (200 OK)

{
  "jobs": [
    {
      "id": "708a3c36-1965-44ab-82fc-9c79a2ac8d37",
      "status": "completed",
      "progress": 100,
      "landscapeUrl": "https://blob.vercel-storage.com/videos/.../landscape.mp4",
      "createdAt": "2025-02-07T19:36:14.124Z",
      "completedAt": "2025-02-07T19:38:28.343Z"
    }
  ],
  "limit": 20,
  "offset": 0
}
GET

/api/v1/properties/:jobId

Get the status and outputs of a single video job.

Response (200 OK — processing)

{
  "id": "708a3c36-...",
  "status": "processing",
  "progress": 45,
  "retryAfter": 30,
  "estimatedCompletionAt": "2025-02-07T19:44:00.000Z"
}

Response (200 OK — completed)

{
  "id": "708a3c36-...",
  "status": "completed",
  "progress": 100,
  "outputs": {
    "landscape": {
      "url": "https://blob.vercel-storage.com/videos/.../landscape.mp4",
      "size": 10969861
    },
    "srt": {
      "url": "https://blob.vercel-storage.com/videos/.../captions.srt"
    }
  },
  "createdAt": "2025-02-07T19:36:14.124Z",
  "completedAt": "2025-02-07T19:38:28.343Z"
}

Tip

Use the retryAfter field to know how long to wait before your next poll. See Smart Polling for details.
DELETE

/api/v1/properties/:jobId

Permanently delete a video job and its outputs.

Response (200 OK)

{ "deleted": true }

Templates

Tip

Most users create and manage templates from the dashboard — configure your preferred voice, music, captions, output formats, and brand kit, then simply reference the template ID in your API calls. The endpoints below are available if you need to manage templates programmatically.

Templates save reusable video configurations. Your oldest template is automatically applied as the default for all video creation requests. Pass a specific presetId to use a different template, or override individual settings in the request body. Per-call values always take precedence.

Endpoints

POST/api/v1/templates
GET/api/v1/templates
GET/api/v1/templates/:templateId
PUT/api/v1/templates/:templateId
DELETE/api/v1/templates/:templateId
POST

/api/v1/templates

Create a new video template.

Request Body

ParameterTypeRequiredDescription
namestringRequiredTemplate name (1-200 chars)
config.languageenumOptionalen, fr, es, or ro
config.scriptStyleenumOptionalpunchy, flowery, or factual
config.voiceIdstringOptionalVoice ID
config.voiceEmotionenumOptionalneutral, warm, energetic, calm, cheerful
config.backgroundMusicobjectOptional{ url?, trackId?, volume? }
config.captionsobjectOptional{ enabled?, textColor?, highlightColor? }
config.endFrameobjectOptional{ brandKitId? }
config.outputsobjectOptional{ landscape?, square?, portrait? }
config.scalingModeenumOptionalcover or blur-fill
config.effectsobjectOptional{ motionEffect? } — zoom, zoomOut, or kenBurns

Example Request

curl -X POST https://www.propervid.io/api/v1/templates \
  -H "Authorization: Bearer vg_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Premium Property Tour",
    "config": {
      "language": "en",
      "scriptStyle": "flowery",
      "voiceId": "eldrin",
      "voiceEmotion": "warm",
      "backgroundMusic": {
        "trackId": "apricity",
        "volume": 20
      },
      "captions": { "enabled": true },
      "outputs": {
        "landscape": { "enabled": true, "resolution": "1080p" },
        "portrait": { "enabled": true, "resolution": "1080p" }
      },
      "effects": {
        "motionEffect": "zoom"
      }
    }
  }'

Response (201 Created)

{
  "id": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b",
  "name": "Premium Property Tour",
  "config": { ... },
  "createdAt": "2025-02-07T19:20:00.000Z",
  "updatedAt": "2025-02-07T19:20:00.000Z"
}

Tip

Your first template is automatically used as the default for all video creation requests. You can pass a specific presetId to use a different template, or override individual settings in the request body.
GET

/api/v1/templates

List all templates for the authenticated user.

Response (200 OK)

{
  "templates": [
    {
      "id": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b",
      "name": "Premium Property Tour",
      "config": {
        "voiceId": "eldrin",
        "voiceEmotion": "warm",
        "backgroundMusic": { "trackId": "apricity", "volume": 20 },
        "captions": { "enabled": true },
        "outputs": { "landscape": { "enabled": true, "resolution": "1080p" } }
      },
      "createdAt": "2025-02-07T19:20:00.000Z",
      "updatedAt": "2025-02-07T19:20:00.000Z"
    }
  ]
}
GET

/api/v1/templates/:templateId

Get a single template by ID.

Response (200 OK)

{
  "id": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b",
  "name": "Premium Property Tour",
  "config": {
    "language": "en",
    "scriptStyle": "flowery",
    "voiceId": "eldrin",
    "voiceEmotion": "warm",
    "backgroundMusic": { "trackId": "apricity", "volume": 20 },
    "captions": { "enabled": true },
    "outputs": {
      "landscape": { "enabled": true, "resolution": "1080p" },
      "portrait": { "enabled": true, "resolution": "1080p" }
    },
    "effects": { "motionEffect": "kenBurns", "transitionEffect": "fade" }
  },
  "createdAt": "2025-02-07T19:20:00.000Z",
  "updatedAt": "2025-02-07T19:20:00.000Z"
}
PUT

/api/v1/templates/:templateId

Update a template. All fields are optional — only provided fields are changed.

Request Body

{
  "name": "Updated Template Name",
  "config": {
    "voiceId": "alicia",
    "backgroundMusic": { "trackId": "paragliding", "volume": 30 }
  }
}

Response (200 OK)

{
  "id": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b",
  "name": "Updated Template Name",
  "config": { ... },
  "createdAt": "2025-02-07T19:20:00.000Z",
  "updatedAt": "2025-02-07T20:15:00.000Z"
}
DELETE

/api/v1/templates/:templateId

Permanently delete a template.

Response (200 OK)

{ "deleted": true }

Brand Kits

Tip

Brand kits are created and designed in the dashboard — upload your logo, enter your website and phone number, and preview how the end frame looks. Then simply reference the brand kit ID in your API calls to add it to every video.

Brand kits add a professional end frame to your property videos with your logo, website, and contact details.

How Brand Kits Work

  1. Create a brand kit in the dashboard under Settings > Brand Kit
  2. Upload your logo, enter your website and phone number, and customise text styling
  3. Use the returned brandKitId in your API requests via the endFrame parameter
  4. You can also save a brand kit reference inside a template for automatic use

Using a Brand Kit in Video Creation

// In POST /api/v1/properties:
{
  "endFrame": {
    "brandKitId": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b"
  }
}

The brand kit includes pre-rendered end frame images for all three formats (landscape, portrait, square) along with your logo, website, phone number, and custom text styling.

Using a Brand Kit in a Template

// In POST /api/v1/templates:
{
  "name": "Branded Property Tour",
  "config": {
    "endFrame": {
      "brandKitId": "d21220d9-9ff9-4e49-a7a6-19b3a6e7634b"
    },
    "captions": {
      "enabled": true
    }
  }
}

Once saved in a template, the brand kit is automatically applied to all videos that use that template.

Inline End Frame (without Brand Kit)

If you don't have a brand kit, you can provide end frame details inline:

{
  "endFrame": {
    "enabled": true,
    "duration": 4,
    "logoUrl": "https://example.com/logo.png",
    "website": "www.example.com",
    "phone": "+1 (555) 123-4567"
  }
}

Tip

For consistent branding across all your videos, we recommend creating a brand kit in the dashboard rather than passing inline values on each request.

Upload

Upload listing images for your property videos. Most users rely on ProperVid's AI voices and royalty-free music library for audio — but if you need to, you can also upload your own pre-recorded voiceover or custom background music track.

POST

/api/v1/upload

Upload a listing image or audio file for use in property video generation. Supports multipart form data or JSON with base64.

Multipart Upload

curl -X POST https://www.propervid.io/api/v1/upload \
  -H "Authorization: Bearer vg_live_your_key" \
  -F "file=@/path/to/property-photo.jpg"

Base64 Upload

curl -X POST https://www.propervid.io/api/v1/upload \
  -H "Authorization: Bearer vg_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "data": "iVBORw0KGgoAAAANS...",
    "contentType": "image/jpeg"
  }'

Supported File Types

Images (max 10 MB)
image/jpeg (JPEG)image/png (PNG)image/webp (WebP)
Audio (max 50 MB)
audio/mpeg (MP3)audio/mp3 (MP3)audio/wav (WAV)audio/ogg (OGG)audio/aac (AAC)audio/m4a (M4A)

Info

Audio uploads are optional. Use a custom audio URL as backgroundMusic.url for your own music track, or as audio.voiceover.url for a pre-recorded narration. Audio levels are automatically normalised during video processing.

Uploading Multiple Images

The upload endpoint accepts one file at a time. To upload multiple listing photos, call it once per image and collect the returned URLs.

const fs = require("fs");
const photos = ["front.jpg", "living.jpg", "kitchen.jpg", "bedroom.jpg"];

const urls = await Promise.all(photos.map(async (photo) => {
  const formData = new FormData();
  formData.append("file", fs.createReadStream(photo));

  const res = await fetch("https://www.propervid.io/api/v1/upload", {
    method: "POST",
    headers: { Authorization: "Bearer vg_live_your_key" },
    body: formData,
  });
  const { url } = await res.json();
  return { url, label: photo.replace(/\.[^.]+$/, "").replace(/-/g, " ") };
}));

// urls is now ready to pass as the "images" array to /api/v1/properties

Response (200 OK)

{
  "url": "https://blob.vercel-storage.com/uploads/abc123.jpg",
  "filename": "property-photo.jpg",
  "size": 1024000,
  "contentType": "image/jpeg"
}

Webhooks

Instead of polling, configure a webhook URL to receive a POST request when your video completes or fails. Webhooks are signed with HMAC-SHA256 so you can verify they came from ProperVid.

How Webhooks Work

  1. Include a webhookUrl when creating a video
  2. When the video completes (or fails), ProperVid sends a POST request to your URL
  3. The request includes an HMAC-SHA256 signature for verification
  4. If your endpoint is unavailable, we retry up to 3 times with exponential backoff

Webhook Events

video.completed

{
  "event": "video.completed",
  "jobId": "708a3c36-1965-44ab-82fc-9c79a2ac8d37",
  "externalId": "OAK-AVE-12",
  "customerMetadata": { "agent": "Jane Doe" },
  "timestamp": "2025-02-07T19:38:28.000Z",
  "data": {
    "landscapeUrl": "https://blob.vercel-storage.com/videos/.../landscape.mp4",
    "landscapeSize": 10969861,
    "squareUrl": null,
    "portraitUrl": null,
    "srtUrl": "https://blob.vercel-storage.com/videos/.../captions.srt"
  }
}

video.failed

{
  "event": "video.failed",
  "jobId": "708a3c36-1965-44ab-82fc-9c79a2ac8d37",
  "externalId": "OAK-AVE-12",
  "timestamp": "2025-02-07T19:35:00.000Z",
  "error": {
    "code": "PROCESSING_ERROR",
    "message": "Failed to download image 0: 404 Not Found"
  }
}

Webhook Headers

HeaderDescription
X-ProperVid-SignatureHMAC-SHA256 hex digest of the request body
X-ProperVid-EventEvent type: video.completed or video.failed
X-ProperVid-DeliveryUnique delivery ID (UUID)

Signature Verification

Your webhook signing secret is provided when you generate your API key. Use it to verify that webhook requests are genuinely from ProperVid.

const crypto = require("crypto");

function verifyWebhookSignature(body, signature, signingSecret) {
  const expected = crypto
    .createHmac("sha256", signingSecret)
    .update(JSON.stringify(body))
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler:
app.post("/webhooks/propervid", (req, res) => {
  const signature = req.headers["x-propervid-signature"];

  if (!verifyWebhookSignature(req.body, signature, SIGNING_SECRET)) {
    return res.status(401).send("Invalid signature");
  }

  const { event, jobId, data } = req.body;

  if (event === "video.completed") {
    console.log("Video ready:", data.landscapeUrl);
  }

  res.status(200).send("OK");
});

Retry Policy

If your webhook endpoint returns a non-2xx status code or times out (10s), we retry with exponential backoff:

AttemptDelay
1st retry30 seconds
2nd retry5 minutes
3rd retry (final)30 minutes

Warning

Webhook URLs must use HTTPS. HTTP URLs and private/internal IP addresses are rejected for security.

Smart Polling

When polling for job status, the API returns hints to help you poll efficiently without wasting requests or missing completion.

Polling Fields

FieldDescription
retryAfterRecommended seconds to wait before next poll
estimatedCompletionAtISO 8601 estimated completion timestamp
Retry-AfterHTTP header with same value as retryAfter

Recommended Intervals

Job StatusretryAfterReason
pending60 secondsWaiting for worker pickup
processing (<80%)30 secondsActively rendering
processing (≥80%)10 secondsNearly complete
completed / failedTerminal state, no more polling needed

Average processing time is ~2-8 minutes depending on video length and output formats.

Polling Example

Node.js
async function pollUntilDone(jobId, apiKey) {
  const url = `https://www.propervid.io/api/v1/properties/${jobId}`;
  const headers = { Authorization: `Bearer ${apiKey}` };

  while (true) {
    const res = await fetch(url, { headers });
    const job = await res.json();

    console.log(`Status: ${job.status} | Progress: ${job.progress}%`);

    if (job.status === 'completed') {
      return job.outputs;
    }
    if (job.status === 'failed') {
      throw new Error(`Video failed: ${job.error.message}`);
    }

    // Use the server-recommended wait time
    const waitMs = (job.retryAfter || 30) * 1000;
    await new Promise(resolve => setTimeout(resolve, waitMs));
  }
}

Tip

Each poll request counts toward your rate limit. Using the recommended retryAfter intervals keeps you well within limits for typical usage.

Rate Limiting

API requests are rate limited per API key on a daily basis. Your rate limit is set and agreed during account creation. Rate limit information is included in response headers on every request.

Response Headers

Every API response includes these rate limit headers:

HeaderExampleDescription
X-RateLimit-Limit1000Your daily request limit
X-RateLimit-Remaining987Requests remaining today
X-RateLimit-Reset2025-02-08T00:00:00.000ZWhen the limit resets (next UTC midnight)

Rate Limit Exceeded (429)

When you exceed your limit, the API returns a 429 status code:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again later."
  }
}

Info

Rate limits reset at midnight UTC each day. Check the X-RateLimit-Reset header to know exactly when your limit refreshes.

Voices

ProperVid supports multiple AI voices across different languages and accents. All voices are included with your account. You can preview every voice in the dashboard before using them in your API calls.

British English

en-GB4 voices

Voice IDNameGenderDescription
eldrinEldrinMaleCrisp British baritone
aliciaAliciaFemalePolished global anchor
finleyFinleyMaleArticulate, authoritative anchor
florenceFlorenceMaleAtmospheric British storyteller

American English

en-US8 voices

Voice IDNameGenderDescription
darianDarianMaleWarm, grounded storyteller
taliaTaliaFemaleWarm, soft guide
adamAdamMaleDeep, authoritative
calebCalebMaleTrusted guide
lawrenceLawrenceMaleBright and informative
elaraElaraFemaleCrisp professional narrator
jadeJadeFemaleUpbeat and natural
maisieMaisieFemaleFriendly, casual neighbor

Australian English

en-AU1 voices

Voice IDNameGenderDescription
baxterBaxterMaleDry, calm Aussie

French

fr-FR4 voices

Voice IDNameGenderDescription
paul-kPaul KMaleWarm, engaging narrator
doreDoreFemaleCaptivating, soft
mathieuMathieuMaleSerious, calm
leaLeaFemaleCalm, educational

Spanish

es-ES4 voices

Voice IDNameGenderDescription
el-javierJavierMaleWarm, middle-aged narrator
el-elenaElenaFemaleSoothing, professional
el-danteDanteMaleDynamic, energetic
el-gabrielaGabrielaFemaleWarm, engaging (Mexican Spanish)

Romanian

ro-RO4 voices

Voice IDNameGenderDescription
el-andreiAndreiMaleWarm, sophisticated
el-antoniaAntoniaFemaleYoung, warm, smooth
el-alex-maxAlexMaleMature, rich, inviting tone
el-cristinaCristinaFemaleWarm, expressive storytelling

Voice Emotions

All voices support an optional voiceEmotion parameter that adjusts the delivery tone:

neutral

Professional, straightforward

warm

Friendly, approachable

energetic

Upbeat, enthusiastic

calm

Relaxed, reassuring

cheerful

Positive, bright

Background Music

Choose from 29 royalty-free tracks included with your account. You can preview every track in the dashboard before using them. Use the trackId in your background music configuration, or upload your own audio and use the URL directly.

Available Tracks

29 royalty-free tracks

Track IDNameMood
a-special-morningA Special MorningUplifting & Warm
apricityApricityWarm & Reflective
at-dawnAt DawnPeaceful & Fresh
battleborn-symphonyBattleborn SymphonyEpic & Powerful
calling-my-flightCalling My FlightAdventurous & Free
carried-by-lightCarried By LightUplifting & Ethereal
clean-exitClean ExitSmooth & Modern
dubwise-connectionDubwise ConnectionGroovy & Relaxed
everything-in-motionEverything in MotionDynamic & Flowing
feel-the-beatFeel the BeatEnergetic & Dynamic
flycatcherFlycatcherLight & Playful
hand-covers-bruiseHand Covers BruiseEmotional & Cinematic
i-found-paradiseI Found ParadiseBlissful & Dreamy
in-motionIn MotionDriving & Energetic
iron-pulseIron PulseIndustrial & Bold
la-lune-et-la-mouetteLa Lune et la MouetteRomantic & French
make-me-smileMake Me SmileHappy & Cheerful
meltspaceMeltspaceAmbient & Spacey
movie-timeMovie TimeCinematic & Fun
one-story-and-many-toysOne Story and Many ToysWhimsical & Playful
opusOpusGrand & Classical
oxygen-lsvOxygen LSVAiry & Electronic
paraglidingParaglidingSoaring & Uplifting
tears-in-the-rainTears in the RainMelancholic & Beautiful
the-chosen-oneThe Chosen OneHeroic & Inspiring
the-leaves-that-fallThe Leaves That FallGentle & Autumnal
vostocVostocElectronic & Cosmic
windows-of-silenceWindows of SilenceCalm & Meditative
you-are-heroYou Are HeroTriumphant & Bold

Output Resolutions

Property videos can be rendered in three aspect ratios at up to 1440p. Request one or more output formats when creating a video.

Landscape (16:9)

720p

1280 x 720

1080p

1920 x 1080

1440p

2560 x 1440

Square (1:1)

720p

720 x 720

1080p

1080 x 1080

1440p

1440 x 1440

Portrait (9:16)

720p

720 x 1280

1080p

1080 x 1920

1440p

1440 x 2560

Motion Effects

Motion effects animate each image during its display duration. Set via motionEffect on the Property Videos or Videos endpoints.

zoom

Zoom In

Slowly zooms into the image over its duration. The default for property videos.

zoomOut

Zoom Out

Starts zoomed in, then slowly pulls back to reveal the full image.

kenBurns

Ken Burns

Cinematic combination of slow zoom and horizontal pan, inspired by the classic documentary technique.

Error Codes

Error Response Format

All errors follow a consistent JSON structure:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Human-readable description of what went wrong"
  }
}

All Error Codes

CodeHTTPDescription
MISSING_AUTH401No Authorization header provided
INVALID_AUTH_FORMAT401Authorization header not in Bearer format
MISSING_API_KEY401API key value is empty
INVALID_API_KEY401API key not found or inactive
UNAUTHORIZED401No valid authentication (API key or session)
USER_REQUIRED403Operation requires a linked user account
AI_ACCESS_DENIED403Account does not have access to this AI feature
VALIDATION_ERROR400Request body failed validation
INVALID_VOICE400Voice ID not found
INVALID_MUSIC400Music track ID not found
INVALID_BRAND_KIT400Brand kit UUID not found for this user
JOB_NOT_FOUND404Video job not found or not owned by API key
TEMPLATE_NOT_FOUND404Template not found or not owned by user
NO_FILE400No file provided for upload
INVALID_FILE_TYPE400File type not supported
FILE_TOO_LARGE400File exceeds size limit
RATE_LIMIT_EXCEEDED429Daily request limit exceeded
SUBSCRIPTION_REQUIRED403Feature not available on your current account
PROCESSING_ERRORVideo processing failed (returned on job, not HTTP)
WORKER_ERROR503Failed to connect to video processor
CONFIG_ERROR503Video processing not configured on server
INTERNAL_ERROR500Unexpected server error

ProperVid API Documentation — v1.0.0

Questions? Contact us