F Fashio Docs
Generation Tools

Photo to Video

Animate a single on-model or product photo into a short video clip — the photo you send becomes the first frame, and the clip plays out from there.

toolId: "ai_videos" 15 credits video no ratio — inherits source framing
Photo to Video result — an on-model photo animated into a short clip

What it does

This tool doesn't re-render anything — the photo you upload is the first frame of the output video. Whatever garment, model and framing you see in that photo is exactly what animates, so there's no risk of the product drifting between the still and the clip. Because of that, ai_videos has no ratio field: the video simply inherits the source photo's framing. That's a deliberate constraint, not a gap — it's what keeps the animated result faithful to the image you approved.

Request body

FieldTypeDescription
toolIdstringrequiredAlways "ai_videos".
images.user_photostringrequiredURL of the still photo to animate — an on-model or product shot. This becomes the video's first frame.
motionPromptstringoptionalFree-text description of the motion or camera move, e.g. "she turns slowly to show the back of the jacket". Omit it and Fashio applies a generic natural motion.
durationnumberoptionalClip length in seconds. Defaults to 5. Check GET /v1/models for the currently supported range — it can change as the underlying video model changes.

Example request

curl -X POST https://api.fashiolabs.com/v1/generations \
  -H "Authorization: Bearer fio_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "toolId": "ai_videos",
    "images": {
      "user_photo": "https://your-cdn.com/on-model-shot.jpg"
    },
    "motionPrompt": "she turns slowly to show the back of the jacket",
    "duration": 5
  }'
const res = await fetch("https://api.fashiolabs.com/v1/generations", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.FASHIO_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    toolId: "ai_videos",
    images: {
      user_photo: "https://your-cdn.com/on-model-shot.jpg",
    },
    motionPrompt: "she turns slowly to show the back of the jacket",
    duration: 5,
  }),
});
const { id } = await res.json();
import os, requests

res = requests.post(
    "https://api.fashiolabs.com/v1/generations",
    headers={"Authorization": f"Bearer {os.environ['FASHIO_API_KEY']}"},
    json={
        "toolId": "ai_videos",
        "images": {
            "user_photo": "https://your-cdn.com/on-model-shot.jpg",
        },
        "motionPrompt": "she turns slowly to show the back of the jacket",
        "duration": 5,
    },
)
job_id = res.json()["id"]

Response

202 Accepted{ "success": true, "id": "8b1e...", "status": "processing" }

Poll GET /v1/generations/:id (see Quickstart) until it completes. For this tool, resultUrls contains one .mp4 URL rather than an image:

200 · completed{ "success": true, "id": "8b1e...", "status": "completed", "resultUrls": ["https://.../result.mp4"], "errorMessage": null }

Common errors

StatusMeaning
400ai_videos: missing required image "user_photo" — required image field wasn't resolvable.
402Insufficient diamonds. Required 15, have <n>.
429Daily request cap reached for this key — see Rate Limits.