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. An integration can also record whether an offer's vendor accepted Youzu's enhanced variant data.
Authenticate a product request
Product routes use the single-use bearer tokens described in Authentication. Use product:read for list, detail, and near-space requests, and product:update to record a vendor's enhancement decision. Generate a fresh token for every request. For the catalogue-free workflow, omit the catalogue ID when creating the token and never send client or catalogue IDs as product query parameters.
See Upload Product Data and Track Processing for pagination and processing readiness, and Check Moderation Results for moderation fields and completion.
Product routes
| Method | Path | Purpose |
|---|---|---|
GET |
/api/v1/product |
List and filter products |
GET |
/api/v1/product/{id} |
Retrieve one product by ID |
PUT |
/api/v1/product/offers/{offerId} |
Record whether the offer's vendor accepted enhanced variant data |
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 a brand ID already returned in a product record |
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, partial, 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, AI-extracted and translated attributes, public image metadata, timestamps, and nullable current 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.
Understand variants and offers
A variant contains Youzu's consolidated, enhanced name, description, and attributes. Its offers represent the vendor-specific records that contributed to that variant. One variant can therefore contain offers from multiple vendors.
Every offer includes a UUID vendorId. Vendor-supplied values remain available on the offer as originalName, originalDescription, and read-only originalAttributes, so an integration can show them alongside the enhanced variant values.
vendorAcceptedEnhancement records the vendor's decision about the enhanced variant data:
null: no decision has been recorded.true: the vendor accepted the enhanced data.false: the vendor explicitly declined the enhanced data.
This field is metadata only. Changing it does not apply, regenerate, or overwrite any product, variant, or offer data.
Record vendor acceptance
Use the offer ID returned inside a variant and a fresh product:update token. The request body accepts only the required vendorAcceptedEnhancement boolean:
curl -X PUT "https://platform.youzu.ai/api/v1/product/offers/5bf718f6-75c1-4145-b88b-2a0949226d68" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"vendorAcceptedEnhancement":true}'
The response contains the updated offer:
{
"success": true,
"data": {
"id": "5bf718f6-75c1-4145-b88b-2a0949226d68",
"variantId": "9820d390-3207-4015-888c-58d546b8b40f",
"vendorId": "bd0a6fe7-9288-4654-8770-fb3e9f670231",
"originalName": {"en": "Office chair black"},
"originalDescription": {"en": "Adjustable office chair"},
"originalAttributes": {"colour": "black"},
"vendorAcceptedEnhancement": true,
"price": {"USD": 299.99},
"inStock": true,
"isPublished": true,
"sku": "CHAIR-001-BLACK",
"url": "https://shop.example/products/chair-001-black",
"externalRef": "VENDOR-CHAIR-001-BLACK",
"versionHash": "3f41982425e33cf1"
}
}
Send false to record an explicit decline. The undecided null state is returned only before a decision; it cannot be submitted to clear or reset one. The token determines the tenant and catalogue, and the request cannot change the offer's vendor, original values, or enhanced variant data.
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:createforPOST /api/v1/product/user-products/{productId}. The product must exist in the token-scoped catalogue. Its optional JSON body can includegeneration_idto associate the saved item with a non-deleted Youzu generation owned by the same token-scoped user. Success returns201and{"message":"Product saved successfully"}. - Use
product:deleteforDELETE /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 returns204with 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: pending and processing are nonterminal; completed, partial, and failed are terminal. partial means some selected work failed while usable product output remains.
The processing object is authoritative for stage-level progress. It returns only stages in the catalogue's compiled, selected pipeline graph. Records use the stable keys ingest, image_acquisition, image_indexing, semantic_text_indexing, ai_processing, identity_enrichment, dedup_indexing, and deduplication, and every record includes status, required, and attemptCount. A returned stage can be skipped when runtime processing determines that no work is needed.
processing.errors contains customer-safe { code, stage, retryable } entries. Internal provider text and traces are omitted. See Upload Product Data and Track Processing for the complete status and stage table.
Moderation runs separately and appears in moderation; it is not a product-processing stage. Each applicable stageResults entry is nonterminal at pending or processing and terminal at approved, flagged, error, or skipped. The aggregate moderation.status is a summary, so inspect stage results to determine completion.
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 routes preserve supported upstream 4xx statuses with safe messages. Upstream server and transport failures return 502 without exposing the upstream response body. A 401 generally means the token is missing, expired, outside the required product scope, or has already been consumed.