Overview
The Corlen API generates AI virtual try-on images: send a customer's photo and a garment image, get back an image of that person wearing the garment. Every generation runs asynchronously: you start it with a POST request, get a jobId back immediately, and poll a GET endpoint until it finishes.
No account yet? Sign up for a free trial (7 days, 10 generations, no credit card needed). Once you have a key, try the Playground to run a real generation from your browser with no code.
Download Postman collectionQuickstart
A full try-on in two calls: start the generation, then poll until it finishes.
# 1. Start the generation
curl -X POST https://corlen.io/api/v1/tryon \
-H "Authorization: Bearer corlen_live_..." \
-H "Content-Type: application/json" \
-d '{
"customerPhotoBase64": "data:image/jpeg;base64,...",
"garmentImageUrl": "https://your-catalog.example.com/garment.jpg",
"category": "upper_body"
}'
# -> { "jobId": "b1e4...", "status": "processing" }
# 2. Poll until it's done (every 2-3 seconds)
curl https://corlen.io/api/v1/tryon/b1e4... \
-H "Authorization: Bearer corlen_live_..."
# -> { "status": "completed", "resultImageBase64": "data:image/jpeg;base64,..." }That's the whole integration. See Recommended workflow for how to poll politely, and Python example for a full working script.
Authentication
Every request needs an API key, created from your dashboard, sent as a bearer token:
Authorization: Bearer corlen_live_...
A missing or invalid key returns 401. Keys are shown once at creation and cannot be retrieved again, only revoked and replaced.
Rate limits and quotas
Requests are limited to 20 per 5 minutes per API key. Exceeding this returns 429 with a Retry-After header.
Your plan also caps how many generations you can run per day and per month; these are shown in your dashboard Overview. Going over your included monthly volume returns a 402 until you buy a top-up pack (see Credits) - a real, one-time payment, never billed after the fact.
Endpoints
/api/v1/tryonGenerates a single garment try-on.
curl -X POST https://corlen.io/api/v1/tryon \
-H "Authorization: Bearer corlen_live_..." \
-H "Content-Type: application/json" \
-d '{
"customerPhotoBase64": "data:image/jpeg;base64,...",
"garmentImageUrl": "https://your-catalog.example.com/garment.jpg",
"category": "upper_body"
}'
# 202 Accepted
{ "jobId": "b1e4...", "status": "processing" }Body fields:
customerPhotoBase64(required): adata:URI. Never a remote URL: the customer's photo is always sent to us directly by your server, never fetched from a link.productId(optional): the id of a garment you registered under Products, instead of passing garmentImageUrl/category/garmentCategory on every call. Any of those fields sent alongside productId override the registered value just for that request.garmentImageUrl(required unless productId is given): anhttps://URL from your own catalog, or adata:URI.garmentBackImageUrl(optional): a back-view reference photo, used whenviewAngleisback.category(required unless productId is given):upper_body,lower_body, orfull_body.garmentCategory,size,customerSize(optional): improve fit rendering when provided.garmentState(optional):openorclosed, for jackets/shirts/waistcoats.tuckState(optional):tuckedoruntucked.viewAngle(optional):front(default),left,right, orback.
/api/v1/tryon/comboGenerates a combined look from 2 to 4 garments (e.g. a top, a jacket, and jeans) in one request.
curl -X POST https://corlen.io/api/v1/tryon/combo \
-H "Authorization: Bearer corlen_live_..." \
-H "Content-Type: application/json" \
-d '{
"customerPhotoBase64": "data:image/jpeg;base64,...",
"garments": [
{ "garmentImageUrl": "https://.../top.jpg", "category": "upper_body", "garmentCategory": "t_shirt" },
{ "garmentImageUrl": "https://.../jeans.jpg", "category": "lower_body", "garmentCategory": "jeans" }
]
}'
# 202 Accepted
{ "jobId": "b1e4...", "status": "processing" }Same fields as above, applied per garment inside the garments array, including productId for any registered garment. Use this endpoint only for 2 or more garments; a single item should use POST /api/v1/tryon instead.
/api/v1/tryon/{jobId}Poll this until the job finishes.
curl https://corlen.io/api/v1/tryon/b1e4... \
-H "Authorization: Bearer corlen_live_..."
# while processing
{ "status": "processing" }
# once complete
{
"status": "completed",
"resultImageBase64": "data:image/jpeg;base64,...",
"generationTimeMs": 24310
}
# if it failed
{ "status": "failed", "error": "..." }While a generation is processing
A generation isn't instant, and the API doesn't return a percentage, only processing. Don't show your customers a countdown or a specific time estimate: it draws attention to the wait instead of the result. Corlen's own kiosk and website use the same pattern below, rotating through a few friendly lines with a simple animation while polling continues in the background.
const stages = [
"Reading your photo...",
"Preparing the garment...",
"Matching your fit...",
"Adding the final touches...",
];
let i = 0;
const interval = setInterval(() => {
i = Math.min(i + 1, stages.length - 1);
showMessage(stages[i]); // pair this with a spinner or a few progress dots
}, 4000);
// stop rotating once your poll to GET /api/v1/tryon/{jobId} comes back
// with status "completed" or "failed"Images
- Accepted formats: JPEG, PNG, WebP.
- Maximum size: 8MB per image.
- Garment images may be a public HTTPS URL or a base64 data URI; customer photos must always be a data URI you send directly.
Watermark
Brand every result with your own logo, placed in the bottom-right corner. This is an account-wide preference, not a per-request field: turn it on and add your logo URL once from Settings, and every generation on both /tryon and /tryon/combo is watermarked automatically from then on.
Errors
| 401 | Missing, invalid, or revoked API key. |
| 403 | Your account has been blocked. Contact support@corlen.io. |
| 400 / 413 / 422 | Malformed request, oversized body, or an image could not be processed. |
| 404 | No product found for the productId you sent. |
| 429 | Rate limit or quota exceeded. Check the Retry-After header. |
| 500 | Something went wrong on our end. Failed generations are never billed. |
Response format
Every endpoint returns one of these three shapes.
Job created (202, from POST /tryon or /tryon/combo):
{
"jobId": "string, uuid",
"status": "processing"
}Job finished (200, from GET /tryon/{jobId}):
{
"status": "completed",
"resultImageBase64": "string, a data:image/jpeg;base64,... URI",
"generationTimeMs": "number, how long generation took"
}Job failed:
{
"status": "failed",
"error": "string, a message safe to show your own users"
}Any error response (4xx/5xx):
{ "error": "string" }Recommended workflow
- Call
POST /api/v1/tryon(or/combo) once per customer action. Store the returnedjobId. - Poll
GET /api/v1/tryon/{jobId}every 2-3 seconds. Don't poll faster than that: it counts against the same rate limit as generation requests. - While it's
processing, show rotating friendly messages, not a countdown (see While a generation is processing). - Stop polling as soon as you see
completedorfailed. A failed generation is never billed, so it's safe to let a customer simply retry. - If you show the same result again later, save
resultImageBase64on your own end. There is no endpoint to re-fetch a past result.
Python example
import base64
import time
import requests
API_KEY = "corlen_live_..."
BASE_URL = "https://corlen.io/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
with open("customer_photo.jpg", "rb") as f:
photo_b64 = base64.b64encode(f.read()).decode()
response = requests.post(
f"{BASE_URL}/tryon",
headers=headers,
json={
"customerPhotoBase64": f"data:image/jpeg;base64,{photo_b64}",
"garmentImageUrl": "https://your-catalog.example.com/garment.jpg",
"category": "upper_body",
},
)
response.raise_for_status()
job_id = response.json()["jobId"]
while True:
time.sleep(2.5)
poll = requests.get(f"{BASE_URL}/tryon/{job_id}", headers=headers).json()
if poll["status"] == "completed":
print("Done:", poll["resultImageBase64"][:40], "...")
break
if poll["status"] == "failed":
print("Failed:", poll["error"])
breakAPI changelog
Version history for the API contract itself. For product-wide updates, see the Corlen changelog.
- August 2026: Added watermarking: brand every result with your own logo, configured once from Settings.
- August 2026: Added
productIdtoPOST /tryonand/combo, backed by the new Products catalog. Added the Playground. - August 2026: Public API launched:
POST /tryon,POST /tryon/combo,GET /tryon/{jobId}.