Loading…

Listing Reel Maker API

Documentation for POST /api/reels, GET /api/reels, and POST /api/reels/edit.

Base URL: https://www.listingreelmaker.com/api/reels

Overview

The Reels API lets you create a new video “reel” generation job from your listing assets and later check its status or download the rendered MP4. For reliability and speed, we recommend the JSON+URL workflow where you send asset URLs (or S3 keys) instead of uploading large files in the same request.

API Token & Access

API access is disabled by default. To enable it, email support@listingreelmaker.com. Once enabled, you will see a Get API token button in the app header.

Include your token with every request using the header X-API-Key: <YOUR_API_TOKEN>.

Endpoint Summary

  • POST /api/reels — Create a reel job with JSON asset URLs or a Zillow listing URL.
  • GET /api/reels — List your jobs with status and URLs (when available).
  • GET /api/reels?jobId=<id> — Fetch status for a single job and a preview/final URL if available.
  • POST /api/reels/edit — Create an edited version from an existing reel.

Create a Reel (JSON mode)

Send Content-Type: application/json with public HTTP(S) URLs for your assets.

Request Body

{
  "photos": [
    "https://example.com/listing/1.jpg",
    "https://example.com/listing/2.jpg",
    "https://example.com/listing/3.jpg"
  ],
  "logo": "https://example.com/brand/logo.png",            // optional
  "headshot": "https://example.com/agent.jpg",             // optional
  "headshotDetails": "Jane Doe — Broker | (555) 555-1212", // required if headshot is present
  "details": "3 bed, 2 bath, renovated kitchen, fenced yard…", // optional
  "displayText": "Open House Sat 2–4",                     // optional
  "captionFadeOutSeconds": 5.0,                           // optional; ignored when textOverlays is present
  "textOverlays": [],                                     // optional advanced overlay payload
  "headshotTextStyle": {},                                // optional headshot badge style
  "script": "Thirty to forty word voiceover text…",        // optional; if present we generate TTS (+1 credit)
  "musicType": "Modern",                                   // required, same options as in the app, Upbeat, Luxury, Warm, Bright, Chill, Modern, Cinematic, Acoustic, normalized to lowercase
  "musicKey": "tracks/custom.mp3",                         // optional specific track key
  "voiceType": "kate",                                     // required only if script present; "kate" | "steve"
  "outputFormat": "portrait",                              // optional; "portrait" (default) | "landscape"
  "enableLowResUpscale": false                             // optional; +1 credit
}

Constraints & Validation

  • photos: 3–15 required (max 15). Combined assets (photos + logo + headshot) ≤ 17 URLs.
  • zillowUrl: can be sent instead of photos. The API selects 3–15 photos automatically.
  • musicType: required for photo URL jobs. Zillow jobs default to Modern if omitted.
  • details: optional.
  • outputFormat: optional. Use portrait for 1080×1920 or landscape for 1920×1080. Edits keep the source reel format.
  • captionFadeOutSeconds: optional number. If provided, the caption will fade out starting at this time (in seconds). If omitted, the caption will remain visible for the entire video.
  • headshot and headshotDetails must be provided together or omitted together.
  • voiceType allowed values: kate, steve (only if script is provided).

Credits & Cost

Each job deducts credits before processing:

  • Base: number of photos (3–15)
  • +1 if headshot & headshotDetails are provided
  • +1 if script is provided (AI voiceover enabled)
  • +1 if enableLowResUpscale is true

If the job fails to start, we refund the credits automatically.

Successful Response

{
  "jobId": "b2e8d1c4-53a0-468f-8bce-7d3a1a3fae9a",
  "costCharged": 5
}

Error Responses

// 400 Bad Request
{ "error": "musicType is required" }

// 400 Bad Request
{ "error": "3-15 photos required" }

// 400 Bad Request
{ "error": "Headshot requires both image and details, or neither." }

// 401 Unauthorized
{ "error": "Unauthorized" }

// 402 Payment Required (insufficient credits)
{ "error": "Insufficient credits", "required": 5, "have": 3 }

// 415 Unsupported Media Type
{ "error": "Unsupported Content-Type. Use application/json with URLs/keys." }

cURL Example (JSON)

curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $LRM_API_TOKEN" \
  https://www.listingreelmaker.com/api/reels \
  -d '{
    "photos": [
      "https://example.com/img/1.jpg",
      "https://example.com/img/2.jpg",
      "https://example.com/img/3.jpg"
    ],
    "details": "3 bed, 2 bath…",
    "displayText": "Open House Sat 2–4",
    "captionFadeOutSeconds": 5.0,
    "musicType": "Modern",
    "script": "Thirty to forty word voiceover text…",
    "voiceType": "kate"
  }'

JavaScript fetch Example

const res = await fetch("/api/reels", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": process.env.NEXT_PUBLIC_LRM_API_TOKEN!
  },
  body: JSON.stringify({
    photos: ["https://example.com/1.jpg","https://example.com/2.jpg","https://example.com/3.jpg"],
    details: "3 bed, 2 bath…",
    displayText: "Open House Sat 2–4",
    captionFadeOutSeconds: 5.0,
    musicType: "Modern",
    script: "Thirty to forty word voiceover text…",
    voiceType: "steve"
  })
});
const data = await res.json();
console.log(data.jobId);

Python requests Example

import os, requests
BASE = "https://www.listingreelmaker.com/api/reels"
API_KEY = os.environ["LRM_API_TOKEN"]

payload = {
  "photos": [
    "https://example.com/1.jpg",
    "https://example.com/2.jpg",
    "https://example.com/3.jpg"
  ],
  "details": "3 bed, 2 bath…",
  "displayText": "Open House Sat 2–4",
  "captionFadeOutSeconds": 5.0,
  "musicType": "Modern",
  "script": "Thirty to forty word voiceover text…",
  "voiceType": "kate"
}

r = requests.post(BASE, json=payload, headers={"X-API-Key": API_KEY})
r.raise_for_status()
print(r.json())

Create a Reel from a Zillow Link

Send a Zillow listing URL and the API will scrape listing details, pick the best photos, generate a short caption and voiceover script, ingest the images, and start the reel job.

{
  "zillowUrl": "https://www.zillow.com/homedetails/123-Main-St_123456_zpid/",
  "photoCount": 10,                 // optional max; 3-15, default 10
  "strictPhotoCount": false,         // optional; true forces exactly photoCount when enough photos exist
  "musicType": "Modern",            // optional for Zillow; defaults to Modern
  "voiceType": "kate",              // optional; "kate" | "steve"
  "includeVoiceover": true,          // optional; default true, +1 credit when script is generated
  "autoDraft": true,                 // optional; default true
  "objective": "luxury open house"   // optional prompt hint
}

You can still override any generated field by passing details, displayText, script, musicType, textOverlays, logo, or headshot fields in the same request.

cURL Example (Zillow)

curl -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $LRM_API_TOKEN" \
  https://www.listingreelmaker.com/api/reels \
  -d '{
    "zillowUrl": "https://www.zillow.com/homedetails/123-Main-St_123456_zpid/",
    "photoCount": 10,
    "musicType": "Modern",
    "voiceType": "kate"
  }'

Successful response includes the job ID and source listing metadata:

{
  "jobId": "b2e8d1c4-53a0-468f-8bce-7d3a1a3fae9a",
  "costCharged": 11,
  "sourceListing": {
    "provider": "zillow",
    "url": "https://www.zillow.com/homedetails/123-Main-St_123456_zpid/",
    "address": "123 Main St, Austin, TX 78701",
    "price": "$750,000",
    "scrapedPhotoCount": 32,
    "selectedPhotoCount": 10
  }
}

Status & Downloads

Poll a single job

Use GET /api/reels?jobId=<id> to retrieve status and URLs.

curl -H "X-API-Key: $LRM_API_TOKEN" \
"https://www.listingreelmaker.com/api/reels?jobId=$JOB_ID"

Possible responses:

{ "status": "generating", "userId": "…", "motionUrls": ["https://…/motion1.mp4", "…"] }
{ "status": "failed", "userId": "…" }
{ "status": "ready", "url": "https://…/final.mp4?X-Amz-SignedHeaders=…", "userId": "…" }

Note: When status is generating, the response may include a motionUrls array with preview videos that can be displayed while waiting for the final render.

List recent jobs

Use GET /api/reels to list your jobs. Supports pagination and status filtering.

# List all jobs (backward compatible array format)
curl -H "X-API-Key: $LRM_API_TOKEN" \
https://www.listingreelmaker.com/api/reels

# With pagination
curl -H "X-API-Key: $LRM_API_TOKEN" \
"https://www.listingreelmaker.com/api/reels?page=1&limit=20"

