Product Management

Product endpoints let a customer integration list and inspect the products in one catalogue, including variants, offers, images, enrichment progress, and moderation state.

Authenticate a product request

Each product read requires its own catalogue-scoped, single-use bearer token. Generate the token on your server:

curl -X POST https://platform.youzu.ai/api/v1/token \
  -H "x-client-key: YOUR_CLIENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "actionResource": "product",
    "actionType": "read",
    "catalogueId": "550e8400-e29b-41d4-a716-446655440000"
  }'

Send the returned token in Authorization: Bearer YOUR_TOKEN. The token supplies both client and catalogue scope; do not send clientId or catalogueId in a product query. A token is consumed by one request, so generate another token for pagination, brand lookup, or product detail.

Product routes

Method Path Purpose
GET /api/v1/product List and filter products
GET /api/v1/product/brands List brands available in the token's catalogue
GET /api/v1/product/{id} Retrieve one product by ID
POST /api/v1/product/search/near-space Find products in the same visual space or category
POST /api/v1/product/user-products/{productId} Save a product for the token-scoped user
DELETE /api/v1/product/user-products/{productId} Remove a product saved by the token-scoped user

List and filter products

curl "https://platform.youzu.ai/api/v1/product?page=1&limit=20&process_status=completed&in_stock=true&sort=updated_at&order=desc" \
  -H "Authorization: Bearer YOUR_TOKEN"

Query parameters use snake_case:

Parameter Description
page Page number, minimum 1; defaults to 1
limit Page size from 1 to 100; defaults to 10
search Search product names and SKUs; maximum 500 characters
category_id One category ID or comma-separated category IDs
brand_id Filter by brand ID; use /brands to discover IDs
is_published Filter by whether a live offer is published
in_stock Filter by whether a live offer is in stock
process_status pending, processing, completed, or failed
moderation_status Result status such as approved, pending, or flagged, or violation severity high, medium, or low
custom_properties URL-encoded, non-array JSON object matched against supplier properties
price_min, price_max Non-negative inclusive offer-price range; when both are present, price_min must not exceed price_max
currency Case-insensitive three-letter currency used by price filtering and sorting; normalized to uppercase and defaults to EUR
sort created_at, updated_at, or price
order asc or desc

List responses include customer-facing product records and pagination metadata:

{
  "success": true,
  "data": [
    {
      "id": "b60d9e58-2607-4ad5-a069-8ce77b8ad41d",
      "name": {"en": "Ergonomic Office Chair"},
      "price": {"USD": 299.99},
      "inStock": true,
      "isPublished": true,
      "url": "https://shop.example/products/chair-001",
      "externalRef": "CLIENT:CATALOGUE:550e8400-e29b-41d4-a716-446655440000:PRODUCT:CHAIR-001",
      "sku": "CHAIR-001",
      "versionHash": "8f2b9f1e6dd54a03",
      "images": [],
      "variants": [],
      "offers": [],
      "processStatus": "processing",
      "processing": {
        "completedStages": 3,
        "totalStages": 5,
        "currentStage": "indexing",
        "stages": [
          {"key": "ingest", "done": true},
          {"key": "images", "done": true},
          {"key": "enrichment", "done": true},
          {"key": "indexing", "done": false},
          {"key": "dedup", "done": false}
        ]
      },
      "moderation": null
    }
  ],
  "meta": {
    "currentPage": 1,
    "pageSize": 20,
    "totalPages": 4,
    "totalItems": 72
  }
}

Response bodies use camelCase. Depending on the source data and processing state, a product can also include its description, discounted price, brand, categories, identifiers, dimensions, weight, colour, custom properties, variant axes, attributes, storage-backed image URLs, timestamps, and nullable moderation result.

Each entry in variants can include variantValues, a dynamic map of configuration axes to values, for example {"color":"black","capacity":"256gb"}. Newly inferred keys and string values are lowercased, and keys normally use lower_snake_case. Treat the map as extensible and preserve unknown keys rather than relying on a fixed list of axes.

Search by visual space

POST /api/v1/product/search/near-space finds products in the same visual space or category as one query image. Generate a single-use product:read token and provide exactly one of these inputs:

  • file: a decodable JPEG, PNG, or WebP multipart upload no larger than 10 MiB.
  • image_url: a public HTTP or HTTPS URL without embedded credentials. Every redirect must remain on public network addresses, and the downloaded image must be a decodable JPEG, PNG, or WebP no larger than 10 MiB.
  • detectionId: the UUID returned for an object by /api/v1/object-detection; Youzu safely retrieves the cached source image and crops its validated bounding box.

For an image URL:

curl -X POST "https://platform.youzu.ai/api/v1/product/search/near-space?matchLevel=similar" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://images.example.com/rooms/office.webp",
    "limit": 20
  }'

For a direct upload, send file and optional limit fields as multipart/form-data. For a cached detection, send detectionId and optional limit in JSON. limit defaults to 20 and accepts 1 through 100; the optional matchLevel query parameter is exact, similar, or broad.

The response uses the same { success, data, meta } product-list envelope shown above. A 400 indicates an invalid input or unsafe URL, 404 means a cached detection is no longer available, 413 indicates an image over 10 MiB, and 502 indicates that the remote image or product service was unavailable.

Save products for a user

Saved-product routes use the user carried by the bearer token. Supply a stable userReference when creating each token so the saved list belongs to the intended customer. Generate a separate single-use token for every operation:

  • Use product:create for POST /api/v1/product/user-products/{productId}. The product must exist in the token-scoped catalogue. Its optional JSON body can include generation_id to associate the saved item with a non-deleted Youzu generation owned by the same token-scoped user. Success returns 201 and {"message":"Product saved successfully"}.
  • Use product:delete for DELETE /api/v1/product/user-products/{productId}. Catalogue scope is stored with the saved item, so removal remains available even if the upstream product was later deleted. Success returns 204 with no response body.

The productId is a product identifier from a catalogue-scoped product response. Never reuse the read token that returned the product for a save or delete request.

Understand processing state

processStatus is the product-level summary. The processing object reports progress through these ordered stages:

  1. ingest — product metadata was accepted.
  2. images — source images were downloaded and stored.
  3. enrichment — AI enrichment was applied.
  4. indexing — vector search data was written.
  5. dedup — deduplication was checked.

Moderation runs separately and appears in moderation; it is not one of the five ingestion stages. Its status is pending or processing while moderation is underway, then approved, flagged, error, or skipped as a terminal outcome. A product may therefore be fully processed while moderation is pending, or carry a moderation result while another reprocessing operation is active.

The API returns real pipeline state. It does not fabricate stock counts, generic product status, AI feature lists, or an always-completed processing value.

Handle errors

Customer-facing product reads preserve valid upstream 4xx and 5xx statuses. Safe 4xx messages and details use the standard failure envelope; upstream server bodies are replaced with a generic customer-safe message. A 401 generally means the token is missing, expired, outside the required product scope, or has already been consumed.