curl -X POST "https://api.genlook.app/tryon/v1/try-on/sync" \
-H "x-api-key: gk_your_api_key" \
-H "Content-Type: application/json" \
--max-time 100 \
-d '{
"products": [{
"externalId": "shirt-42",
"title": "Red cotton t-shirt",
"description": "Regular fit crew neck tee, short sleeves, hip length.",
"images": [{ "source": { "url": "https://cdn.example.com/red-tee.jpg" } }]
}],
"person": { "image": { "source": { "url": "https://cdn.example.com/me.jpg" } } }
}'
import requests
r = requests.post(
"https://api.genlook.app/tryon/v1/try-on/sync",
headers={"x-api-key": "gk_your_api_key"},
json={
"products": [{"externalId": "shirt-42"}],
"person": {"image": {"source": {"url": "https://cdn.example.com/me.jpg"}}},
},
timeout=100,
)
r.raise_for_status()
data = r.json()
if r.status_code == 202:
print("Still running, poll:", data["generationId"])
else:
print(data["resultImageUrl"])
import { Genlook } from "@genlook/api";
const client = new Genlook({ apiKey: process.env.GENLOOK_API_KEY! });
const result = await client.tryOn.createSync({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
});
// Took longer than 90 s? Wait for it.
const done =
result.status === "COMPLETED" ? result : await client.generations.waitFor(result.generationId);
console.log(done.resultImageUrl);
const res = await fetch("https://api.genlook.app/tryon/v1/try-on/sync", {
method: "POST",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
}),
signal: AbortSignal.timeout(100_000),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.message}`);
// 202: still running, poll /generations/:id with data.generationId
console.log(data.resultImageUrl);
{
"generationId": "cm8gen456xyz",
"status": "COMPLETED",
"resultImageUrl": "https://storage.googleapis.com/...",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:00:09.800Z"
}
{
"generationId": "cm8gen456xyz",
"status": "PROCESSING",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:01:30.000Z"
}
{
"code": "GENERATION_TIMEOUT",
"message": "The try-on generation did not finish within 60 seconds and was cancelled. The credit has been refunded; please retry.",
"status": 504
}
Try-On
Create Try-On (sync)
Create a try-on and get the result in the same request. Costs 1 credit.
POST
/
tryon
/
v1
/
try-on
/
sync
curl -X POST "https://api.genlook.app/tryon/v1/try-on/sync" \
-H "x-api-key: gk_your_api_key" \
-H "Content-Type: application/json" \
--max-time 100 \
-d '{
"products": [{
"externalId": "shirt-42",
"title": "Red cotton t-shirt",
"description": "Regular fit crew neck tee, short sleeves, hip length.",
"images": [{ "source": { "url": "https://cdn.example.com/red-tee.jpg" } }]
}],
"person": { "image": { "source": { "url": "https://cdn.example.com/me.jpg" } } }
}'
import requests
r = requests.post(
"https://api.genlook.app/tryon/v1/try-on/sync",
headers={"x-api-key": "gk_your_api_key"},
json={
"products": [{"externalId": "shirt-42"}],
"person": {"image": {"source": {"url": "https://cdn.example.com/me.jpg"}}},
},
timeout=100,
)
r.raise_for_status()
data = r.json()
if r.status_code == 202:
print("Still running, poll:", data["generationId"])
else:
print(data["resultImageUrl"])
import { Genlook } from "@genlook/api";
const client = new Genlook({ apiKey: process.env.GENLOOK_API_KEY! });
const result = await client.tryOn.createSync({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
});
// Took longer than 90 s? Wait for it.
const done =
result.status === "COMPLETED" ? result : await client.generations.waitFor(result.generationId);
console.log(done.resultImageUrl);
const res = await fetch("https://api.genlook.app/tryon/v1/try-on/sync", {
method: "POST",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
}),
signal: AbortSignal.timeout(100_000),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.message}`);
// 202: still running, poll /generations/:id with data.generationId
console.log(data.resultImageUrl);
{
"generationId": "cm8gen456xyz",
"status": "COMPLETED",
"resultImageUrl": "https://storage.googleapis.com/...",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:00:09.800Z"
}
{
"generationId": "cm8gen456xyz",
"status": "PROCESSING",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:01:30.000Z"
}
{
"code": "GENERATION_TIMEOUT",
"message": "The try-on generation did not finish within 60 seconds and was cancelled. The credit has been refunded; please retry.",
"status": 504
}
Same body as Create Try-On, but the request stays open until the result is ready, usually about 10 seconds. No polling. Use it for scripts, serverless functions and any client that prefers one call. Costs 1 credit, refunded if the generation fails.
The request waits up to 90 seconds. Set your HTTP client timeout above that (100 seconds works).
| Outcome | Response |
|---|---|
| Result ready | 200 with the generation, including resultImageUrl. |
| Generation failed | The error, same codes as Generation Status (e.g. GENERATION_FAILED, GENERATION_TIMEOUT), with the generation in details.generationId. The credit is refunded. |
| Still running after 90 s | 202 with the generationId. Poll Generation Status for the result. |
First try-on of a product is a few seconds slower: the product gets analyzed. Register products ahead of time with
Upsert Product and the analysis runs right away, before the first try-on.
Body
Identical to Create Try-On:products, person, externalUserId, output.
curl -X POST "https://api.genlook.app/tryon/v1/try-on/sync" \
-H "x-api-key: gk_your_api_key" \
-H "Content-Type: application/json" \
--max-time 100 \
-d '{
"products": [{
"externalId": "shirt-42",
"title": "Red cotton t-shirt",
"description": "Regular fit crew neck tee, short sleeves, hip length.",
"images": [{ "source": { "url": "https://cdn.example.com/red-tee.jpg" } }]
}],
"person": { "image": { "source": { "url": "https://cdn.example.com/me.jpg" } } }
}'
import requests
r = requests.post(
"https://api.genlook.app/tryon/v1/try-on/sync",
headers={"x-api-key": "gk_your_api_key"},
json={
"products": [{"externalId": "shirt-42"}],
"person": {"image": {"source": {"url": "https://cdn.example.com/me.jpg"}}},
},
timeout=100,
)
r.raise_for_status()
data = r.json()
if r.status_code == 202:
print("Still running, poll:", data["generationId"])
else:
print(data["resultImageUrl"])
import { Genlook } from "@genlook/api";
const client = new Genlook({ apiKey: process.env.GENLOOK_API_KEY! });
const result = await client.tryOn.createSync({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
});
// Took longer than 90 s? Wait for it.
const done =
result.status === "COMPLETED" ? result : await client.generations.waitFor(result.generationId);
console.log(done.resultImageUrl);
const res = await fetch("https://api.genlook.app/tryon/v1/try-on/sync", {
method: "POST",
headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
products: [{ externalId: "shirt-42" }],
person: { image: { source: { url: "https://cdn.example.com/me.jpg" } } },
}),
signal: AbortSignal.timeout(100_000),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.code}: ${data.message}`);
// 202: still running, poll /generations/:id with data.generationId
console.log(data.resultImageUrl);
Response
string
required
The generation ID.
string
required
COMPLETED on 200. PENDING or PROCESSING on 202.string
Temporary signed URL of the result. Present on
200. Display or download it right away, or fetch the generation
again for a fresh URL.string
Your
externalId, or the generated ID of a one-shot product.string
required
ISO timestamp.
string
required
ISO timestamp.
{
"generationId": "cm8gen456xyz",
"status": "COMPLETED",
"resultImageUrl": "https://storage.googleapis.com/...",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:00:09.800Z"
}
{
"generationId": "cm8gen456xyz",
"status": "PROCESSING",
"productExternalId": "shirt-42",
"createdAt": "2026-09-30T10:00:00.000Z",
"updatedAt": "2026-09-30T10:01:30.000Z"
}
{
"code": "GENERATION_TIMEOUT",
"message": "The try-on generation did not finish within 60 seconds and was cancelled. The credit has been refunded; please retry.",
"status": 504
}
Errors
Everything from Create Try-On, plus the generation errors from Generation Status. See Errors for the full list.Was this page helpful?

