FASHN Try-On v1.6 is a virtual try-on (image-to-image) model on hiapi. You hand it two images — a person photo and a garment photo — and it returns one composited, on-body result. This is a developer walkthrough of the fashn try-on api: a real /v1/tasks request I ran end to end, the complete input schema checked against the live validator, and the production details a parameter table leaves out.
Model page and playground: FASHN Try-On v1.6.
1. What you'll build + prerequisites
The flow is the standard async task pattern: one POST creates a task, you poll until it reaches a terminal state, then download the output image.
You need:
- An API key (
sk-...) from the hiapi quick start. - Two publicly reachable image URLs: a person photo for
model_imageand a garment photo forgarment_image.
2. Minimal runnable example
Create the task (curl)
curl -s https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "fashn-tryon-v1.6",
"input": {
"model_image": "https://cdn.example.com/person.jpg",
"garment_image": "https://cdn.example.com/shirt.png"
}
}'
Response — an accepted task, not a finished image:
{"code":200,"data":{"taskId":"tk-hiapi-01M5D3JTGD12PFF3SFM9JRNPAZ"},"message":"success"}
model_image and garment_image are the only required fields; everything else defaults.
Poll for the result (curl)
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-01M5D3JTGD12PFF3SFM9JRNPAZ \
-H "Authorization: Bearer sk-YOUR_KEY"
On completion you get data.status: "success" and the image under data.output[0].url:
{
"code": 200,
"data": {
"status": "success",
"model": "fashn-tryon-v1.6",
"storage": "temp",
"output": [
{ "type": "image", "url": "https://temp.hiapi.ai/.../...-0.png", "expireAt": 1793119887 }
]
},
"message": "success"
}
That expireAt matters: the output sits on temporary storage (about a 7-day TTL). Download or re-host the bytes right away — don't hotlink it.
End to end in Python
import time, requests
API = "https://api.hiapi.ai"
KEY = "sk-YOUR_KEY"
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
def try_on(model_image, garment_image, **opts):
payload = {
"model": "fashn-tryon-v1.6",
"input": {"model_image": model_image, "garment_image": garment_image, **opts},
}
r = requests.post(f"{API}/v1/tasks", json=payload, headers=HEADERS, timeout=30)
r.raise_for_status()
task_id = r.json()["data"]["taskId"]
while True: # poll until terminal
time.sleep(3)
d = requests.get(f"{API}/v1/tasks/{task_id}", headers=HEADERS, timeout=30).json()["data"]
if d.get("status") == "success":
return d["output"][0]["url"]
if d.get("status") in ("fail", "error"):
raise RuntimeError(f"task failed: {d}")
url = try_on(
"https://cdn.example.com/person.jpg",
"https://cdn.example.com/shirt.png",
category="tops", mode="quality",
)
print(url)
3. The input schema (verified against the live validator)
fashn-tryon-v1.6 uses a closed schema — any field not listed below is rejected, so you can't smuggle in native FASHN extras that hiapi doesn't expose.
| field | required | type | accepted values |
|---|---|---|---|
model_image | yes | string (URL) | person photo |
garment_image | yes | string (URL) | garment photo |
category | no | enum | tops, bottoms, one-pieces, auto |
mode | no | enum | performance, balanced, quality |
garment_photo_type | no | enum | auto, model, flat-lay |
output_format | no | enum | png, jpeg |
seed | no | integer | for reproducibility |
segmentation_free | no | boolean | — |
How I know these: posting {"model":"fashn-tryon-v1.6","input":{}} returns
invalid input: model_image: missing required field "model_image"; garment_image: missing required field "garment_image"
and every enum above came from sending a bad value, e.g. mode: value must be one of 'performance', 'balanced', 'quality'. Passing num_samples, num_images, or any field outside the table returns additional properties '...' not allowed — there is no multi-sample option. One request returns one image; vary seed across calls for different results.
4. Production patterns
- Validation happens before billing. Bad input returns HTTP
400with the envelope{"code":400,"data":null,"error_code":"INVALID_REQUEST","message":"invalid input: ..."}, and no task is created — malformed requests don't cost you. A valid request returnscode:200with ataskId. - Re-poll, don't re-submit. Every
POST /v1/taskscreates a new (billable) task. If a poll request times out, keep polling thetaskIdyou already have; a dropped response doesn't mean the task failed. - Callbacks instead of polling. For batches you can register a callback so hiapi notifies you when the task reaches a final state rather than polling it yourself — see the Unified Async API reference for the exact field. The example above uses polling.
5. What one real run looked like
I ran the minimal request above — a 768×1152 person photo and a 768×1152 garment image, with mode and category omitted:
- Latency: ~13 seconds from
createdtocompletedon the task object. - Output: a single PNG at 768×1152, i.e. a portrait image. The model page notes the output size tracks the person photo (its verified runs measured both 972×1296 and 768×1152), and this run is consistent with that — there is no
width/height/aspect_ratiofield, so the person photo's dimensions decide the output size. - Status path: the poll showed
archivingand thensuccess;storagewastemp. - Defaults are real. Omitting
modeandcategorystill succeeded, so the two image URLs genuinely are the only inputs you must supply — the model auto-detects the garment type.
Pricing is per output image and does not change with the mode you pick; check the current rate on the pricing page.
Related
- FASHN Try-On v1.6 model page & playground
- Unified Async (Task) API reference
- Quick start — get an API key
- Pricing
FAQ
Which fields are required? Only model_image and garment_image, both as publicly reachable URLs.
Can I get several variations from one call? No — num_samples and num_images are rejected by the schema. One request returns one image; change seed between calls for variety.
How do I control the output size? You don't set it directly. The result follows the person photo's dimensions — my 768×1152 input produced a 768×1152 output.
How long is the result URL valid? The output is on temporary storage with an expireAt (around 7 days). Download the bytes immediately.
Does the quality mode change the price? No — billing is per output image regardless of performance, balanced, or quality.





