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.

    Object lookup

    View source

    POST /discovery/v1/objects fetches catalog objects you already know by reference — the products in a cart, the categories a page references, a hand-picked list — with no query, no ranking and no pagination.

    Terminal window
    curl -X POST 'https://api.eu1.luigisbox.ai/discovery/v1/objects?channel_id=lbn_4hj9tv' \
    -H 'Authorization: Bearer <token>' \
    -H 'X-Lbx-Visitor-Id: 8f14e45f-…' \
    -H 'Content-Type: application/json' \
    -d '{
    "references": [
    "product/@id:product/sku-1001",
    "product/sku:ABC-987"
    ],
    "return_fields": ["@title", "price", "image_url"]
    }'
    Query parameterRequiredNotes
    channel_idYesServing destination — the channel’s visibility rules still apply
    Body fieldRequiredNotes
    referencesYes1–200 references
    return_fieldsNoField projection, up to 100 fields

    There is no surface_id and no type field: each reference names its own type, and nothing is being ranked.

    A reference is three parts:

    <type>/<field>:<value>

    For example:

    product/@id:product/sku-1001
    product/sku:ABC-123
    product/ean:5901234123457
    • <type> is the object type, as in @type.
    • <field> is the field to match on — any field the object carries.
    • <value> is the value to match.

    product/@id:product/sku-1001 looks the product up by the id discovery returned; product/ean:5901234123457 finds the same product by its barcode, so an external key resolves without a mapping table of your own.

    A reference must resolve to at most one object. Two objects matching the same reference is a 422.

    This is the same reference shape that analytics events use, so a reference you already build for reporting can be reused here unchanged.

    {
    "objects": [
    {
    "@id": "product/sku-1001",
    "@type": "product",
    "@title": "Blue Cotton T-Shirt",
    "price": 29.9,
    "image_url": "https://cdn.example.com/products/sku-1001.jpg"
    }
    ]
    }
    • Order is not guaranteed to match your request. Key the response by @id rather than zipping it against your input.
    • References that match nothing are absent. There is no placeholder and no error. Diff the response against what you asked for to find the gaps.
    const byId = new Map(objects.map((o) => [o['@id'], o]));
    const missing = wantedIds.filter((id) => !byId.has(id));

    A missing object was deleted or is excluded by the channel’s visibility rules; a product hidden from this channel is invisible here as it is in search.

    SituationEndpoint
    Render the cart, or a wishlistObject lookup
    Turn @category / @brand references into titles and URLsObject lookup
    Resolve a barcode or partner SKU to a productObject lookup
    Hydrate a hand-picked list in an email or CMS blockObject lookup
    Find products matching a phraseSearch
    Show everything in a categoryCollections
    Suggest what else to buyRecommendations

    Use object lookup when you already know which objects you want and need their data. Use a discovery endpoint when determining which objects those are is the question.

    Up to 200 references fit in one call. Resolving a 40-item cart with 40 requests costs 40 round trips and 40 rate-limit entries; one request costs one.

    async function hydrate(references) {
    const url = `${API}/discovery/v1/objects?channel_id=${channelId}`;
    const results = [];
    for (let i = 0; i < references.length; i += 200) {
    const { objects } = await fetch(url, {
    method: 'POST',
    headers: { ...headers, 'Content-Type': 'application/json' },
    body: JSON.stringify({
    references: references.slice(i, i + 200),
    return_fields: CARD_FIELDS,
    }),
    }).then((r) => r.json());
    results.push(...objects);
    }
    return results;
    }

    Objects fetched this way were not ranked, so there is no result set to attribute to. If you render them somewhere a shopper can act on — a cart, a wishlist — report the interactions as normal. See Sending events.