Skip to main content
The Genlook Virtual Try-On API lets you add AI-powered virtual try-on to any e-commerce platform, mobile app, or custom flow. The minimal integration is two HTTP calls: upload the customer photo, run the try-on. Products are managed for you — no catalog sync, no cleanup loop.

Base URL

https://api.genlook.app/tryon/v1

Authentication

Every request needs the x-api-key header.
curl -H "x-api-key: gk_your_api_key" \
  https://api.genlook.app/tryon/v1/products?limit=1
Grab your API key by creating an account on app.genlook.app

TypeScript SDK

For Node 20+, Deno, Bun, or edge runtimes, install @genlook/api — every endpoint on this page has a typed method, automatic retries, and a one-line generation poller.
pnpm add @genlook/api    # or npm i / yarn add
import { Genlook } from "@genlook/api";

const client = new Genlook({ apiKey: process.env.GENLOOK_API_KEY! });
The endpoint pages below show the SDK call alongside the raw HTTP example. Browser usage is intentionally unsupported — keep the API key on your server. See the SDK guide for configuration, error handling, and the waitFor poller, or clone the Next.js example app for a full working integration.

Credits

Each try-on consumes 1 credit. Credits don’t expire. Out of credits → the call returns 402 Payment Required with code INSUFFICIENT_CREDITS. Read your remaining balance with GET /account/credits; top-ups are done from the Genlook dashboard.
Building a new product? We run a startup program (including free credits) for new products integrating Genlook — email thibault@genlook.app to learn more.

Rate limits

Default 100 requests/minute per account. Over the limit returns 429 Too Many Requests with code RATE_LIMITED.

Errors

Every error response uses the same shape — { code, message, status } (plus details for validation). Branch on the code string. See Errors for the full catalog.

How a try-on flows

The inline products[] field is the recommended path. /try-on creates or refreshes the product and runs the generation in a single call — no separate “create product” step, no catalog sync loop. products is an array that holds exactly one item for now (multi-product try-on is on the roadmap). Three shapes per item:
  • Inline (default for first-time products){ products: [{ externalId, title, description, images: [...] }] }. Creates the product if it doesn’t exist, updates it if it does. Lives 15 days from last use; every generation refreshes the timer, so actively-used products never expire.
  • Reference (cheap repeat call){ products: [{ externalId: "shirt-42" }] }. Once a product exists, subsequent generations just send the ID.
  • One-shot{ products: [{ title, description, images: [...] }] } (no externalId). The response includes a generated productExternalId you can re-use to reference the same product later. One-shot products live 7 days from last use.
Most integrations only need the inline path. POST /products exists as an opt-in alternative for callers who want explicit catalog management — lifetime TTL by default, visible in GET /products and the dashboard. You don’t need it to get started.

Person image options

POST /try-on takes a person object whose image.source holds exactly one of three fields:
FieldWhen to use
person.image.source.idRecommended. Image id from a prior POST /images/upload. Reusable across generations, and the only path that controls cropping (crop=false on upload).
person.image.source.urlQuick one-shot from a remote URL. Server downloads + 4:5-crops + processes on every call.
person.image.source.fileKeyShip the bytes in the same /try-on request (multipart). Always 4:5-cropped.
Pre-uploading wins for repeat use — the upload happens once and the same id can power many generations. The inline url / fileKey paths always apply the person-aware 4:5 crop; if you need a raw image, go through /images/upload with crop=false.
The previous request shape — a top-level singular product, a customer object, top-level customerId, and top-level useWatermark / retentionDays — is still accepted but deprecated (not a breaking change). Migrate to products: [...], person.image.source, externalUserId, and output.watermark / output.keepForDays. See the Changelog.

Response format

JSON. Errors use a stable { code, message, status } shape:
{
  "code": "INSUFFICIENT_CREDITS",
  "message": "Insufficient credits. Top up the account balance and retry.",
  "status": 402
}
Switch on code (a documented enum) — full catalog at Errors. The shortest version: upload the customer photo once, reference products by externalId, fall back to an inline upsert if you hit PRODUCT_NOT_FOUND. See Full Example (Python) for a runnable template, and the Quickstart for a 5-minute walkthrough.

Next steps

Quickstart

Two-call try-on in 5 minutes

TypeScript SDK

Typed client for Node, Deno, Bun & edge

Example app (Next.js)

Clone a full working integration

Full Example (Python)

Ref-first / upsert-on-miss template

Try-On endpoint

Every option on /try-on

Watermark

Brand every result with your logo

Changelog

Release notes — currently v1.0.0

Migrating from the alpha

Recipes for upgrading alpha integrations