1.4.0 — 2026-06-17
Not a breaking change. The previous request shape is still accepted (deprecated). Existing integrations keep
working unchanged — migrate at your own pace.
Changed
POST /try-onrequest shape redesigned. The canonical body is now:products: [...]— an array (was the singularproductobject). Exactly one item for now; multi-product try-on is on the roadmap.person: { image: { source: { id | url | fileKey } } }— the shopper photo (was thecustomerobject).externalUserId— opaque, no-PII attribution + GDPR key (wascustomerId).output: { watermark, keepForDays }— result controls (was the top-leveluseWatermarkandretentionDays).keepForDaysis one of1,3,7and sets how long the generation’s stored images are kept.
POST /images/uploadform fields renamed.externalUserId(wascustomerId) andkeepForDays(wasretentionDays).cropis unchanged. The returnedimageIdis passed asperson.image.source.idon/try-on.
Deprecated
- Previous try-on / upload shapes. The old forms —
product(singular object),customer(object), top-levelcustomerId,useWatermark,retentionDayson/try-on, andcustomerId/retentionDaysform fields on/images/upload— are still accepted but deprecated. Preferproducts[],person.image,externalUserId,output.watermark/output.keepForDays, andkeepForDaysin new code.
1.3.0 — 2026-06-17
Changed
- Image references moved under a
sourcesub-object. The customer photo onPOST /try-onand each product image onPOST /try-on(inlineproduct) andPOST /productsnow nest their reference insidesource:- Customer:
customer: { source: { id | url | fileKey } }. - Product images:
images: [{ source: { url | fileKey }, classifications? }]. The optionalclassificationsobject now sits alongsidesourceon each image entry.
- Customer:
Deprecated
- Legacy flat image shape. The old top-level form —
customer: { id | url | fileKey }andimages: [{ url | fileKey, classifications }]— is still accepted but deprecated. Migrate to thesourcesub-object; prefer it in new code.
1.3.0 — 2026-06-25
Removed
autoClassifyImageson products. Removed fromPOST /products, inline/try-onproduct payloads, and product responses. Classification runs based on detected product type instead.
1.2.0 — 2026-05-18
Added
autoClassifyImagesflag on products. Opt-in switch onPOST /productsand the inlineproductpayload ofPOST /try-on. Defaults tofalseso generations stay as fast as possible — flip it totrueon products where the smart front/back picker is worth the extra processing time.
Changed
- Smarter image selection for harder categories. For some product types the engine now picks the image showing the product worn on a real person or bust rather than the flat packshot, when such an image is available. No API change required.
Removed
autoDetectImageRolesfield. Replaced byautoClassifyImages(same intent, broader scope). Update any callers passing the old name.
1.1.0 — 2026-05-14
Added
- Per-call retention on
POST /images/uploadandPOST /try-on. New optionalretentionDaysbody field (one of1,3,7) overrides the account-level customer-retention window for that single upload. Omitting the field keeps today’s behaviour. - Customer identifier on uploads.
POST /images/uploadnow accepts an optionalcustomerIdbody field. When set, the upload is tracked server-side so it can later be wiped by the new GDPR endpoint.POST /try-onalready acceptedcustomerId; same semantics now apply for both endpoints. - GDPR delete endpoint —
DELETE /tryon/v1/customers/:customerId. Deletes every customer-image and result image stored under the givencustomerId, anonymizes the corresponding generation rows, and removes upload tracking metadata. Idempotent, returns204 No Content. See Delete Customer Data. PRODUCT_IMAGE_FETCH_FAILEDerror code. When the AI pipeline can’t download a product image URL during processing, the generation transitions toFAILEDwitherrorCode: "PRODUCT_IMAGE_FETCH_FAILED"onGET /generations/:id. Mirrors the synchronousCUSTOMER_IMAGE_FETCH_FAILED400 already raised byPOST /try-on.errorCodeon the generation-status response.GET /generations/:idnow returns a stableerrorCodealongsideerrorMessagewhenever the failure was raised as a typed error. Switch on the code instead of parsing the message.
1.0.0 — 2026-05-12
First stable release. The surface is intentionally small: upload a customer photo, run a try-on, poll the result. Everything else (products, account management, watermark) is optional.Added
- Inline
productfield onPOST /try-on. Three usage modes in one endpoint:- Reference an existing product by
externalId. - Create or update a product inline (full payload), then run the generation.
- One-shot — omit
externalIdand the response returns a generated ID you can re-use.
- Reference an existing product by
- Customer image — three input modes on
POST /try-on:customer: { id }referencing a priorPOST /images/upload(recommended for repeat use).customer.url— server downloads on demand.customer.fileKey— multipart file inline with the request.
- Multipart product images on
POST /try-onandPOST /products. Mix URLs and uploaded files in the sameimagesarray. cropflag onPOST /tryon/v1/images/upload. Defaulttrue; passfalseto preserve original framing.useWatermarkflag onPOST /try-on. Defaulttrue; passfalseto skip the account’s watermark logo for a single generation.productExternalIdin every/try-onresponse — echoes the caller’s value for named products, returns a server-generated ID for one-shots.- Per-product stats at
GET /tryon/v1/products/:externalId/stats— totals by status and average generation time. - Product lifetime model:
- Products created via
POST /productsare kept forever by default. SetvalidForDaysto opt into a TTL. - Products created inline via
/try-onlive 15 days from last use (refreshed on every generation). - One-shot products live 7 days from last use.
- Pass
validForDays: nullon an update to opt into “kept forever” later.
- Products created via
- Partial updates on
POST /products. Send only the fields you want to change; omitted fields stay as they were. - Watermark feature — composite your brand logo onto every generation. Configure once in the dashboard; opt out per-call with
useWatermark: false. See Watermark. - Unified error responses. Every failure returns
{ code, message, status, details? }with a stablecodefrom a documented enum — switch on that instead of parsing messages. Full list at Errors.
Changed
- Single
productfield onPOST /try-onreplaces the olderproductId/externalProductIdbody field. The endpoint figures out reference vs. upsert vs. one-shot from what’s present. - Single
customerobject onPOST /try-onreplaces the oldcustomerImageIdshortcut. Exactly one ofcustomer.id,customer.url, orcustomer.fileKeymust be set. POST /productssupports partial updates. Hitting it with an existingexternalIdand only the field(s) you want to change merges over stored values.- Product responses (
POST /products,GET /products,GET /products/:externalId) return the full product shape — same fields everywhere, noproductId(callers reference byexternalId). - Product images on responses are now
{ sourceUrl, order }. For URL-sourced imagessourceUrlechoes back the URL you supplied; for multipart-uploaded images it’s an opaque internal reference you can ignore. - Consistent identifiers.
productExternalIdis now returned on every generation. The reserved prefix_anon_is used for server-generated IDs. - Concurrent identical calls are safe. Parallel inline upserts with the same content resolve to a single product — no duplicates, no race conditions.
Removed
PATCH /tryon/v1/products/:externalId. UsePOST /productswith the fields you want to change.- Generation ratings (👍 / 👎) are no longer exposed on the public API — the stats endpoint returns counts and timings only.
GET /tryon/v1/generations(paginated list). Track your own generation ids fromPOST /try-onresponses and pollGET /generations/:idfor each one.resultImageKeyhas been dropped fromGET /generations/:id. UseresultImageUrlinstead — re-fetch the endpoint when the URL expires.productIdhas been dropped fromPOST /productsresponses. Reference products byexternalId.
Deprecated
imageUrls: string[]on product upsert. Useimages: [{ url }, …]instead. The old field is still accepted in v1 and will be removed in v2.
Documentation
- New Quickstart — two-call try-on (upload → try-on) in under five minutes.
- New Full Example (Python) — ref-first / upsert-on-miss template you can copy.
- New Watermark page.
- New Breaking changes page — migration recipes for callers coming from the alpha.
Alpha
Unreleased. No version was assigned. The endpoint shapes, response fields, and product lifecycle rules churned regularly during this period. If you have an integration that talked to the alpha surface, the Breaking changes page covers everything you need to update.Versioning
The Virtual Try-On API follows semantic versioning going forward:- Patch (
1.0.x) — bug fixes and additive non-breaking changes. - Minor (
1.x.0) — new endpoints, new optional fields, new response fields. Existing requests keep working. - Major (
2.0.0+) — breaking changes. Always announced ahead of time with a parallel migration window; the old major stays available until a posted sunset date.
/tryon/v1/*. Subscribe to release notifications at support@genlook.app.
