Introduction
Video Head Swap takes the task id of an analysis, the positions you picked from its preview images and one to three reference photos for each, and returns the clip with those heads replaced. Hair, head shape and identity change; the body, the wardrobe, the motion, the framing and the original audio track stay as shot. Heads you do not list are left untouched.
Video Head Swap works in two calls. The first tracks every head in a clip of 5 to 30 seconds and hands back one preview still per head, in a fixed order. The second takes the positions you picked plus one to three reference photos for each, and returns the clip with those heads replaced and the original audio kept.
This two-step workflow starts with Video Head Swap Analysis and continues with Video Head Swap.
Key features & highlights
You choose who changes
Most swap endpoints have to guess which person you meant. Here the first call shows you every head it found, numbered, and the second call touches only the numbers you send back. On a clip with four people you can change one of them and leave the other three exactly as shot.
Keep the video and the resolution identical
Video Head Swap is a pair of endpoints, not one. The first call, video-analyze, tracks every head in a clip of 5 to 30 seconds and returns one preview still per head in a fixed order, charged once per request whatever the clip's length and however many heads it finds. The second call, video-edit, takes the task id of that analysis, the positions you picked and one to three reference photos for each, and returns a single clip with the original audio track intact, billed per second of footage at 480p or 720p. You never see the tracking data itself: you work with your own task id and with zero-based positions that line up with the preview images you were shown. The same video and the same resolution have to be used in both calls, and the second call is rejected rather than letting a mismatch through quietly.
Request parameters
| Parameter | Required | Description |
|---|---|---|
analysis_task_id | Yes | The task id of the analyse call for this clip. Its preview images are listed in the same order as |
swap_targets | Yes | One entry per head you want replaced; heads you leave out are not touched. |
video_url | No | Optional. Leave it out and the video from the analysis is used. at least 1 characters |
resolution | No | Must match the resolution the analysis ran at. This is also the field that sets the price tier. |
seed | No | Random seed; zero requests a random seed. The same seed makes a fair comparison when you change one other thing, it does not promise an identical frame-for-frame result. |
Pricing
Billed in whole 5-second blocks of the source clip, so a 6-second clip costs the same as 10 seconds. The estimate before submission uses the actual length of a clip you uploaded, or the 30-second maximum for a video URL; any difference is released when the task settles.
| Specification | Price |
|---|---|
| $0.064 / second |
| $0.12 / second |
Use cases
Recast a shot that already works
Keep the take whose lighting, blocking and camera move are already signed off, and put a different head on the performer instead of regenerating the whole shot and losing the performance you had.
Any subject matter, with a consented performer
Nothing about the request changes with what the footage shows. The authorisation requirement in the limits below does not change either: it is a hard condition, not a formality.
One person through a generated series
Generate a batch of clips with any video model, analyse each one, then carry the same consented head across all of them so the series reads as a single person.
Crowds where only one person changes
Analyse a scene with several people on screen, look at the previews, and send back only the position you meant. Everyone else is left untouched.
Prompt guide & pro tips
Confirm you hold the rights to every head involved
The footage and the reference photos both depict people. You need authorisation for the likeness you are moving and for the footage you are moving it into. Keep the release with the job record.
Analyse first, then read the preview order
The analysis returns preview stills in a fixed order. The first image is object_index 0, the second is 1, and so on. That position is the only handle you need: send it back in swap_targets.
Keep the video and the resolution identical
Both calls have to run on the same video at the same resolution. Leave video_url out of the second call and it is copied from the analysis; if you do send it, it has to match. A different resolution is rejected rather than quietly re-tracked.
API quick start
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "spicyapi/head-swap-video-v1/video-edit",
"input": {
"analysis_task_id": "example",
"resolution": "720p",
"swap_targets": [
{
"image_urls": [
"example"
],
"object_index": 0
}
]
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"
See the API reference for authentication, the complete schema, polling, and error handling.

