Image to GIF API
Model ID: modelfold/image-to-gif
Submit once, then poll: prompt optimization → optional subject isolation → 1080p video → GIF/WebP. Standard uses bytedance/v1-pro-fast-image-to-video (5 s); advanced uses wan/2-7-image-to-video (5 s). Animal GIF is a separate tool.
Parameters
| Parameter | Type / values | Default |
|---|---|---|
| image_url | HTTPS URL | required / 必填 |
| prompt | string, 1–2000 characters | required / 必填 |
| cutout | boolean | false |
| cutout_subject | auto | person |
| quality | standard | advanced |
| optimize_prompt | boolean | true |
| output | gif | webp |
| size | 256 | 443 |
| frames | 0 | integer 8–16 |
| transparent | boolean | true when cutout=true; otherwise forced false |
JPEG/PNG/WebP, up to 10 MB and 20 MP. Uploads and outputs expire after 24 hours. cutout=false skips image APIs; optimize_prompt=false skips chat APIs and preserves your prompt, with only required background constraints appended for cutout. Auto isolation uses Recraft; targeted isolation uses an editing mask combined with original pixels, falling back to the edited result only if alignment is poor. WebP is recommended for full color and soft edges. Loops are selected automatically; AI motion and identity can vary.
Quote and billing
GET /api/tools/image-to-gif/quote?quality=standard&cutout=false&optimize_prompt=true
The quote returns credits, the maximum reserved for this request. Submitting reserves that maximum once; on success you are charged for actual usage and the difference is refunded, never above the reserved amount. Any failed step is fully refunded. If expectedCredits differs from the current quote, the API returns 409 and you should fetch a new quote.
| Combination | Max reserved (prompt optimizer on/off) |
|---|---|
| Standard / no cutout | 44 / 44 |
| Standard / auto | 45 / 45 |
| Advanced / no cutout | 145 / 144 |
| Advanced / auto | 146 / 146 |
Targeted cutout (person/animal/object) costs slightly more than auto. Prices are examples; always use /quote.
One submission examples
Both inputs work with every example below. Use your own public image URL and API Key. No second confirmation is needed.
1. Standard / no isolation
curl https://modelfold.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $MODELFOLD_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: image-gif-example-1' \
-d '{"model": "modelfold/image-to-gif", "input": {"image_url": "https://example.com/photo.png", "prompt": "The person waves hello naturally and returns to the initial pose.", "cutout": false, "quality": "standard", "optimize_prompt": false}}'import os, uuid, requests
body = {'model': 'modelfold/image-to-gif', 'input': {'image_url': 'https://example.com/photo.png', 'prompt': 'The person waves hello naturally and returns to the initial pose.', 'cutout': False, 'quality': 'standard', 'optimize_prompt': False}}
r = requests.post("https://modelfold.ai/api/v1/jobs/createTask", json=body,
headers={"Authorization": "Bearer " + os.environ["MODELFOLD_API_KEY"],
"Idempotency-Key": str(uuid.uuid4())})
r.raise_for_status()
print(r.json()["data"]["taskId"])const r = await fetch("https://modelfold.ai/api/v1/jobs/createTask", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.MODELFOLD_API_KEY}`,
"Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID()},
body: JSON.stringify({"model": "modelfold/image-to-gif", "input": {"image_url": "https://example.com/photo.png", "prompt": "The person waves hello naturally and returns to the initial pose.", "cutout": false, "quality": "standard", "optimize_prompt": false}})
});
if (!r.ok) throw new Error(await r.text());
console.log((await r.json()).data.taskId);2. Advanced / transparent
curl https://modelfold.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $MODELFOLD_API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: image-gif-example-2' \
-d '{"model": "modelfold/image-to-gif", "input": {"image_url": "https://example.com/product.png", "prompt": "The product rotates smoothly, returning to its starting angle.", "cutout": true, "cutout_subject": "auto", "quality": "advanced", "transparent": true, "optimize_prompt": true, "output": "both"}}'import os, uuid, requests
body = {'model': 'modelfold/image-to-gif', 'input': {'image_url': 'https://example.com/product.png', 'prompt': 'The product rotates smoothly, returning to its starting angle.', 'cutout': True, 'cutout_subject': 'auto', 'quality': 'advanced', 'transparent': True, 'optimize_prompt': True, 'output': 'both'}}
r = requests.post("https://modelfold.ai/api/v1/jobs/createTask", json=body,
headers={"Authorization": "Bearer " + os.environ["MODELFOLD_API_KEY"],
"Idempotency-Key": str(uuid.uuid4())})
r.raise_for_status()
print(r.json()["data"]["taskId"])const r = await fetch("https://modelfold.ai/api/v1/jobs/createTask", {
method: "POST",
headers: {Authorization: `Bearer ${process.env.MODELFOLD_API_KEY}`,
"Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID()},
body: JSON.stringify({"model": "modelfold/image-to-gif", "input": {"image_url": "https://example.com/product.png", "prompt": "The product rotates smoothly, returning to its starting angle.", "cutout": true, "cutout_subject": "auto", "quality": "advanced", "transparent": true, "optimize_prompt": true, "output": "both"}})
});
if (!r.ok) throw new Error(await r.text());
console.log((await r.json()).data.taskId);Polling and upload
curl "https://modelfold.ai/api/v1/jobs/recordInfo?taskId=TASK_ID" \
-H "Authorization: Bearer $MODELFOLD_API_KEY"Poll every 3–5 seconds until success or fail. progress.stage: optimizing / isolating / animating / rendering / done. resultJson is a JSON string with resultUrls and resultObject (gif, webp, optimizedPrompt, videoModel, expiresAt, size, frames, loop). usage.credits is the final charge only when usage.settled=true.
POST /api/tools/image-to-gif/generate: JSON input directly, or raw image bytes with parameters in the query string. Bearer API Key and Idempotency-Key (1–150 characters) required. This returns the same task; poll /api/tools/image-to-gif/tasks/:id.
Errors and refund
| HTTP | Meaning |
|---|---|
| 400 | Invalid parameters / image |
| 401 | Authentication required |
| 402 | Insufficient credits / Key limit |
| 403 | Account restricted |
| 404 | Task not owned / file expired |
| 409 | Price changed / idempotency conflict |
| 413 | Image exceeds 10 MB |
| 429 | Rate limit / pending tasks |
| 500 | Internal request error |
A task may fail after a successful HTTP submission. Check state and failMsg; terminal failure settles at zero credits and refunds the full reservation, including successful earlier stages. Reusing the same idempotency key with identical input returns the original task.
