Clothing AI Try-On — API Reference
This document covers the digital-twin and virtual-fitting endpoints of the WEARFITS GenAI API. For 3D shoe generation (/api/v1/shoe-3d) refer to the separate Shoe-3D API Reference.
Base Information
| Property | Value |
|---|---|
| Production base URL | https://api.wearfits.com |
| OpenAPI spec | api.wearfits.com/doc |
| Interactive docs (Swagger UI) | api.wearfits.com/reference |
| Authentication header | X-API-Key |
All /api/* routes require the X-API-Key header on every request.
Image Input Formats
Every image field in the API accepts one of two formats:
HTTP/HTTPS URL — a publicly accessible URL pointing to a hosted image.
Base64 Data URL — an inline base64-encoded image embedded directly in the JSON body.
Supported MIME types: image/png, image/jpeg, image/jpg, image/gif, image/webp, image/svg+xml.
Available Poses
The poseId field accepts the following values across all endpoints that support posing:
| poseId | Description |
|---|---|
standing_arms_down |
Neutral standing, arms at sides |
man_pose |
Male standing pose |
girl_pose |
Female standing pose (default) |
shoe_girl_pose |
Female pose optimized for footwear display |
Body Measurement Ranges
When supplying bodyMeasurements, values must fall within the following ranges. At least two measurements are required.
| Field | Unit | Min | Max |
|---|---|---|---|
height |
cm | 140 | 210 |
chest |
cm | 70 | 150 |
waist |
cm | 55 | 140 |
hip |
cm | 70 | 150 |
inseam |
cm | 60 | 95 |
Core Endpoints
POST /api/v1/digital-twin
Generate a photorealistic digital twin (avatar) for use in virtual try-on sessions. This is an asynchronous operation — the endpoint returns a jobId which you poll via GET /api/v1/jobs/{jobId} to retrieve the digitalTwinId on completion.
Input Modes
| Mode | Required fields | How it works |
|---|---|---|
| Photo Mode | faceImage + bodyPhotoUrl |
SAM-3D extracts the body mesh automatically from the full-body photo |
| Size Mode (measurements) | faceImage + bodyMeasurements |
Nearest-neighbour body mask lookup from the BodyM dataset |
| Size Mode (clothing size) | faceImage + clothingSize |
Simplified size input; converted internally to measurements |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
faceImage |
string | Yes | URL or Base64 Data URL of the user's face |
bodyPhotoUrl |
string | Photo Mode | URL or Base64 Data URL of full-body photo |
bodyMeasurements |
object | Size Mode | Body dimensions object — see ranges above |
bodyMeasurements.height |
number | — | Height in cm |
bodyMeasurements.chest |
number | — | Chest circumference in cm |
bodyMeasurements.waist |
number | — | Waist circumference in cm |
bodyMeasurements.hip |
number | — | Hip circumference in cm |
bodyMeasurements.inseam |
number | — | Inseam length in cm |
clothingSize |
object | Size Mode | Simplified size input |
clothingSize.height |
number | — | Height in cm |
clothingSize.size |
string | — | Standard clothing size (e.g. "M", "L", "XL") |
gender |
string | Recommended | "male" or "female" |
poseId |
string | No | Target pose — see Available Poses above |
Response
Once the job reaches completed status, GET /api/v1/jobs/{jobId} returns:
Example — Photo Mode
curl -X POST https://api.wearfits.com/api/v1/digital-twin \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"faceImage": "https://example.com/user-face.jpg",
"bodyPhotoUrl": "https://example.com/user-body.jpg",
"gender": "female",
"poseId": "girl_pose"
}'
Example — Size Mode (measurements)
curl -X POST https://api.wearfits.com/api/v1/digital-twin \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"faceImage": "https://example.com/user-face.jpg",
"bodyMeasurements": {
"height": 170,
"chest": 88,
"waist": 70,
"hip": 96
},
"gender": "female"
}'
Example — Size Mode (clothing size)
curl -X POST https://api.wearfits.com/api/v1/digital-twin \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"faceImage": "https://example.com/user-face.jpg",
"clothingSize": {
"height": 175,
"size": "M"
},
"gender": "male"
}'
GET /api/v1/digital-twin/{id}
Verify that a digitalTwinId still exists in cache. Useful when persisting a twin ID in client storage (cookies, localStorage) to confirm it is still available before initiating a try-on session without regenerating the avatar.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id |
string | The digitalTwinId to validate |
Response — valid twin
Response — expired or unknown twin
HTTP 404 or { "valid": false }.
Caching policy: Digital twins are cached for 30 days from generation. After expiry, a new twin must be generated via POST /api/v1/digital-twin.
Example
POST /api/v1/virtual-fitting
The primary virtual try-on pipeline. Applies one or more garments onto a digital twin and returns a photorealistic composite image. This is an asynchronous operation — the response contains a jobId that you poll to retrieve the final result.
You can either supply a pre-generated digitalTwinId (recommended for returning users) or pass inline body/face data to generate a twin on-the-fly within the same request.
Request Body
Identity — choose one approach:
| Field | Type | Description |
|---|---|---|
digitalTwinId |
string | ID of a previously generated digital twin (preferred) |
faceImage |
string | URL or Base64; used with inline body data |
photoUrl |
string | Full-body photo URL or Base64 (Photo Mode inline) |
bodyMeasurements |
object | Body dimensions (Size Mode inline) |
clothingSize |
object | Simplified size (Size Mode inline) |
Garments — at least one garment field is required:
| Field | Type | Description |
|---|---|---|
topGarment |
string | [string, string] | Single image URL/Base64, or a pair [front, back] |
bottomGarment |
string | [string, string] | Bottom garment image(s) |
fullBodyGarment |
string | [string, string] | Full-body garment (e.g. dress, jumpsuit) |
shoes |
string | [string, string] | Shoe image(s) |
Presentation options:
| Field | Type | Description |
|---|---|---|
gender |
string | "male" or "female" |
poseId |
string | Target pose — see Available Poses above |
Response
Poll GET /api/v1/jobs/{jobId} until status is completed. The result contains a URL to the generated try-on image.
Example — fitting with pre-generated twin
curl -X POST https://api.wearfits.com/api/v1/virtual-fitting \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"digitalTwinId": "twin_xyz789",
"topGarment": "https://example.com/shirt-front.jpg",
"bottomGarment": "https://example.com/trousers.jpg",
"gender": "male",
"poseId": "man_pose"
}'
Example — fitting with front and back garment images
curl -X POST https://api.wearfits.com/api/v1/virtual-fitting \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"digitalTwinId": "twin_xyz789",
"topGarment": [
"https://example.com/jacket-front.jpg",
"https://example.com/jacket-back.jpg"
],
"gender": "female",
"poseId": "girl_pose"
}'
Example — inline body data (no pre-generated twin)
curl -X POST https://api.wearfits.com/api/v1/virtual-fitting \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key_here" \
-d '{
"faceImage": "https://example.com/user-face.jpg",
"bodyMeasurements": {
"height": 168,
"waist": 68,
"hip": 94
},
"fullBodyGarment": "https://example.com/dress.jpg",
"gender": "female"
}'
Job Management Endpoints
GET /api/v1/jobs/{jobId}
Poll the status and retrieve results of any asynchronous job (digital twin generation, virtual fitting, etc.).
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId |
string | Job ID returned by a submission endpoint |
Job Status Values
| Status | Meaning |
|---|---|
queued |
Job is waiting in the processing queue |
validating |
Input data is being validated |
processing |
AI models are generating the result |
uploading |
Output is being uploaded to storage |
completed |
Job finished successfully; result is populated |
failed |
Job failed; error field describes the cause |
Response — in-progress
Response — completed virtual fitting
{
"jobId": "job_def456",
"status": "completed",
"progress": 100,
"result": {
"imageUrl": "https://cdn.wearfits.com/results/job_def456/output.jpg"
}
}
Response — completed digital twin
{
"jobId": "job_abc123",
"status": "completed",
"progress": 100,
"result": {
"digitalTwinId": "twin_xyz789"
}
}
Example — polling loop (bash)
JOB_ID="job_def456"
while true; do
RESPONSE=$(curl -s "https://api.wearfits.com/api/v1/jobs/$JOB_ID" \
-H "X-API-Key: your_api_key_here")
STATUS=$(echo "$RESPONSE" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
echo "$RESPONSE" | jq .
break
fi
sleep 3
done
Example — polling loop (JavaScript)
async function pollJob(jobId, apiKey, intervalMs = 3000) {
const url = `https://api.wearfits.com/api/v1/jobs/${jobId}`;
while (true) {
const res = await fetch(url, {
headers: { 'X-API-Key': apiKey },
});
const job = await res.json();
if (job.status === 'completed') {
return job.result;
}
if (job.status === 'failed') {
throw new Error(`Job failed: ${job.error}`);
}
await new Promise((resolve) => setTimeout(resolve, intervalMs));
}
}
DELETE /api/v1/jobs/{jobId}
Cancel a running or queued job immediately.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
jobId |
string | ID of the job to cancel |
Response
HTTP 200 on successful cancellation.
Example
Secondary Endpoints
The following endpoints provide standalone or utility functionality. They follow the same authentication and job-polling patterns as the core endpoints.
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/tryon/clothing |
Standalone clothing try-on (without a full digital twin pipeline) |
| POST | /api/v1/tryon/shoes |
Standalone shoe try-on |
| POST | /api/v1/generate |
Generate images from a text prompt |
| POST | /api/v1/pose-transfer |
Transfer the pose of one person onto another |
Recommended Integration Flow
The following pattern covers the typical e-commerce use case: a user visits a product page, generates a personal avatar once, then tries on multiple garments using that avatar.
1. User uploads face photo (+ body photo OR measurements OR clothing size)
│
▼
2. POST /api/v1/digital-twin
│
▼
3. Poll GET /api/v1/jobs/{jobId} ──► status: completed
│
▼ result.digitalTwinId
4. Store digitalTwinId client-side (cookie / localStorage)
│
On subsequent visits:
5. GET /api/v1/digital-twin/{id} ──► valid: true (skip step 1–4)
│
▼
6. POST /api/v1/virtual-fitting { digitalTwinId, topGarment, … }
│
▼
7. Poll GET /api/v1/jobs/{jobId} ──► status: completed
│
▼ result.imageUrl
8. Display try-on image
Webhook Signatures
If you configure a webhook URL to receive job completion notifications, each request is signed so you can verify its authenticity.
Signing algorithm: HMAC-SHA256
Secret derivation: hex( SHA-256( your_api_key ) )
Verification steps:
-
Derive the signing secret:
-
Sort the JSON body keys alphabetically and serialize to a canonical JSON string.
-
Compute the HMAC-SHA256 of the canonical JSON string using the signing secret.
-
Compare your computed signature against the value in the
X-Webhook-Signaturerequest header.
Python verification example:
import hashlib
import hmac
import json
def verify_webhook(payload: bytes, received_signature: str, api_key: str) -> bool:
# Derive signing secret from API key
signing_secret = hashlib.sha256(api_key.encode()).hexdigest()
# Canonical form: parse and re-serialize with sorted keys
body = json.loads(payload)
canonical = json.dumps(body, sort_keys=True, separators=(',', ':'))
# Compute expected signature
expected = hmac.new(
signing_secret.encode(),
canonical.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, received_signature)
Node.js verification example:
const crypto = require('crypto');
function verifyWebhook(rawBody, receivedSignature, apiKey) {
// Derive signing secret from API key
const signingSecret = crypto
.createHash('sha256')
.update(apiKey)
.digest('hex');
// Canonical form: parse and re-serialize with sorted keys
const body = JSON.parse(rawBody);
const sorted = JSON.stringify(body, Object.keys(body).sort());
// Compute expected signature
const expected = crypto
.createHmac('sha256', signingSecret)
.update(sorted)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected, 'hex'),
Buffer.from(receivedSignature, 'hex')
);
}
Rate Limits
Rate limits are enforced per API key.
| Endpoint category | Limit |
|---|---|
| Job submission | 50 requests / minute |
| Job status polling | 500 requests / minute |
| File downloads | 300 requests / minute |
| Health check | 5 000 requests / minute |
Limits are 10× higher when using localhost or the DEV_API_KEY (development environment only).
If you exceed a limit, the API returns HTTP 429 Too Many Requests. Implement exponential back-off in your polling loop to stay within the job-status limit during high-concurrency scenarios.