Genjutsu Lite 1.0
Replace an object in a source video with one from your reference images, at a lower price.
The lower-priced version of Genjutsu 1.0: object replacement only, at 720p or 1080p (no 480p).
mode | What it does |
|---|---|
replace_object_flash | Object replacement: an object in the source video is replaced with the one in your reference images. |
Create a task
https://api.nanoapi.ai/v1/tasksUse the shared create endpoint with model: "genjutsu-lite-1.0". It works exactly like Genjutsu 1.0: it freezes the cost from your available balance and usually responds in 1–3 seconds with 200 and the task in short form; get the result by webhook or with GET /v1/tasks/{id}.
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | Yes | genjutsu-lite-1.0. |
mode | string | Yes | Always replace_object_flash. |
video_url | string | Yes | Source video, 4–30 seconds. See Media. |
image_urls | string[] | Yes | 1–10 reference images. See Media. |
prompt | string | No | At most 5000 characters. Say which object to replace with what. |
resolution | string | No | 720p (default) or 1080p. Sets the price. |
A mode or resolution this model doesn't support (such as motion_control or 480p) returns 400 invalid_request with param set to that parameter. num_outputs and webhook_url work the same for every model: see Create a task.
curl https://api.nanoapi.ai/v1/tasks \
-H "Authorization: Bearer $NANOAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "genjutsu-lite-1.0",
"mode": "replace_object_flash",
"image_urls": ["https://example.com/monster.png"],
"video_url": "https://example.com/street.mp4",
"prompt": "Replace the woman walking in front with the furry monster from the reference image",
"resolution": "720p",
"webhook_url": "https://example.com/hooks/nanoapi"
}'Response: 200 OK. data is the task in short form, the same as for Genjutsu 1.0; get everything else with GET /v1/tasks/{id}.
{
"code": 200,
"message": "success",
"data": {
"object": "task",
"id": "tk_01jb8z5q4w3e2r1t0y9u8i7o6p",
"model": "genjutsu-lite-1.0",
"status": "queued",
"billing": {
"currency": "USD",
"frozen": "3.51",
"charged": "0.00",
"refunded": "0.00",
"billed_seconds": null
},
"error": null,
"created_at": "2026-10-22T08:30:00Z"
}
}Media
All media is passed as public http(s) URLs. There's no upload endpoint: host the files yourself. URLs are at most 4096 characters and can't point to localhost or private, loopback or reserved addresses.
Source video (video_url) | Reference images (image_urls) | |
|---|---|---|
| Count | 1 | 1–10 |
| Format | A direct download in mp4, mov, webm or mkv | Common image formats |
| Length | 4–30 seconds | – |
| If there's a problem | Can't be opened, too long or too short: the create endpoint returns 400 (see Errors); no task, nothing frozen | Only read when generation runs: if one can't be opened the task fails and the frozen amount is returned in full |
Keep every link reachable until the task finishes, including links that expire.
Pricing
cost = billed seconds of the source video × price per second of the resolution| Resolution | Price per second | 30-second video |
|---|---|---|
| 720p | $0.234 | $7.02 |
| 1080p | $0.468 | $14.04 |
Billed seconds: the length of the source video (the longer of the video and audio tracks), rounded up to a whole second. A few tens of milliseconds of encoding error are ignored.
Example: a 15-second video at 720p freezes $3.51 and is charged $3.51 when it succeeds. How freezing and charging work in general: Billing. Prices can change: GET /v1/products returns the current ones, and billing.frozen in the response is what counts.
Errors
Errors specific to this model. Every error of the create endpoint and how to handle it: Create a task → Errors.
| Status | error.type | When |
|---|---|---|
| 400 | invalid_request | mode isn't replace_object_flash or resolution isn't 720p / 1080p. param names the parameter. |
| 400 | invalid_media | The source video can't be read: the link doesn't open or has expired, isn't public, or isn't a supported video. details.reason says why. |
| 400 | video_too_long | The source video is longer than 30 seconds (details.video_duration). |
| 400 | video_too_short | The source video is shorter than 4 seconds (details.video_duration). |
| 402 | insufficient_balance | Your available balance can't cover the cost (details.required, details.available). |
| 503 | service_unavailable | The price can't be calculated right now. No task was created; retry after Retry-After seconds. |
None of these create a task or freeze anything.