Skip to main content
POST
/
tryon
/
v1
/
try-on
curl -X POST "https://api.genlook.app/tryon/v1/try-on" \
  -H "x-api-key: gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [{ "externalId": "shirt-42" }],
    "person": { "image": { "source": { "id": "ephemeral/customer/ttl-7d/.../20260512-….jpeg" } } }
  }'
{
  "generationId": "cm8gen456xyz",
  "status": "PENDING",
  "productExternalId": "shirt-42"
}
Creates a virtual try-on generation. Runs asynchronously — poll Generation Status for the result. Each generation consumes 1 credit. The body has three parts: a products array describing what to try on, a person image (the shopper photo, either pre-uploaded or shipped inline), and optional externalUserId / output controls.

Products

products is an array. For now it must hold exactly one item (multi-product try-on is on the roadmap). Each item works three ways:
  • Reference an existing product — pass { "externalId": "..." } only. Cheapest call (~50 bytes on the wire).
  • Describe a product inline — pass { "externalId": "...", "title": ..., "description": ..., "images": [...] }. Creates the product if it’s new; updates it if it’s not. Inline-created products live for 15 days from their last use; the server refreshes the timer on every generation, so an actively-used product never expires.
  • One-shot — omit externalId. The server returns a generated ID in the response under productExternalId that you can pass back if you want to reference the same product later. One-shot products live for 7 days from their last use.
products
array
required
Array of product specs to try on. Exactly one item for now — multi-product try-on is on the roadmap.

Person

The shopper photo. person.image.source holds exactly one of id, url, or fileKey.
person
object
required
externalUserId
string
Optional opaque identifier of your own end user (e.g. your user ID). No PII — it’s used purely as an attribution and GDPR key. When set, the generation — and the person image uploaded as part of this call — can be wiped on demand via DELETE /customers/:customerId (pass the same value as the path segment).
output
object
Optional controls over the generated result.
The previous request shape is still accepted but deprecated (this is not a breaking change). The old form used a top-level singular product object, a customer object (customer: { source: { id | url | fileKey } }), a top-level customerId, and top-level useWatermark / retentionDays. Migrate to products: [...], person.image.source, externalUserId, and output.watermark / output.keepForDays. See the Changelog.
  1. Upload the person image once via POST /images/upload — gets you an imageId you can reuse.
  2. Call /try-on with { products: [{ externalId }], person: { image: { source: { id: imageId } } } } for repeat generations against known products, or with a full inline product when introducing a new SKU.
The inline person.image.source.url and person.image.source.fileKey paths are convenient one-shot conveniences but they re-download/re-upload on every call. Stick to /images/upload once you’re in steady state.

Examples

curl -X POST "https://api.genlook.app/tryon/v1/try-on" \
  -H "x-api-key: gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [{ "externalId": "shirt-42" }],
    "person": { "image": { "source": { "id": "ephemeral/customer/ttl-7d/.../20260512-….jpeg" } } }
  }'

Response

generationId
string
required
Poll GET /generations/:id every 2s until status is COMPLETED or FAILED.
status
string
required
Initial status: PENDING.
productExternalId
string
The product’s external ID. Echoes back the value you sent for named calls; on one-shot calls it’s a server-generated ID you can store and re-use to reference the same product later.
{
  "generationId": "cm8gen456xyz",
  "status": "PENDING",
  "productExternalId": "shirt-42"
}

Errors

CodeHTTPMeaning
PRODUCT_NOT_FOUND404The referenced externalId doesn’t exist (or has expired). Retry with a full inline payload.
PRODUCT_IMAGES_REQUIRED400One-shot call (no externalId) without any image.
CUSTOMER_IMAGE_REQUIRED400person is missing.
CUSTOMER_IMAGE_FETCH_FAILED400person.image.source.url could not be downloaded — DNS fail, host unreachable, or non-2xx status.
MULTIPART_FILE_NOT_FOUND400A fileKey from data doesn’t appear in the multipart payload.
VALIDATION_FAILED400Request body failed validation — see details[] for the offending fields.
INSUFFICIENT_CREDITS402Account is out of credits.
RESERVED_EXTERNAL_ID409product.externalId starts with _anon_, which is reserved for server-generated IDs.
Full catalog at Errors. If a reference call returns PRODUCT_NOT_FOUND, the product has fallen out of cache — retry with the full inline payload to recreate it. No sync loop required.

Watermarking

If your account has a logo configured, the result comes back with the logo composited in the bottom-left corner. Pass output: { watermark: false } to skip it on a single call. See Watermark for configuration.