Skip to main content
POST
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.
To test your integration without waiting on AI output, send a product whose title is mock (case-insensitive). The generation runs through the whole pipeline but returns the person image unchanged, so responses are fast and deterministic. Mock generations still consume 1 credit.

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.
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.
object
required
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).
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, which 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

Response

string
required
Poll GET /generations/:id every 2s until status is COMPLETED or FAILED.
string
required
Initial status: PENDING.
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.

Errors

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.