@genlook/api is the official TypeScript SDK for the Virtual Try-On API. Every endpoint in this reference has a typed method; on top of that you get automatic retries on 429/5xx, typed error classes, and waitFor — a generation poller that replaces the hand-rolled polling loop.
Works on Node 20+, Deno ≥ 1.40, Bun ≥ 1.0, and edge runtimes (Cloudflare Workers, Vercel Edge). Browser usage is intentionally unsupported — API keys must never reach client-side bundles, so proxy through your backend.
Example app — Next.js + @genlook/api
A runnable e-commerce demo: product grid, try-on widget, server-side API routes that keep the key off the browser.
Clone it, add your API key,
pnpm dev.Install
Quickstart
The full recommended flow — upload the customer photo once, run the try-on, wait for the result — is three calls:Configuration
| Option | Default | Notes |
|---|---|---|
apiKey | — | Required. Get one on app.genlook.app. |
baseUrl | https://api.genlook.app/tryon/v1 | Override for sandbox/staging. |
timeoutMs | 60_000 | Per-request. Large customer-photo uploads on slow links may need more. |
maxRetries | 2 | Retries 429 / 5xx / transport failures; respects Retry-After. |
fetch | global fetch | Pass your own if the runtime hides the global. |
Resources
| Resource | Methods | Purpose |
|---|---|---|
client.images | upload | Pre-upload customer photos, reuse the imageId across generations. |
client.tryOn | create | Queue a try-on (inline-upsert the product or reference it by externalId). |
client.generations | retrieve, waitFor | Poll status; waitFor replaces hand-rolled polling loops. |
client.products | upsert, list, iterate, get, delete, stats | Explicit catalog management — optional, most integrations use inline tryOn. |
client.account | credits | Remaining credit balance. |
client.customers | delete | GDPR right-to-erasure (wipe per-customer images + anonymize generations). |
Waiting for a generation
client.generations.waitFor(id) polls until the generation terminates. It resolves with the completed generation, throws GenerationFailedError on FAILED, and GenerationTimeoutError if it doesn’t finish in time.
client.generations.retrieve(generationId) maps to GET /generations/:id.
Error handling
Every failed request throws a typedGenlookError subclass. Use instanceof or branch on the stable error.code:
| Class | Thrown for |
|---|---|
AuthError | 401 — missing or invalid API key |
ValidationError | 400 — invalid body, unsupported image, file too large, … |
InsufficientCreditsError | 402 INSUFFICIENT_CREDITS |
RateLimitError | 429 — carries retryAfterSeconds |
ProductNotFoundError | 404 PRODUCT_NOT_FOUND — upsert inline and retry |
GenerationNotFoundError | 404 GENERATION_NOT_FOUND |
GenerationFailedError | waitFor reached a FAILED generation |
GenerationTimeoutError | waitFor exceeded its timeoutMs |
GenlookConnectionError / GenlookTimeoutError | Transport failure / request exceeded the client’s timeoutMs |
GenlookError carries code, status, details, requestId, and an err.is("PRODUCT_NOT_FOUND") helper. The full code catalog lives at Errors.
Uploads
client.images.upload accepts any standard byte source — Blob, File, Buffer, Uint8Array, ArrayBuffer, a web ReadableStream, or a Node Readable (e.g. fs.createReadStream). Pass filename / mimeType when the source doesn’t carry them:
tryOn.create or products.upsert, reference them with fileKey and provide the bytes in the files map — the SDK marshals the multipart request for you:
Pagination
client.products.list is cursor-based. For a full catalog walk, iterate handles the cursor for you:
GDPR / right-to-erasure
Pass anexternalUserId when uploading images or creating try-ons, then wipe everything linked to that user in one call:
DELETE /customers/:id for the underlying semantics.
Next steps
Example app (Next.js)
Full working integration: upload widget, server-side routes, polling UI
Try-On endpoint
Every option on /try-on — the SDK’s
tryOn.create maps 1:1Errors
The full error-code catalog behind the typed classes
npm package
@genlook/api on the npm registry