# Filter by status
curl -H "X-API-Key: $LRM_API_TOKEN" \
"https://www.listingreelmaker.com/api/reels?status=complete&page=1&limit=20"

Response formats:

// Without pagination params (backward compatible)
[
  { "id": "…", "status": "generating", "url": null, "createdAt": "2024-01-01T00:00:00Z" },
  { "id": "…", "status": "complete", "url": "https://…/final.mp4?…", "createdAt": "2024-01-01T00:00:00Z", "title": "Open House Sat 2–4" }
]

// With pagination params
{
  "reels": [
    { "id": "…", "status": "complete", "url": "https://…/final.mp4?…", "createdAt": "2024-01-01T00:00:00Z", "title": "Open House Sat 2–4" }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 45,
    "totalPages": 3,
    "hasMore": true
  }
}

Query Parameters

  • jobId — Fetch a single job by ID (returns object, not array)
  • page — Page number (default: 1)
  • limit — Items per page (default: 50, max: 100)
  • status — Filter by status: generating, complete, or failed

Response Fields

  • id — Job ID
  • status — One of: generating, complete, failed
  • url — Presigned download URL (null if not ready)
  • createdAt — ISO 8601 timestamp
  • title — Optional title from displayText or details
  • userId — User ID (in single job responses)
  • motionUrls — Array of preview video URLs (only when status is generating)

Edit an Existing Reel

Use POST /api/reels/edit to create a new version from a completed reel. Pass the source job ID plus any fields you want to change.

{
  "sourceJobId": "existing-job-id",
  "photos": ["https://example.com/new-1.jpg", "https://example.com/new-2.jpg", "https://example.com/new-3.jpg"],
  "displayText": "New Open House",
  "textOverlays": [],
  "musicType": "Luxury",
  "script": "Updated thirty to forty word narration...",
  "voiceType": "kate",
  "idempotencyKey": "client-generated-key"
}

Edited versions are returned as normal jobs and can be polled with GET /api/reels?jobId=<id>.

Field Reference

photosrequired
string[]
3–15 required unless zillowUrl is provided; HTTP(S) URLs or our S3 keys.
zillowUrl
string
Optional Zillow listing URL. When present, the API scrapes listing data and selects photos automatically.
listingUrl
string
Alias for zillowUrl.
photoCount
number
Optional max for Zillow jobs; 3–15, default 10. The API may use fewer weak photos for a cleaner reel.
strictPhotoCount
boolean
Optional for Zillow jobs; true forces exactly photoCount when enough photos exist.
autoDraft
boolean
Optional for Zillow jobs; default true. Generates caption and script from listing details.
includeVoiceover
boolean
Optional for Zillow jobs; default true. Set false to skip generated narration.
objective
string
Optional prompt hint for Zillow auto drafts.
logo
string
Optional; URL or S3 key.
headshot
string
Optional; requires headshotDetails if present.
headshotDetails
string
Optional; required if headshot present.
headshotTextStyle
object
Optional headshot badge style payload.
details
string
Optional text used for captions/visuals.
displayText
string
Optional on-video text (e.g., Open House).
captionFadeOutSeconds
number
Optional. Seconds at which the caption fades out. Ignored when textOverlays is present.
textOverlays
object[]
Optional advanced overlay payload used by the app editor.
script
string
Optional 30–40 word narration. Triggers AI voiceover and +1 credit.
voiceType
"kate" | "steve"
Required only if script present.
musicTyperequired
string
Required for photo jobs; Zillow jobs default to Modern. Normalized (e.g., 'modern').
musicKey
string
Optional specific music track key.
enableLowResUpscale
boolean
Optional AI upscale for low-resolution photos. Adds +1 credit.

Common Errors & Troubleshooting

  • 401 Unauthorized: Missing/invalid API Token. Ensure the X-API-Key header (or ?api_key= when testing) is present and correct.
  • 402 Insufficient credits: Top up credits or reduce optional items (e.g., remove headshot or script).
  • 400 musicType is required: Include a non-empty musicType field.
  • 400 Asset ingest failed: A provided URL could not be fetched (4xx/5xx). Verify public reachability.
  • 400 ZILLOW_SCRAPE_FAILED: Zillow listing data could not be loaded. Verify the URL is public and includes a Zillow property ID.
  • 400 Too many assets: Combined assets (photos + logo + headshot) exceed the maximum of 17 URLs.
  • 400 3-15 photos required: Photo count must be between 3 and 15 inclusive.