Skip to main content
POST
/
tryon
/
v1
/
products
curl -X POST "https://api.genlook.app/tryon/v1/products" \
  -H "x-api-key: gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "shirt-42",
    "title": "Red tee",
    "description": "Soft cotton regular fit",
    "images": [
      { "url": "https://cdn.example/front.jpg" },
      { "url": "https://cdn.example/back.jpg", "role": "top-back" }
    ]
  }'
{
  "externalId": "shirt-42",
  "title": "Red tee",
  "description": "Soft cotton regular fit",
  "metadata": null,
  "autoDetectImageRoles": false,
  "validForDays": null,
  "expiresAt": null,
  "lastUsedAt": null,
  "createdAt": "2026-05-13T10:00:00.000Z",
  "updatedAt": "2026-05-13T10:00:00.000Z",
  "images": [
    { "sourceUrl": "https://cdn.example/front.jpg", "role": null, "order": 0 }
  ]
}

Documentation Index

Fetch the complete documentation index at: https://docs.genlook.app/docs/llms.txt

Use this file to discover all available pages before exploring further.

You probably don’t need this endpoint. The recommended path is the inline product field on POST /try-on — same upsert semantics, one less call. Use this endpoint only when you want:
  • a lifetime TTL by default (inline upserts default to 15 days),
  • the product listed in GET /products and visible in the dashboard,
  • to pre-register a catalog without immediately running a generation.
Creates or updates a product, matched on (account, externalId). The same endpoint handles both — pass full fields the first time, then partial fields to edit later. Products created via this endpoint default to lifetime (no expiry); pass validForDays to opt into a TTL.

Content types

  • application/json — when all images are URLs.
  • multipart/form-data — when you ship image bytes inline. The JSON payload arrives in a data form field; each images[].fileKey references a file field by name.

Request

externalId
string
required
Your product ID. Reused on subsequent calls to update the same product. Don’t start it with _anon_ — that prefix is reserved for IDs we generate.
title
string
Optional. Helps the AI classify the product category more accurately. Preserved on updates if omitted.
description
string
Optional. Helps the AI classify the product category more accurately. Preserved on updates if omitted.
images
array
Replaces the full image list on update. Each entry has exactly one of:
  • url — remote URL.
  • fileKey — name of a multipart file field in the same request.
Optional role is top-front or top-back. Up to 10 images per request, 10 MB each.
autoDetectImageRoles
boolean
default:"false"
Have the server figure out which image is the front view vs the back view automatically.
validForDays
integer | null
How long the product lives between uses, in days. Defaults to null (kept forever) when created via this endpoint. Pass a number (1–365) to set a custom lifetime, null to opt back into “kept forever” on an existing product, or omit to preserve the existing value.
metadata
object
Free-form JSON returned on GET /products/:externalId.
imageUrls
string[]
deprecated
Legacy alias for images: [{ url }, …]. Still accepted; will be removed in the next major. Prefer images.
curl -X POST "https://api.genlook.app/tryon/v1/products" \
  -H "x-api-key: gk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "externalId": "shirt-42",
    "title": "Red tee",
    "description": "Soft cotton regular fit",
    "images": [
      { "url": "https://cdn.example/front.jpg" },
      { "url": "https://cdn.example/back.jpg", "role": "top-back" }
    ]
  }'

Response

Returns the full product state after the upsert. See List Products for the field-by-field reference.
{
  "externalId": "shirt-42",
  "title": "Red tee",
  "description": "Soft cotton regular fit",
  "metadata": null,
  "autoDetectImageRoles": false,
  "validForDays": null,
  "expiresAt": null,
  "lastUsedAt": null,
  "createdAt": "2026-05-13T10:00:00.000Z",
  "updatedAt": "2026-05-13T10:00:00.000Z",
  "images": [
    { "sourceUrl": "https://cdn.example/front.jpg", "role": null, "order": 0 }
  ]
}