Pre-launch API. The concepts described here are settled, but the API shape is not: request and response fields, parameters and defaults can still change. Build against it, and talk to your Luigi's Box contact before you put an integration into production.
const url = 'https://api.eu1.luigisbox.ai/discovery/v1/variants?channel_id=example';const options = { method: 'POST', headers: { 'x-lbx-visitor-id': 'example', Authorization: 'Bearer <token>', 'Content-Type': 'application/json' }, body: '{"guid":"example","ids":["example"],"return_fields":["example"]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url 'https://api.eu1.luigisbox.ai/discovery/v1/variants?channel_id=example' \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --header 'x-lbx-visitor-id: example' \ --data '{ "guid": "example", "ids": [ "example" ], "return_fields": [ "example" ] }'Resolve the variant group of each product id and return its siblings.
A follow-up to a search or collections result (like /facets), so a token
authorized on either surface may call it. channel_id is a query parameter;
the ids, optional guid, and optional return_fields travel in the JSON body.
Siblings and total cover only the members this channel can serve. Each
id’s siblings are capped at 100; when a group is larger, the first 100 by
@id are returned and total reflects the group’s visible size, so
truncation is detectable.
variants maps every requested id to its variant siblings (the id itself
excluded) and the group’s total size.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”Channel identifier (serving destination).
Channel identifier (serving destination).
Header Parameters
Section titled “Header Parameters ”Stable per-browser visitor identifier, generated client-side and persisted (e.g. a UUID in localStorage or a first-party cookie). Send it whether or not personalization is on: it is what links a request to a visitor’s history and to the analytics events reporting it. Keep it stable across page loads, sessions and token refreshes; never generate it server-side, or every visitor collapses into one.
Stable per-browser visitor identifier, generated client-side and persisted (e.g. a UUID in localStorage or a first-party cookie). Send it whether or not personalization is on: it is what links a request to a visitor’s history and to the analytics events reporting it. Keep it stable across page loads, sessions and token refreshes; never generate it server-side, or every visitor collapses into one.
Request Body required
Section titled “Request Body required ”JSON body accepted by the variants endpoint.
object
Example generated
{ "guid": "example", "ids": [ "example" ], "return_fields": [ "example" ]}Responses
Section titled “ Responses ”Successful Response
Response of POST /discovery/v1/variants.
object
Each requested id mapped to its variant siblings and the group’s visible size.
object
One requested id’s variant siblings, with the group’s visible size.
object
The variant group’s other members this channel can serve — the requested id itself excluded. Capped at 100; when the group is larger the first 100 by @id are returned and total reflects its visible size.
Single result item returned by discover endpoints.
Flat structure — all catalog fields are top-level keys.
@id and @type are always present; every other key is a catalog field.
object
Unique identity of the hit.
Type of the hit (e.g. ‘product’).
Member count of the group, counting only the members this channel can serve and including the requested id when it is one of them. An ungrouped or not-found id has empty siblings and total 0. Otherwise total minus the number of returned siblings is one for a requested id this channel can serve, zero for one it cannot, and more than one when the group is larger than the 100-member cap.
Example generated
{ "variants": { "additionalProperty": { "siblings": [ { "@id": "example", "@type": "example" } ], "total": 1 } }}Malformed request
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Missing or invalid credentials
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Authenticated but not permitted
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Request validation failed
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Rate limit exceeded
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Upstream service failed
Canonical error body — every non-2xx response uses this shape.
object
Machine-readable error context; empty object when there is nothing to add.
object
One field-level reason a request was rejected.
object
Path to the offending value from the request root, e.g. ["body", "filters", 0, "operator"].
What is wrong with the value at loc.
Stable machine code for the problem, e.g. missing or string_too_short.
Human-readable, actionable error message.
Example generated
{ "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example"}Was this page helpful?
Thanks.