Skip to content

    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.

    Selecting fields

    View source

    A hit carries catalog fields as top-level keys. Which ones arrive is decided by three things, in order:

    1. What your credentials may see. A browser token never receives private: fields.
    2. What the surface returns by default. Configured per surface.
    3. What you asked for with return_fields.

    An array of field names in the request body:

    Terminal window
    curl -X POST 'https://api.eu1.luigisbox.ai/discovery/v1/search?channel_id=lbn_4hj9tv&surface_id=lbs_search_main' \
    -H 'Authorization: Bearer <token>' \
    -H 'X-Lbx-Visitor-Id: 8f14e45f-…' \
    -H 'Content-Type: application/json' \
    -d '{
    "type": "product",
    "query": "shirt",
    "return_fields": ["@title", "price", "image_url", "url"]
    }'
    FormMeaning
    priceOne field, by exact name
    params.*Every field under a nested object
    *Everything visible to your credentials

    * must stand alone. Combining it with other names is a 422* already includes them.

    Limits: up to 100 fields per request, and 512 characters per name.

    @id and @type are always present on a hit, whether or not you list them.

    A product card usually needs a handful of fields. Requesting them explicitly makes the response smaller:

    const CARD_FIELDS = ['@title', 'price', 'list_price', 'image_url', 'url', 'availability'];
    const body = { type: 'product', query, return_fields: CARD_FIELDS };

    Different placements want different projections. An autocomplete row needs a title, a thumbnail and a price; a results-page card needs more; a product page needs everything. Keep one list per placement rather than one list for the whole integration.

    Field visibility follows from the field name and from the credential you authenticated with; it cannot be overridden per request.

    Field nameExampleBrowser tokenServer token
    Plaincolor, priceVisibleVisible
    @ registered@id, @title, @categoryVisibleVisible
    lbx: derivedlbx:group_primaryVisibleVisible
    private:private:marginNeverVisible

    Two consequences:

    • Anything a shopper must not read belongs in private:. Discovery requests and responses are visible in browser developer tools. A cost, a margin, a supplier code or an internal note in a plain field is public data.
    • A server-side integration can see private: fields, so it decides what reaches the page. If your backend renders search results, set return_fields to the fields you intend to display. Passing the whole hit through to your template exposes every field it carries.

    Asking for a private: field with a browser token is not an error; the field is absent from the response.

    See How to structure your data for the writing side of this.

    An attribute holding an object is addressed by dot-path:

    {
    "@id": "product/sku-1001",
    "params": { "material": "cotton", "fit": "regular" }
    }

    Address it either one field at a time or as a whole group:

    { "return_fields": ["params.material"] } // just that one
    { "return_fields": ["params.*"] } // the whole group

    The same dot-path works in filters and in facet fields.

    Catalog metadata lists every attribute an object type carries, with its value shape:

    Terminal window
    curl -G 'https://api.eu1.luigisbox.ai/catalog/v1/lbc_8w3k2p/types/product/attributes' \
    --data-urlencode 'query=price' \
    -H 'Authorization: Bearer <token>'

    See Catalog metadata.