Capability · Apparel
Virtual try-on API for apparel
In one sentence
Photta's virtual try-on API takes a flat-lay apparel image, a mannequin ID and a pose ID and returns a 2K or 4K on-model photo. POST the job, poll every 3–5 seconds, download when status is completed.
- Typical time: 1.5–4 min
- Credits: 5 credits at 2K · 6 credits at 4K
- Processing: async, polling
- Limits: 600 requests/min
- Authentication: Bearer key
Every figure on this page comes from the Photta API docs · checked
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.statusimport os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]
At a glance
At a glance
- Endpoint
- POST /api/v1/tryon/apparel
- Authentication
- Bearer API key
- Processing
- Asynchronous — poll the status endpoint
- Typical time
- 1.5–4 min
- Credits
- 5 credits at 2K · 6 credits at 4K
- Aspect ratios
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Input limits
- Up to 10 MB per image; JPEG, PNG, WebP
- Idempotent
- No
Request and response
Request
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/apparel \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')const res = await fetch("https://api.photta.app/api/v1/tryon/apparel", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
}),
});
const { data } = await res.json(); // data.id, data.statusimport os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/apparel",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"product_type": "top",
"product_images": [
"https://cdn.yourstore.com/products/shirt-front.jpg"
],
"product_back_image": "https://cdn.yourstore.com/products/shirt-back.jpg",
"product_category": "t_shirt",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"background": "https://cdn.yourstore.com/backgrounds/studio-loft.jpg",
"lock_background": True,
"resolution": "2K",
"aspect_ratio": "3:4",
"body_size": "M",
"expression": "neutral",
"user_instruction": "Keep the collar pattern crisp and centered."
},
)
data = res.json()["data"] # data["id"], data["status"]202 Accepted / Completed
{
"data": {
"id": "try_abc123",
"status": "processing",
"product_type": "top",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"lock_background": true,
"resolution": "2K",
"aspect_ratio": "3:4",
"credits_used": 5,
"created_at": "2026-04-10T12:00:00Z"
},
"request_id": "req_xyz789"
}{
"data": {
"id": "try_abc123",
"status": "completed",
"product_type": "top",
"mannequin_id": "mnk_f3a9b1",
"pose_id": "pose_c2d4e5",
"resolution": "2K",
"aspect_ratio": "3:4",
"output_url": "https://cdn.photta.app/generated/try_abc123.jpg",
"thumbnail_url": "https://cdn.photta.app/generated/try_abc123-thumb.jpg",
"credits_used": 5,
"created_at": "2026-04-10T12:00:00Z",
"completed_at": "2026-04-10T12:01:15Z",
"duration_ms": 75000
},
"request_id": "req_abc001"
}Request parameters
product_typeType: stringRequired
Type of garment.
Values:topbottomtop_and_bottomone_pieceproduct_imagesType: array[string]Required
Array of image URLs or base64 data URIs. The first entry is the FRONT image and is required. Not used when product_type is "top_and_bottom".
product_back_imageType: string
Optional URL or base64 data URI for the BACK of the garment. When supplied, the pipeline auto-switches to the back image whenever the selected pose is back-facing (Back / BackCloseUp). Not used when product_type is "top_and_bottom".
top_imageType: string
Front image of the top garment. Required when product_type is "top_and_bottom".
top_back_imageType: string
Optional back image of the top garment. Auto-selected on back-facing poses when present.
bottom_imageType: string
Front image of the bottom garment. Required when product_type is "top_and_bottom".
bottom_back_imageType: string
Optional back image of the bottom garment. Auto-selected on back-facing poses when present.
mannequin_idType: stringRequired
ID of the mannequin to wear the garment. Use GET /api/v1/mannequins to list available options.
pose_idType: stringRequired
ID of the pose. Use GET /api/v1/poses to list available options. The pose dictates the framing of the output — what's in frame, whether the face/feet are visible, full body vs half body, etc.
backgroundType: string
Optional URL or base64 data URI to a background photo. Anything that is not a URL or data: URI is rejected with HTTP 400. When omitted, an editorial neutral backdrop is used.
lock_backgroundType: boolean
When true, the supplied background image is reproduced faithfully (locked) instead of being treated as loose inspiration. Requires the background field — returns 400 if set without a background. Echoed back in the response object.
= false
resolutionType: string
Output resolution. 4K cannot be combined with aspect_ratio 1:1 — that combination returns 400.
= 2K
Values:2K4Kaspect_ratioType: string
Output aspect ratio. 1:1 cannot be combined with resolution 4K — that combination returns 400.
= 3:4
Values:3:41:14:39:1616:9body_sizeType: string
Body size of the mannequin.
= M
Values:XSSMLXLXXLexpressionType: string
Facial expression.
= neutral
Values:neutralhappyserioussmilingfootwear_urlType: string
URL or base64 of a custom footwear image. The pipeline always stages the footwear when supplied; the prompt's pose-authority block decides whether to render it (poses that don't show feet drop it cleanly).
user_instructionType: string
Free-form refinement, e.g. "preserve the seam pattern across the shoulder", "keep the collar contrast strong". Capped at 500 characters server-side; longer strings are silently truncated. Useful for brand-specific details that need an extra nudge.
product_categoryType: string
Optional silhouette anchor for the garment (e.g. "t_shirt", "jeans", "blazer", "midi_dress"). Helps disambiguate the structure of the garment when the silhouette is ambiguous from the photo alone. Used for product_type "top", "bottom", and "one_piece".
top_categoryType: string
Silhouette anchor for the top half. Only valid when product_type is "top_and_bottom".
bottom_categoryType: string
Silhouette anchor for the bottom half. Only valid when product_type is "top_and_bottom".
lengthType: string
Garment length key for product_type "top", "bottom", or "one_piece". List available values with GET /api/v1/garment-attributes?type=length&garment_type={product_type}.
fitType: string
Garment fit key for product_type "top", "bottom", or "one_piece". List available values with GET /api/v1/garment-attributes?type=fit&garment_type={product_type}.
top_lengthType: string
Top length key. Only valid when product_type is "top_and_bottom". List with GET /api/v1/garment-attributes?type=length&garment_type=top.
top_fitType: string
Top fit key. Only valid when product_type is "top_and_bottom". List with GET /api/v1/garment-attributes?type=fit&garment_type=top.
bottom_lengthType: string
Bottom length key. Only valid when product_type is "top_and_bottom". List with GET /api/v1/garment-attributes?type=length&garment_type=bottom.
bottom_fitType: string
Bottom fit key. Only valid when product_type is "top_and_bottom". List with GET /api/v1/garment-attributes?type=fit&garment_type=bottom.
Errors
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
Limits
- 600 requests per minute per API key (Fixed window; the limit is the same on every plan)
- A 429 carries Retry-After: 30 seconds
- Up to 10 MB per image
- Formats: JPEG, PNG, WebP
- Concurrent batches per plan: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Polling only — the API sends no webhooks.
Five steps, one product photo
Pick a mannequin, submit the job, poll until it's done, download the result.
Step 1
Generate an API key
Sign up at ai.photta.app, open the Developers tab, click Generate API key. Live keys start with `photta_live_`. Put the key in `PHOTTA_API_KEY` — never commit it.
Step 2
Pick a mannequin and a pose
GET `/api/v1/mannequins` to list available options. GET `/api/v1/poses` for the framing. Both IDs go into the try-on request.
Step 3
POST the try-on job
Send a POST to `/api/v1/tryon/apparel` with `product_type`, `product_images`, `mannequin_id`, `pose_id` and optional `resolution` and `aspect_ratio`. The API returns 202 Accepted with a generation ID.
Step 4
Poll until the job completes
GET `/api/v1/tryon/apparel/:id` every 3 seconds. When `data.status` flips to `completed`, the payload includes `output_url` and `thumbnail_url`. Put an upper bound so a stuck job can't hang your request.
Step 5
Download and persist
Fetch the bytes from `output_url` and store them in your own object storage. The CDN URL is stable but your product shouldn't depend on it for rendering.
Same endpoint in Node.js, Python and cURL
Node.js
Virtual try-on API in Node.js
Call Photta's virtual try-on API from a Node.js backend with native fetch. No SDK required: store your key, submit the job, poll for the result.
ReadPython
Virtual try-on API in Python
Call Photta's virtual try-on API in Python with the requests library. Thirty-line wrapper, async-friendly via httpx, works in Django, FastAPI and Celery.
ReadcURL
Virtual try-on API with cURL
Call Photta's virtual try-on API directly from the shell with cURL. Submit, poll, download — every snippet pairs with jq for scripted pipelines.
Read
Questions developers ask before shipping apparel try-on
What is Photta's virtual try-on API?
A REST endpoint that takes a flat-lay product image and a mannequin ID and returns a photorealistic on-model image. Same pipeline as Photta's consumer app. Four product types are supported: top, bottom, top+bottom, one-piece.
How much does it cost per call?
5 credits for a 2K result, 6 credits for 4K. Credits come with your subscription and can be topped up. Failed generations don't cost credits — they're refunded.
How long does a generation take?
Typical completion is 1.5 to 4 minutes, measured end to end. The POST returns a generation ID in under a second; the GPU work happens in the background while you poll.
What product types are supported?
Four: `top`, `bottom`, `top_and_bottom`, `one_piece`. Each expects a different `product_images` shape — for example `top_and_bottom` wants both `top_image` and `bottom_image` URLs.
Can I use my own mannequin?
Yes. Upload a mannequin photo with `POST /api/v1/mannequins` or generate a new AI mannequin with `POST /api/v1/mannequins/generate`. The returned ID plugs straight into the try-on request.
How do I poll for the result?
GET `/api/v1/tryon/apparel/:id` every 3 to 5 seconds until `data.status` is `completed` or `failed`. Put an upper bound on attempts — 120 × 3s covers the documented window with room to spare.
Related capabilities
Capabilities
Jewelry try-on API for necklaces, rings, bracelets and earrings
Place necklaces, rings, bracelets and earrings on AI models via REST. 5 credits at 2K, close-up mannequins built-in, reflection-aware rendering from the Photta docs.
See the endpointCapabilities
Ghost mannequin API for hollow-man product photos
AI ghost mannequin endpoint. Remove the mannequin from a garment photo and preserve interior detail. 3D or flat-lay, batch processing, 4 credits at 2K.
See the endpointBuild
Build a virtual try-on feature for your app
End-to-end recipe for shipping a virtual try-on feature with the Photta API: upload, submit, poll from a worker, render the result. TypeScript + server-only patterns.
See the endpointBuild
Add virtual try-on to an iOS or Android app
How to add AI virtual try-on to a native iOS or Android app using the Photta API: never ship the key to the device, proxy through your backend, mirror job status.
See the endpointCompare
Photta vs FASHN — AI fashion API, side by side
Photta and FASHN compared: endpoints, credit pricing, plan tiers, concurrency limits. Sourced from each company's own pricing page on 2026-04-19. No invented numbers.
See the endpointCompare
Photta vs Fitroom — pick the right fit for fashion APIs
Photta and Fitroom compared on endpoints, credit cost per call, pricing model and integration surface. Pulled from each site on 2026-04-19. No made-up numbers.
See the endpointQuickstart
First Photta image in under five minutes.
Sign up, generate an API key, run your first cURL call, poll until it completes, persist the result. Five steps, documented end-to-end.
See the endpointReference
Photta API errors
The full list of Photta API error types with their status codes, the shape of an error body, and which failures are worth retrying.
See the endpointReference
Photta API rate limits
The Photta API rate limit, its window, the Retry-After header, the polling interval and the per-plan concurrency caps, all read from the API documentation.
See the endpoint
Every figure on this page comes from the Photta API docs · checked
Try the API in five minutes
Generate a Photta API key, paste the cURL snippet above, and you'll have your first on-model image before the coffee finishes brewing.
- 1.5–4 min
- 5 credits at 2K · 6 credits at 4K
- async, polling
- 600 requests/min
- Bearer key