Skip to content

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.

X-API-Key: your_api_key_here

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.

data:image/<format>;base64,<base64-encoded-data>

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

{
  "jobId": "job_abc123",
  "estimatedTime": 30
}

Once the job reaches completed status, GET /api/v1/jobs/{jobId} returns:

{
  "status": "completed",
  "result": {
    "digitalTwinId": "twin_xyz789"
  }
}

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

{
  "valid": true
}

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

curl https://api.wearfits.com/api/v1/digital-twin/twin_xyz789 \
  -H "X-API-Key: your_api_key_here"

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

{
  "jobId": "job_def456",
  "estimatedTime": 20
}

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

{
  "jobId": "job_abc123",
  "status": "processing",
  "progress": 45
}

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

curl -X DELETE https://api.wearfits.com/api/v1/jobs/job_def456 \
  -H "X-API-Key: your_api_key_here"

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

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:

  1. Derive the signing secret:

    import hashlib
    signing_secret = hashlib.sha256(api_key.encode()).hexdigest()
    

  2. Sort the JSON body keys alphabetically and serialize to a canonical JSON string.

  3. Compute the HMAC-SHA256 of the canonical JSON string using the signing secret.

  4. Compare your computed signature against the value in the X-Webhook-Signature request 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.