Skip to main content

Quickstart: curl

Render a video from the command line using only curl. This guide assumes you have curl installed and a Pro-or-higher API key.


1. Set credentials

export VIRALSYNC_API_KEY="vs_prod_YOUR_API_KEY"
export VIRALSYNC_PROJECT_ID="proj_abc123"

Verify:

curl -s \
-H "x-api-key: $VIRALSYNC_API_KEY" \
https://api.viralsync.io/v1/me
# → { "userId": "user_...", "plan": "pro" }

2. Create the movie JSON

Save this as movie.json:

{
"kind": "movie",
"projectId": "proj_abc123",
"movie": {
"width": 1920,
"height": 1080,
"fps": 30,
"scenes": [
{
"id": "scene_intro",
"duration": 4,
"bgColor": "#0f172a",
"layers": [
{
"id": "headline",
"type": "text",
"text": "Built with ViralSync API",
"startTime": 0,
"duration": 4,
"zIndex": 1,
"position": { "x": 200, "y": 420 },
"size": { "width": 1520, "height": 200 },
"fontSize": 88,
"fontWeight": "bold",
"color": "#00d4ff",
"textAlign": "center"
},
{
"id": "subtitle",
"type": "text",
"text": "Video rendering via JSON + HTTP",
"startTime": 0.5,
"duration": 3.5,
"zIndex": 2,
"position": { "x": 360, "y": 620 },
"size": { "width": 1200, "height": 80 },
"fontSize": 36,
"color": "#94a3b8",
"textAlign": "center"
}
]
},
{
"id": "scene_cta",
"duration": 3,
"bgColor": "#1e293b",
"layers": [
{
"id": "cta",
"type": "text",
"text": "viralsync.io",
"startTime": 0,
"duration": 3,
"zIndex": 1,
"position": { "x": 760, "y": 460 },
"size": { "width": 400, "height": 100 },
"fontSize": 56,
"fontWeight": "600",
"color": "#ffffff",
"textAlign": "center"
}
]
}
]
}
}

3. Submit the render job

RESPONSE=$(curl -s -X POST https://api.viralsync.io/v1/render/jobs \
-H "x-api-key: $VIRALSYNC_API_KEY" \
-H "Content-Type: application/json" \
-d @movie.json)

echo $RESPONSE
# → { "jobId": "job_a1b2c3d4e5f6", "status": "queued" }

export JOB_ID=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['jobId'])")
echo "Job ID: $JOB_ID"

4. Poll until done

while true; do
STATUS_RESPONSE=$(curl -s \
-H "x-api-key: $VIRALSYNC_API_KEY" \
"https://api.viralsync.io/v1/jobs/$JOB_ID")

STATUS=$(echo $STATUS_RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
PROGRESS=$(echo $STATUS_RESPONSE | python3 -c "import sys,json; d=json.load(sys.stdin); print(int((d.get('progress') or 0)*100))")

echo "[$STATUS] ${PROGRESS}%"

if [ "$STATUS" = "done" ]; then
OUTPUT_URL=$(echo $STATUS_RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['outputUrl'])")
echo "✓ Done! Output URL: $OUTPUT_URL"
break
elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
echo "✗ Job ended with status: $STATUS"
echo $STATUS_RESPONSE
break
fi

sleep 3
done

5. Download the video

curl -L "$OUTPUT_URL" -o rendered-video.mp4
echo "Saved to rendered-video.mp4"

Adding a video background

Replace scene_intro.bgColor with a video layer:

{
"id": "bg",
"type": "video",
"source": "https://your-cdn.com/footage/background.mp4",
"startTime": 0,
"duration": 4,
"zIndex": 0,
"position": { "x": 0, "y": 0 },
"size": { "width": 1920, "height": 1080 },
"mute": true,
"transform": { "opacity": 0.5 }
}
Source URLs must be publicly accessible

No authentication required. Use CDN URLs, not presigned URLs with short expiry.


Next steps