VTO API Reference
This page covers all steps to integrate virtual try-on API into your system.
Get your API keys
Your API requests are authenticated using API keys. Any request that doesn't include an API key will return an error.
You can generate an API key from your user dashboard in Miragic website anytime.

Authentication
All requests must include the X-API-Key header containing your assigned API key.
curl -X POST "https://backend.miragic.ai/api/v1/virtual-try-on" \
-H "X-API-Key: YOUR_API_KEY" \
-F "garmentType=full_body" \
-F "humanImage=@path/to/human_image.jpg;type=image/jpeg" \
-F "clothImage=@path/to/cloth_image.jpg;type=image/jpeg"import axios from "axios";
import FormData from "form-data";
import fs from "fs";
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://backend.miragic.ai";
async function virtualTryOn() {
const url = `${BASE_URL}/api/v1/virtual-try-on`;
// Prepare form data
const formData = new FormData();
formData.append("garmentType", "full_body");
formData.append("humanImage", fs.createReadStream("path/to/human_image.jpg"));
formData.append("clothImage", fs.createReadStream("path/to/cloth_image.jpg"));
try {
const response = await axios.post(url, formData, {
headers: {
...formData.getHeaders(),
"X-API-Key": API_KEY,
},
maxBodyLength: Infinity, // useful for large files
});
console.log("✅ Success!");
console.log(response.data);
} catch (error) {
if (error.response) {
console.error("❌ API Error:", error.response.status, error.response.data);
} else {
console.error("❌ Request Error:", error.message);
}
}
}
virtualTryOn();import requests
import time
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
base_url = 'https://backend.miragic.ai'
def virtualtryon():
url = f'{base_url}/api/v1/virtual-try-on'
data = {'garmentType': 'full_body'}
files=[
('humanImage',('human_image.jpg',open('path/to/human_image.jpg','rb'),'image/jpeg')),
('clothImage',('cloth_image.jpg',open('path/to/cloth_image.jpg','rb'),'image/jpeg'))
]
headers = {'X-API-Key': api_key}
response = requests.request("POST", url, headers=headers, data=data, files=files)
print(response.text)
if __name__ == '__main__':
virtualtryon()
How To Create VTO Process
POST /api/v1/virtual-try-on
This API starts the virtualtry-on process by creating a task that generates an image of the model wearing the specified clothing. It supports both single-item try-ons and combo try-ons (upper and lower body clothing combined).
Try-on Options
Single Item Try-on:
Upper Body: Try on shirts, t-shirts, jackets, etc.Lower Body: Try on pants, shorts, skirts, etc.Full Body: Try on dresses, jumpsuits, etc.
Combo Try-on:
Try on upper and lower body clothing simultaneously.
Particularly useful for coordinating complete outfits.
Requires a compatible model pose for both items.
Request
Form Data (Case 1: Single Clothing Try-on)
humanImage
File
Yes
Human image (recommended size: 2048px)
clothImage
File
Yes
Garment image to try on (recommended size: 1024px)
garmentType
String
Yes
Type of garment: upper_body, lower_body, or full_body
Form Data (Case 2: Combo Try-on)
garmentType
String
Yes
Can be any text for this case
clothImage
File
Yes
Upper garment image (recommended size: 1024px)
bottomClothImage
File
Yes
Lower garment image (recommended size: 1024px)
humanImage
File
Yes
Human image (recommended size: 2048px)
The best way to interact with our API is to use one of our official libraries:
Request Example (Case 1: Single Clothing Try-on)
curl -X POST "https://backend.miragic.ai/api/v1/virtual-try-on" \
-H "X-API-Key: YOUR_API_KEY" \
-F "garmentType=full_body" \
-F "humanImage=@path/to/human_image.jpg;type=image/jpeg" \
-F "clothImage=@path/to/cloth_image.jpg;type=image/jpeg"import axios from "axios";
import FormData from "form-data";
import fs from "fs";
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://backend.miragic.ai";
async function virtualTryOn() {
const url = `${BASE_URL}/api/v1/virtual-try-on`;
// Prepare form data
const formData = new FormData();
formData.append("garmentType", "full_body");
formData.append("humanImage", fs.createReadStream("path/to/human_image.jpg"));
formData.append("clothImage", fs.createReadStream("path/to/cloth_image.jpg"));
try {
const response = await axios.post(url, formData, {
headers: {
...formData.getHeaders(),
"X-API-Key": API_KEY,
},
maxBodyLength: Infinity, // useful for large files
});
console.log("✅ Success!");
console.log(response.data);
} catch (error) {
if (error.response) {
console.error("❌ API Error:", error.response.status, error.response.data);
} else {
console.error("❌ Request Error:", error.message);
}
}
}
virtualTryOn();import requests
import time
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
base_url = 'https://backend.miragic.ai'
def virtualtryon():
url = f'{base_url}/api/v1/virtual-try-on'
data = {'garmentType': 'full_body'}
files=[
('humanImage',('human_image.jpg',open('path/to/human_image.jpg','rb'),'image/jpeg')),
('clothImage',('cloth_image.jpg',open('path/to/cloth_image.jpg','rb'),'image/jpeg'))
]
headers = {'X-API-Key': api_key}
response = requests.request("POST", url, headers=headers, data=data, files=files)
print(response.text)
if __name__ == '__main__':
virtualtryon()
Request Example (Case 2: Combo Try-on)
curl -X POST "https://backend.miragic.ai/api/v1/virtual-try-on" \
-H "X-API-Key: YOUR_API_KEY" \
-F "garmentType=comb" \
-F "humanImage=@path/to/human_image.jpg;type=image/jpeg" \
-F "clothImage=@path/to/cloth_image.jpg;type=image/jpeg" \
-F "bottomClothImage=@path/to/bottom_cloth_image.jpg;type=image/jpeg"import axios from "axios";
import FormData from "form-data";
import fs from "fs";
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://backend.miragic.ai";
async function virtualTryOn() {
const url = `${BASE_URL}/api/v1/virtual-try-on`;
// Prepare form data
const formData = new FormData();
formData.append("garmentType", "comb");
formData.append("humanImage", fs.createReadStream("path/to/human_image.jpg"));
formData.append("clothImage", fs.createReadStream("path/to/cloth_image.jpg"));
formData.append("bottomClothImage", fs.createReadStream("path/to/bottom_cloth_image.jpg"));
try {
const response = await axios.post(url, formData, {
headers: {
...formData.getHeaders(),
"X-API-Key": API_KEY,
},
maxBodyLength: Infinity, // useful for large files
});
console.log("✅ Success!");
console.log(response.data);
} catch (error) {
if (error.response) {
console.error("❌ API Error:", error.response.status, error.response.data);
} else {
console.error("❌ Request Error:", error.message);
}
}
}
virtualTryOn();import requests
import time
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
base_url = 'https://backend.miragic.ai'
def virtualtryon():
url = f'{base_url}/api/v1/virtual-try-on'
data = {'garmentType': 'comb'}
files=[
('humanImage',('human_image.jpg',open('path/to/human_image.jpg','rb'),'image/jpeg')),
('clothImage',('cloth_image.jpg',open('path/to/cloth_image.jpg','rb'),'image/jpeg')),
('bottomClothImage',('bottom_cloth_image.jpg',open('path/to/bottom_cloth_image.jpg','rb'),'image/jpeg'))
]
headers = {'X-API-Key': api_key}
response = requests.request("POST", url, headers=headers, data=data, files=files)
print(response.text)
if __name__ == '__main__':
virtualtryon()
Response (Case 1: Single Clothing Try-on)
{"success":true,"message":"Virtual try-on job created and processing started","data":{"jobId":"25331fb2-d0b0-44bd-b932-44f6fcc85e3e","status":"PENDING","mode":"SINGLE","createdAt":"2025-10-08T13:46:57.867Z"}}Response (Case 2: Combo Try-on)
{"success":true,"message":"Virtual try-on job created and processing started","data":{"jobId":"89011007-ea00-4160-9f3d-b15e77b719bc","status":"PENDING","mode":"TOP_BOTTOM","createdAt":"2025-10-08T14:25:18.213Z"}}Response Field
jobId
String
A unique identifier used to track task status and retrieve results.
status
String
The initial status will be PENDING. Use the Get Task Status API to track progress.
mode
String
String to indicate single clothing try-on(SINGLE) or combo try-on(TOP_BOTTOM).
createdAt
String
Date
success
Logic
true or false to indicate whether task is successful or not.
How To Get Process Status
GET /api/v1/virtual-try-on/:jobId
This API lets you check the status of a try-on task and retrieve the final result. Because the try-on process runs asynchronously, you’ll need to poll this endpoint until the task is finished.
Task Status:
PENDING
Task is currently being processed.
0~99%
Continue polling
COMPLETED
Task has finished successfully.
100%
Download result using download_signed_url
FAILED
Task processing failed.
N/A
Check error details and retry if needed
Request:
URL Parameters
JobId
String
Yes
This value indicates task ID assigned by requesting VTO process API
Request Example
curl -X GET https://backend.miragic.ai/api/v1/virtual-try-on/25331fb2-d0b0-44f6fcc85e3e \
-H "X-API-Key: YOUR_API_KEY"const fetch = require("node-fetch"); // for Node.js
const apiKey = "YOUR_API_KEY";
const jobId = "25331fb2-d0b0-44f6fcc85e3e";
const url = `https://backend.miragic.ai/api/v1/virtual-try-on/${jobId}`;
const options = {
method: "GET",
headers: {
"X-API-Key": apiKey
}
};
fetch(url, options)
.then(response => response.json())
.then(data => {
console.log("Response:", data);
})
.catch(error => {
console.error("Error:", error);
});import requests
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
job_id = "25331fb2-d0b0-44f6fcc85e3e"
url = f"https://backend.miragic.ai/api/v1/virtual-try-on/{job_id}"
headers = {
"X-API-Key": api_key
}
response = requests.get(url, headers=headers)
# Print status code and response JSON
print("Status Code:", response.status_code)
print("Response:", response.json())Response Example
Completed Status (200):
{
'success': True,
'data': {
'id': '25331fb2-d0b0-44f6fcc85e3e',
'status': 'COMPLETED',
'mode': 'SINGLE',
'humanImagePath': 'https://backend.miragic.ai/uploads/temp/1759935012047-9783377-1.jpg',
'clothImagePath': 'https://backend.miragic.ai/uploads/virtualtryon/original/clothes/single/0f01f45d-37e5-4796-ae1d-aca695a0d792/3baecbdb-d7fe-4599-b542-b86f4d28fa90.jpg',
'bottomClothImagePath': None,
'resultImagePath': 'https://backend.miragic.ai/uploads/virtualtryon/processed/single/0f01f45d-37e5-ae1d-aca695a0d792/b86386c0-7626-4d3b-9572-5dae9c59fccd.jpg',
'processedUrl': 'https://backend.miragic.ai/uploads/virtualtryon/processed/single/0f01f45d-4796-ae1d-aca695a0d792/b86386c0-7626-4d3b-9572-5dae9c59fccd.jpg',
'createdAt': '2025-10-08T14:50:12.191Z',
'processingStartedAt': '2025-10-08T14:50:12.194Z',
'processingCompletedAt': '2025-10-08T14:50:32.211Z',
'errorMessage': None
}
}Response Fields
id
String
Unique identifier of the task
status
String
Current status of the task (PENDING/COMPLETED/FAILED)
mode
String
String to indicate single clothing try-on(SINGLE) or combo try-on(TOP_BOTTOM).
humanImagePath
String
URL to human image
bottomClothImagePath
String
URL to lower garment image
clothImagePath
String
URL to uppper garment image
resultImagePath
String
URL to result image
createdAt
Number
Unix timestamp when processing is created
processingStartedAt
Number
Unix timestamp when processing is started
processingCompletedAt
Number
Unix timestamp when processing is completed
errorMessage
String
Error message
Rate Limits
To maintain service stability and fair usage, the API enforces the following rate limit:
60requests per minute perAPIkey
If this limit is exceeded, an error (Too Many Requests) will be returned. Please ensure your application includes proper retry logic with exponential backoff.
Full Code Example
The following code lines are quick example to use our API in multiple languages.
Case 1: Single Clothing Try-on
curl -X POST "https://backend.miragic.ai/api/v1/virtual-try-on" \
-H "X-API-Key: YOUR_API_KEY" \
-F "garmentType=full_body" \
-F "humanImage=@path/to/human_image.jpg;type=image/jpeg" \
-F "clothImage=@path/to/cloth_image.jpg;type=image/jpeg"import axios from "axios";
import fs from "fs";
import FormData from "form-data";
const apiKey = "YOUR_API_KEY";
const baseUrl = "https://backend.miragic.ai";
async function virtualTryOn() {
const url = `${baseUrl}/api/v1/virtual-try-on`;
const formData = new FormData();
formData.append("garmentType", "full_body");
formData.append("humanImage", fs.createReadStream("path/to/human_image.jpg"));
formData.append("clothImage", fs.createReadStream("path/to/cloth_image.jpg"));
try {
// Step 1: Create virtual try-on job
const response = await axios.post(url, formData, {
headers: {
"X-API-Key": apiKey,
...formData.getHeaders(),
},
});
console.log("Response:", response.data);
if (response.data.success) {
const jobId = response.data.data.jobId;
console.log(`Job ID: ${jobId}`);
// Step 2: Poll for result
while (true) {
const result = await axios.get(`${baseUrl}/api/v1/virtual-try-on/${jobId}`, {
headers: {
"X-API-Key": apiKey,
},
});
const status = result.data.data.status;
console.log("Status:", status);
if (status === "COMPLETED") {
console.log("Result:", result.data);
break;
} else if (status === "FAILED") {
console.error("Job failed:", result.data);
break;
}
// Wait 2 seconds before next poll
await new Promise((resolve) => setTimeout(resolve, 2000));
}
} else {
console.error("Error:", response.data);
}
} catch (error) {
console.error("Error occurred:", error.response?.data || error.message);
}
}
virtualTryOn();
import requests
import time
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
base_url = 'https://backend.miragic.ai'
def virtualtryon():
url = f'{base_url}/api/v1/virtual-try-on'
data = {'garmentType': 'full_body'}
files=[
('humanImage',('human_image.jpg',open('path/to/human_image.jpg','rb'),'image/jpeg')),
('clothImage',('cloth_image.jpg',open('path/to/cloth_image.jpg','rb'),'image/jpeg'))
]
headers = {'X-API-Key': api_key}
response = requests.request("POST", url, headers=headers, data=data, files=files)
print(response.text)
if response.json()['success']:
job_id = response.json()['data']['jobId']
print(f'Job ID: {job_id}')
# Poll for results
while True:
result = requests.get(
f'{base_url}/api/v1/virtual-try-on/{job_id}',
headers=headers
)
if result.json()['data']['status'] == 'COMPLETED':
print('Result:', result.json())
break
elif result.json()['data']['status'] == 'FAILED':
print('Job failed:', result.json())
break
time.sleep(2)
else:
print('Error:', response.json())
if __name__ == '__main__':
virtualtryon()
Case 2: Combo Try-on
curl -X POST "https://backend.miragic.ai/api/v1/virtual-try-on" \
-H "X-API-Key: YOUR_API_KEY" \
-F "garmentType=comb" \
-F "humanImage=@path/to/human_image.jpg;type=image/jpeg" \
-F "clothImage=@path/to/cloth_image.jpg;type=image/jpeg" \
-F "bottomClothImage=@path/to/bottom_cloth_image.jpg;type=image/jpeg"import axios from "axios";
import FormData from "form-data";
import fs from "fs";
const apiKey = "YOUR_API_KEY";
const baseUrl = "https://backend.miragic.ai";
async function virtualTryOn() {
const url = `${baseUrl}/api/v1/virtual-try-on`;
// Prepare form data
const formData = new FormData();
formData.append("garmentType", "comb");
formData.append("humanImage", fs.createReadStream("path/to/human_image.jpg"));
formData.append("clothImage", fs.createReadStream("path/to/cloth_image.jpg"));
formData.append(
"bottomClothImage",
fs.createReadStream("path/to/bottom_cloth_image.jpg")
);
const headers = {
"X-API-Key": apiKey,
...formData.getHeaders(),
};
try {
// Step 1: Submit try-on request
const response = await axios.post(url, formData, { headers });
console.log(response.data);
if (response.data.success) {
const jobId = response.data.data.jobId;
console.log(`Job ID: ${jobId}`);
// Step 2: Poll for results
while (true) {
const result = await axios.get(`${baseUrl}/api/v1/virtual-try-on/${jobId}`, {
headers: { "X-API-Key": apiKey },
});
const status = result.data.data.status;
if (status === "COMPLETED") {
console.log("Result:", result.data);
break;
} else if (status === "FAILED") {
console.log("Job failed:", result.data);
break;
}
// Wait before next check
await new Promise((resolve) => setTimeout(resolve, 2000));
}
} else {
console.log("Error:", response.data);
}
} catch (error) {
console.error("Request failed:", error.response?.data || error.message);
}
}
virtualTryOn();
import requests
import time
api_key = 'YOUR_API_KEY' # ← Replace with your actual API key
base_url = 'https://backend.miragic.ai'
def virtualtryon():
url = f'{base_url}/api/v1/virtual-try-on'
data = {'garmentType': 'comb'}
files=[
('humanImage',('human_image.jpg',open('path/to/human_image.jpg','rb'),'image/jpeg')),
('clothImage',('cloth_image.jpg',open('path/to/cloth_image.jpg','rb'),'image/jpeg')),
('bottomClothImage',('bottom_cloth_image.jpg',open('path/to/bottom_cloth_image.jpg','rb'),'image/jpeg'))
]
headers = {'X-API-Key': api_key}
response = requests.request("POST", url, headers=headers, data=data, files=files)
print(response.text)
if response.json()['success']:
job_id = response.json()['data']['jobId']
print(f'Job ID: {job_id}')
# Poll for results
while True:
result = requests.get(
f'{base_url}/api/v1/virtual-try-on/{job_id}',
headers=headers
)
if result.json()['data']['status'] == 'COMPLETED':
print('Result:', result.json())
break
elif result.json()['data']['status'] == 'FAILED':
print('Job failed:', result.json())
break
time.sleep(2)
else:
print('Error:', response.json())
if __name__ == '__main__':
virtualtryon()
Last updated