# Resolve variant groups for ids `POST /discovery/v1/variants` 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. ## Request example ```bash curl --request POST \ --url 'https://api.eu1.luigisbox.ai/discovery/v1/variants?channel_id=' \ --header 'x-lbx-visitor-id: ' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "guid": "example", "ids": [ "example" ], "return_fields": [ "example" ] }' ``` ## Query Parameters | Name | Type | Required | Description | Constraints | |---|---|---|---|---| | `channel_id` | `string` | Yes | Channel identifier (serving destination). | >= 1 characters | ## Header Parameters | Name | Type | Required | Description | Constraints | |---|---|---|---|---| | `x-lbx-visitor-id` | `string` | Yes | 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. | >= 1 characters | ## Request Body **Required.** ### application/json Schema: `object` #### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `guid` | `anyOf(string, null)` | No | Result-set identifier from a prior search or collections response; when given, variant groups are read from that result before falling back to the catalog. | — | | `ids` | `Array` | Yes | Catalog `@id` values to resolve, used verbatim. | >= 1 items; <= 200 items | | `return_fields` | `Array` | No | Object fields to return; empty for the default, or ['*'] for all fields. | <= 100 items | #### Request body example ```json { "guid": "example", "ids": [ "example" ], "return_fields": [ "example" ] } ``` ## Responses | Status | Description | Content | |---|---|---| | `200` | Successful Response | application/json: object | | `400` | Malformed request | application/json: object | | `401` | Missing or invalid credentials | application/json: object | | `403` | Authenticated but not permitted | application/json: object | | `422` | Request validation failed | application/json: object | | `429` | Rate limit exceeded | application/json: object | | `502` | Upstream service failed | application/json: object | ### 200 Successful Response #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `variants` | `object` | No | Each requested id mapped to its variant siblings and the group's visible size. | — | | `variants.*` | `object` | No | One requested id's variant siblings, with the group's visible size. | — | | `variants.*.siblings` | `Array` | No | 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. | — | | `variants.*.siblings[].@id` | `string` | Yes | Unique identity of the hit. | — | | `variants.*.siblings[].@type` | `string` | Yes | Type of the hit (e.g. 'product'). | — | | `variants.*.siblings[].*` | `any` | No | Additional property. | — | | `variants.*.total` | `integer` | Yes | 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. | — | ##### Response example ```json { "variants": { "additionalProperty": { "siblings": [ { "@id": "example", "@type": "example" } ], "total": 1 } } } ``` ### 400 Malformed request #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 401 Missing or invalid credentials #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 403 Authenticated but not permitted #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 422 Request validation failed #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 429 Rate limit exceeded #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ``` ### 502 Upstream service failed #### application/json Schema: `object` ##### Attributes | Attribute | Type | Required | Description | Constraints | |---|---|---|---|---| | `exception_details` | `object` | No | Machine-readable error context; empty object when there is nothing to add. | — | | `exception_details.validation_errors` | `anyOf(Array, null)` | No | Every field-level problem found in the request, when validation is what failed. Absent when the rejection is not about a specific value. | — | | `exception_details.validation_errors[].loc` | `Array` | Yes | Path to the offending value from the request root, e.g. `["body", "filters", 0, "operator"]`. | — | | `exception_details.validation_errors[].msg` | `string` | Yes | What is wrong with the value at `loc`. | — | | `exception_details.validation_errors[].type` | `string` | Yes | Stable machine code for the problem, e.g. `missing` or `string_too_short`. | — | | `exception_details.*` | `any` | No | Additional property. | — | | `reason` | `string` | Yes | Human-readable, actionable error message. | — | | `request_id` | `anyOf(string, null)` | No | Request correlation ID (matches the X-Request-Id response header). | — | ##### Response example ```json { "exception_details": { "validation_errors": [ { "loc": [ "example" ], "msg": "example", "type": "example" } ] }, "reason": "example", "request_id": "example" } ```