Base URL
Authentication
Every request needs thex-api-key header.
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.
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 returns402 Payment Required with code INSUFFICIENT_CREDITS. Read your remaining balance with GET /account/credits; top-ups are done from the Genlook dashboard.
Rate limits
Default 100 requests/minute per account. Over the limit returns429 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 inlineproducts[] 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: [...] }] }(noexternalId). The response includes a generatedproductExternalIdyou can re-use to reference the same product later. One-shot products live 7 days from last use.
Person image options
POST /try-on takes a person object whose image.source holds exactly one of three fields:
| Field | When to use |
|---|---|
person.image.source.id | Recommended. 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.url | Quick one-shot from a remote URL. Server downloads + 4:5-crops + processes on every call. |
person.image.source.fileKey | Ship the bytes in the same /try-on request (multipart). Always 4:5-cropped. |
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 (a documented enum) — full catalog at Errors.
Recommended workflow
The shortest version: upload the customer photo once, reference products byexternalId, 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

