Skip to main content

Quickstart: Your First Render in 5 Minutes

This guide takes you from zero to a rendered MP4 file using only curl. No SDK, no setup — just HTTP.

Plan requirement

API access requires a Pro plan or higher. Free-plan users can render videos through the visual editor in the dashboard. See plans →


Prerequisites

  • A ViralSync account (sign up)
  • An API key — create one in Dashboard → Settings → API Keys
  • A project ID — visible in Dashboard → Projects or in the URL when you open a project
  • curl installed (macOS/Linux built-in; Windows: Git Bash or WSL)

Step 1 — Set your credentials

Export your API key and project ID as environment variables so you don't have to repeat them:

export VIRALSYNC_API_KEY="vs_prod_YOUR_API_KEY_HERE"
export VIRALSYNC_PROJECT_ID="proj_abc123"

Test that your key works:

curl -s \
-H "x-api-key: $VIRALSYNC_API_KEY" \
https://api.viralsync.io/v1/me

Expected response:

{
"userId": "user_...",
"plan": "pro",
"email": "you@example.com"
}

If you see a 401 error, double-check your key in the dashboard.


Step 2 — Submit a render job

The core of the ViralSync API is the Movie JSON — a structured description of your video. Here is the smallest possible movie: one scene, one text layer, 5 seconds long.

Save this as movie.json:

{
"kind": "movie",
"projectId": "proj_abc123",
"movie": {
"width": 1920,
"height": 1080,
"fps": 30,
"scenes": [
{
"id": "scene_1",
"duration": 5,
"bgColor": "#1a1a2e",
"layers": [
{
"id": "title",
"type": "text",
"text": "Hello, ViralSync!",
"startTime": 0,
"duration": 5,
"zIndex": 1,
"position": { "x": 360, "y": 460 },
"size": { "width": 1200, "height": 160 },
"fontSize": 80,
"fontWeight": "bold",
"color": "#ffffff",
"textAlign": "center"
}
]
}
]
}
}

Submit it:

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

You'll receive an immediate 202 Accepted response:

{
"jobId": "job_a1b2c3d4e5f6",
"status": "queued"
}

Save the jobId — you'll use it in the next step.

export JOB_ID="job_a1b2c3d4e5f6"

Step 3 — Poll for completion

Check the job status every few seconds until it reaches done:

curl -s \
-H "x-api-key: $VIRALSYNC_API_KEY" \
https://api.viralsync.io/v1/jobs/$JOB_ID

While the job is running, you'll see something like:

{
"jobId": "job_a1b2c3d4e5f6",
"status": "running",
"progress": 0.62,
"phase": "rendering"
}

Once it completes:

{
"jobId": "job_a1b2c3d4e5f6",
"status": "done",
"progress": 1.0,
"outputUrl": "https://r2.viralsync.io/outputs/job_a1b2c3d4e5f6/output.mp4",
"mediaData": {
"duration": 5.0,
"width": 1920,
"height": 1080
}
}
Timing expectation

A 5-second, 1-scene text-only video typically renders in 5–15 seconds on a Pro plan. Longer videos with video/image layers take longer.

Poll loop in bash:

while true; do
RESPONSE=$(curl -s -H "x-api-key: $VIRALSYNC_API_KEY" \
https://api.viralsync.io/v1/jobs/$JOB_ID)
STATUS=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
echo "Status: $STATUS"
if [ "$STATUS" = "done" ] || [ "$STATUS" = "failed" ] || [ "$STATUS" = "cancelled" ]; then
echo "$RESPONSE"
break
fi
sleep 3
done

Step 4 — Download your video

OUTPUT_URL=$(curl -s -H "x-api-key: $VIRALSYNC_API_KEY" \
https://api.viralsync.io/v1/jobs/$JOB_ID \
| python3 -c "import sys,json; print(json.load(sys.stdin)['outputUrl'])")

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

Open my-first-video.mp4 — you should see a 5-second video with white text on a dark background.


What you just built

Let's look at what the movie JSON did:

{
"kind": "movie", // tells the API this is a scene-based render
"projectId": "proj_abc123", // links the job to your project
"movie": {
"width": 1920, "height": 1080, "fps": 30, // 1080p at 30fps
"scenes": [{
"id": "scene_1", // unique identifier (used for caching)
"duration": 5, // this scene is 5 seconds long
"bgColor": "#1a1a2e", // dark blue background
"layers": [{
"id": "title",
"type": "text", // rendered as text (no source URL needed)
"text": "Hello, ViralSync!",
"startTime": 0, // appears at the very start of the scene
"duration": 5, // visible for the full 5 seconds
"zIndex": 1, // rendered on top of any background layers
"position": { "x": 360, "y": 460 }, // top-left of the text box
"size": { "width": 1200, "height": 160 }, // bounding box
"fontSize": 80,
"fontWeight": "bold",
"color": "#ffffff",
"textAlign": "center"
}]
}]
}
}

Adding video and image layers

To render with real media, add a video or image layer with a public source URL:

{
"id": "background_clip",
"type": "video",
"source": "https://cdn.example.com/footage/cityscape.mp4",
"startTime": 0,
"duration": 5,
"zIndex": 0,
"position": { "x": 0, "y": 0 },
"size": { "width": 1920, "height": 1080 },
"mute": true
}
Source URLs must be public

The render worker downloads your media at render time. The source URL must be publicly accessible — no authentication headers, no short-lived presigned URLs. Use CDN URLs.


Next Steps