> ## 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.

# List, Get & Delete Products

> Inspect or remove products you've created. Most integrations don't need these — the inline /try-on flow doesn't depend on them.

<Note>
  These endpoints are for introspection and cleanup, not part of the core try-on flow. If you're using the inline [`POST
      /try-on`](/tryon-api/endpoints/create-try-on) pattern you can skip them entirely — products self-manage via TTL.
</Note>

`GET /tryon/v1/products` paginates through products you've registered with a stable `externalId`. One-shot products (created by `/try-on` without an `externalId`) are not part of your catalog and don't appear here.

`GET /tryon/v1/products/:externalId` fetches a single product by ID. This works for any ID you have, including server-generated one-shot IDs returned from `/try-on`.

`DELETE /tryon/v1/products/:externalId` removes a product. Past generations keep their snapshot of the product details — deleting only removes the product itself, not the history.

## List

<ParamField query="limit" type="number">
  1–200, default 50.
</ParamField>

<ParamField query="cursor" type="string">
  `nextCursor` from the previous page.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.genlook.app/tryon/v1/products?limit=10" \
    -H "x-api-key: gk_your_api_key"
  ```

  ```bash Get one theme={null}
  curl "https://api.genlook.app/tryon/v1/products/shirt-42" \
    -H "x-api-key: gk_your_api_key"
  ```

  ```bash Delete theme={null}
  curl -X DELETE "https://api.genlook.app/tryon/v1/products/shirt-42" \
    -H "x-api-key: gk_your_api_key"
  ```

  ```ts Node SDK theme={null}
  import { Genlook } from "@genlook/api";

  const client = new Genlook({ apiKey: process.env.GENLOOK_API_KEY! });

  // Single page
  const page = await client.products.list({ limit: 10 });
  for (const p of page.items) console.log(p.externalId);

  // Auto-paginate every product
  for await (const product of client.products.iterate({ limit: 50 })) {
    console.log(product.externalId);
  }

  // Get one
  const product = await client.products.get("shirt-42");

  // Delete (idempotent)
  await client.products.delete("shirt-42");
  ```
</RequestExample>

## Response shape

Each product has:

<ResponseField name="externalId" type="string" required>Your product ID.</ResponseField>

<ResponseField name="title" type="string" required />

<ResponseField name="description" type="string" required />

<ResponseField name="images" type="array" required>
  One entry per image: `{ sourceUrl, order }`.

  * `sourceUrl` — the URL you supplied on upsert. For images shipped as multipart bytes this is an opaque internal reference (e.g. `upload://…`); treat it as a stable identifier, not as something you can fetch.
  * `order` — 0-indexed position in the original list.
</ResponseField>

<ResponseField name="metadata" type="object | null">Whatever JSON you sent on upsert.</ResponseField>

<ResponseField name="validForDays" type="integer | null">
  How long the product lives between uses, in days. `null` means kept forever.
</ResponseField>

<ResponseField name="lastUsedAt" type="string | null">
  ISO timestamp of the last generation that referenced this product. `null` until the first use.
</ResponseField>

<ResponseField name="expiresAt" type="string | null">
  ISO timestamp at which the product will be removed if it's not used again. `null` when `validForDays` is `null` (kept forever). Refreshed on every generation.
</ResponseField>

<ResponseField name="createdAt" type="string" required>ISO 8601 timestamp.</ResponseField>
<ResponseField name="updatedAt" type="string" required>ISO 8601 timestamp of the last edit.</ResponseField>

The list endpoint wraps `items` in `{ items, nextCursor, hasMore, count }`. `nextCursor` is `null` (or omitted) on the last page.

<ResponseExample>
  ```json List theme={null}
  {
    "items": [
      {
        "externalId": "shirt-42",
        "title": "Red tee",
        "description": "Soft cotton regular fit",
        "images": [
          { "sourceUrl": "https://cdn.example/front.jpg", "order": 0 },
          { "sourceUrl": "https://cdn.example/back.jpg", "order": 1 }
        ],
        "metadata": null,
        "validForDays": null,
        "lastUsedAt": "2026-05-12T14:32:00.000Z",
        "expiresAt": null,
        "createdAt": "2026-04-30T08:11:00.000Z",
        "updatedAt": "2026-04-30T08:11:00.000Z"
      }
    ],
    "nextCursor": null,
    "hasMore": false,
    "count": 1
  }
  ```

  ```json Not found (404) theme={null}
  {
    "code": "PRODUCT_NOT_FOUND",
    "message": "Product 'shirt-42' not found.",
    "status": 404
  }
  ```
</ResponseExample>
