Listing Reel Maker API
Documentation for POST /api/reels and GET /api/reels.
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. Supports JSON (preferred) and multipart/form-data (legacy).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.
Create a Reel (JSON mode — recommended)
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; seconds at which caption fades out
"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
"voiceType": "kate" // required only if script present; "kate" | "steve"
}Constraints & Validation
- photos: 3–15 required (max 15). Combined assets (photos + logo + headshot) ≤ 17 URLs.
- musicType: required (e.g.,
Modern,Chill, etc.). - details: optional.
- 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 ifscriptis provided).
Credits & Cost
Each job deducts credits before processing:
- Base:
number of photos(3–15) - +1 if headshot & headshotDetails are provided
- +1 if
scriptis provided (AI voiceover enabled)
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-5 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, or "multipart/form-data"." }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 (multipart/form-data — legacy)
This mode uploads binary files in the same request. It is convenient but more likely to hit serverless limits on large payloads. If you see 413 errors, switch to JSON mode.
Note: The logo and headshot fields can be sent as either file uploads or as string URLs. If you send a URL string, the server will download it automatically.
Request Fields
- photos: 3–15 required files (uploaded as binary)
- logo: Optional file upload or HTTP(S) URL string
- headshot: Optional file upload or HTTP(S) URL string (requires headshotDetails)
- headshotDetails: Text string (required if headshot is provided)
- details: Optional text string
- displayText: Optional text string
- captionFadeOutSeconds: Optional number (seconds at which caption fades out)
- musicType: Required text string
- script: Optional text string (triggers voiceover, +1 credit)
- voiceType: Optional text string ("kate" | "steve", required if script present)
cURL Example (with file uploads)
curl -X POST \
-H "X-API-Key: $LRM_API_TOKEN" \
-F "photos=@/path/1.jpg" \
-F "photos=@/path/2.jpg" \
-F "photos=@/path/3.jpg" \
-F "logo=@/path/logo.png" \
-F "headshot=@/path/agent.jpg" \
-F "headshotDetails=Jane Doe — Broker" \
-F "details=3 bed, 2 bath…" \
-F "displayText=Open House Sat 2–4" \
-F "captionFadeOutSeconds=5.0" \
-F "musicType=Modern" \
-F "script=Thirty to forty word voiceover text…" \
-F "voiceType=kate" \
https://www.listingreelmaker.com/api/reelscURL Example (with logo as URL string)
curl -X POST \
-H "X-API-Key: $LRM_API_TOKEN" \
-F "photos=@/path/1.jpg" \
-F "photos=@/path/2.jpg" \
-F "photos=@/path/3.jpg" \
-F "logo=https://www.listingreelmaker.com/logo.png" \
-F "details=3 bed, 2 bath…" \
-F "displayText=Open House Sat 2–4" \
-F "captionFadeOutSeconds=5.0" \
-F "musicType=Modern" \
https://www.listingreelmaker.com/api/reelsStatus & 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, orfailed
Response Fields
id— Job IDstatus— One of:generating,complete,failedurl— Presigned download URL (null if not ready)createdAt— ISO 8601 timestamptitle— Optional title fromdisplayTextordetailsuserId— User ID (in single job responses)motionUrls— Array of preview video URLs (only when status isgenerating)
Field Reference
photosrequiredlogoheadshotheadshotDetailsdetailsdisplayTextcaptionFadeOutSecondsscriptvoiceTypemusicTyperequiredCommon Errors & Troubleshooting
- 401 Unauthorized: Missing/invalid API Token. Ensure the
X-API-Keyheader (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).
- 413 Payload too large: Use JSON mode and host images, or pre-upload to your S3.
- 400 musicType is required: Include a non-empty
musicTypefield. - 400 Asset ingest failed: A provided URL could not be fetched (4xx/5xx). Verify public reachability.
- 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.