---
title: Recommender API
description: Use the Recommender API to retrieve personalized product suggestions, alternatives, and bestsellers.
slug: recommendations/api/v1/recommender
docKind: endpoint
hub: recommendations
tableOfContents: true
---
import ApiSection from "../../../../../components/ApiSection.astro";
import ApiEndpoint from "../../../../../components/ApiEndpoint.astro";
import ApiCodeTabs from "../../../../../components/ApiCodeTabs.astro";
import { Aside, Tabs, TabItem } from "@astrojs/starlight/components";

<ApiSection>
  <div slot="code">
    <ApiEndpoint method="POST" url="https://live.luigisbox.com/v1/recommend" />
  </div>
## Overview

The Recommender API lets you retrieve personalized product suggestions, alternatives, and bestsellers programmatically. It is designed to return recommendation results based on user behavior, item similarity, popularity, and context.

### Features

- **Flexible batching:** Request multiple recommenders in a single API call.
- **Context awareness:** Restrict recommendations with request-time filters.
- **Business logic support:** Override settings for scenarios like warehouse-specific availability.

<Aside type="note">
  This endpoint is public and requires no authentication.
</Aside>

<Aside type="tip">
  To get the best results, synchronize your catalog and integrate analytics so Luigi's Box can learn user behavior and personalize recommendations.
</Aside>
</ApiSection>

<ApiSection>
## Request parameters

To get recommendations, send a `POST` request to the endpoint. The `tracker_id` is passed as a query parameter and the recommendation definition is sent in the JSON body.

### Query parameters

| Parameter | Type | Required | Description |
| :-- | :-- | :-- | :-- |
| `tracker_id` | string | ✓ | Your unique site identifier within Luigi's Box. |

### Request body

The request body is a JSON array of recommendation request objects. This allows you to batch multiple widgets in one HTTP call.

<table>
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Type</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>recommendation_type</code></td>
      <td>string</td>
      <td>
        Required. Identifier of the recommender model, for example <code>bestsellers</code> or <code>item_detail_alternatives</code>. See [Reference Models](/recommendations/models/).
      </td>
    </tr>
    <tr>
      <td><code>recommender_client_identifier</code></td>
      <td>string</td>
      <td>
        Arbitrary identifier for the widget location, such as `homepage_hero` or `cart_cross_sell`.
      </td>
    </tr>
    <tr>
      <td><code>user_id</code></td>
      <td>string</td>
      <td>
        User identifier used for personalization. For anonymous users, use a stable client identifier such as the `_lb` cookie. For logged-in users, use your own customer ID.
      </td>
    </tr>
    <tr>
      <td><code>item_ids</code></td>
      <td>array</td>
      <td>
        List of item IDs the recommendation should be based on. Required for contextual models such as alternatives or related items. Only the first 10 values are used.
      </td>
    </tr>
    <tr>
      <td><code>size</code></td>
      <td>integer</td>
      <td>
        Number of items to return. Default: <code>10</code>. Maximum: <code>50</code>.
      </td>
    </tr>
    <tr>
      <td><code>hit_fields</code></td>
      <td>array</td>
      <td>
        List of fields to return for each hit, for example <code>["title", "url", "price"]</code>.
      </td>
    </tr>
    <tr>
      <td><code>blacklisted_item_ids</code></td>
      <td>array</td>
      <td>
        List of item IDs that must be excluded from the response.
      </td>
    </tr>
    <tr>
      <td><code>recommendation_context</code></td>
      <td>object</td>
      <td>
        Request-time filter object. Supports operators like `or`, `and`, `not`, and range values using the pipe character.
      </td>
    </tr>
    <tr>
      <td><code>settings_override</code></td>
      <td>object</td>
      <td>
        Overrides model settings for this request, for example changing the availability field in a multi-warehouse setup.
      </td>
    </tr>
    <tr>
      <td><code>mark_fallback_results</code></td>
      <td>boolean</td>
      <td>
        When `true`, the response indicates whether a result came from the primary model or a fallback strategy.
      </td>
    </tr>
  </tbody>
</table>

### Request headers

| Header | Value | Required | Description |
| :-- | :-- | :-- | :-- |
| `Content-Type` | `application/json; charset=utf-8` | ✓ | Indicates JSON request format. |
| `Accept-Encoding` | `gzip, deflate` | Recommended | Enables compressed responses. |

  <div slot="code">
    <h4 class="code-section-title">Example Request</h4>

```shell
curl -X POST "https://live.luigisbox.com/v1/recommend?tracker_id=YOUR_TRACKER_ID" \
  -H "Content-Type: application/json" \
  -H "Accept-Encoding: gzip, deflate" \
  -d '[
    {
      "recommendation_type": "item_detail_alternatives",
      "item_ids": ["/products/123"],
      "size": 4
    }
  ]'
```
  </div>
</ApiSection>

<ApiSection>
## How to Make a Request

To make a valid recommendation request:

- Send a `POST` request to `https://live.luigisbox.com/v1/recommend`.
- Put `tracker_id` in the query string.
- Send one or more recommendation request objects in a JSON array.
- Use batching whenever you need recommendations for multiple widgets on the same page.

<div slot="code">
  <h4 class="code-section-title">Code Examples</h4>
  <ApiCodeTabs syncKey="recommender-api-request">
    <div slot="ruby">

```ruby
require 'faraday'
require 'json'

connection = Faraday.new(url: 'https://live.luigisbox.com') do |conn|
  conn.use FaradayMiddleware::Gzip
end

payload = [
  {
    "recommendation_type" => "item_detail_alternatives",
    "recommender_client_identifier" => "item_detail",
    "item_ids" => ["/products/123"],
    "size" => 4,
    "user_id" => "user_session_id"
  }
]

response = connection.post('/v1/recommend') do |req|
  req.params['tracker_id'] = 'your_tracker_id'
  req.headers['Content-Type'] = 'application/json'
  req.headers['Accept-Encoding'] = 'gzip, deflate'
  req.body = payload.to_json
end

if response.success?
  puts JSON.pretty_generate(JSON.parse(response.body))
else
  puts "Error: #{response.status} - #{response.body}"
end
```
    </div>
    <div slot="php">

```php
<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client();

$payload = [
    [
        "recommendation_type" => "item_detail_alternatives",
        "recommender_client_identifier" => "item_detail",
        "item_ids" => ["/products/123"],
        "size" => 4,
        "user_id" => "user_session_id"
    ]
];

$response = $client->request('POST', 'https://live.luigisbox.com/v1/recommend', [
    'query' => ['tracker_id' => 'your_tracker_id'],
    'json' => $payload,
    'headers' => [
        'Accept-Encoding' => 'gzip, deflate',
    ],
]);

echo json_encode(json_decode($response->getBody()), JSON_PRETTY_PRINT);
```
    </div>
    <div slot="javascript">

```javascript
const axios = require('axios');

const payload = [
  {
    recommendation_type: 'item_detail_alternatives',
    recommender_client_identifier: 'item_detail',
    item_ids: ['/products/123'],
    size: 4,
    user_id: 'user_session_id',
  },
];

axios
  .post('https://live.luigisbox.com/v1/recommend', payload, {
    params: { tracker_id: 'your_tracker_id' },
    headers: {
      'Content-Type': 'application/json',
      'Accept-Encoding': 'gzip, deflate',
    },
  })
  .then((response) => {
    console.log(JSON.stringify(response.data, null, 2));
  })
  .catch((error) => {
    console.error(error.message);
  });
```
    </div>
  </ApiCodeTabs>
</div>
</ApiSection>

<ApiSection>
## Response structure

The response is a JSON array in the same order as the request objects you sent.

### Response attributes

| Field | Type | Description |
| :-- | :-- | :-- |
| `recommendation_id` | string | Unique identifier for the generated recommendation batch. |
| `recommendation_type` | string | Recommender model used for this result set. |
| `recommender_client_identifier` | string | Widget identifier echoed from the request. |
| `hits` | array | List of recommended items. |
| `hits[].type` | string | Usually `item`. |
| `hits[].url` | string | Identity of the recommended product. |
| `hits[].attributes` | object | Product data such as title, price, and image fields. |
| `hits[].pinned` | boolean | Present when the result was added by customization. |
| `generated_at` | string | Generation timestamp. |

  <div slot="code">
    <h4 class="code-section-title">Example Response</h4>

```json
[
  {
    "generated_at": "2025-01-13T12:00:00+00:00",
    "recommendation_id": "req-123-abc",
    "recommendation_type": "item_detail_alternatives",
    "recommender_client_identifier": "item_detail",
    "hits": [
      {
        "url": "/products/123456",
        "type": "item",
        "attributes": {
          "title": "Premium Wireless Headphones",
          "price": "199.00 EUR",
          "image_link": "http://myshop.com/imgs/headphones.jpg",
          "availability": "in_stock"
        }
      },
      {
        "url": "/products/789012",
        "type": "item",
        "attributes": {
          "title": "Standard Wired Headphones",
          "price": "89.00 EUR",
          "image_link": "http://myshop.com/imgs/wired.jpg",
          "availability": "in_stock"
        },
        "pinned": true
      }
    ]
  }
]
```
  </div>
</ApiSection>

<ApiSection>
## Error handling

The API uses standard HTTP status codes to indicate success or failure. All error responses are returned as a JSON array.

| Status | Description |
| :-- | :-- |
| `200 OK` | Success. The body contains recommendation results. |
| `400 Bad Request` | Malformed JSON, wrong content type, or missing required parameters. |
| `404 Not Found` | The `tracker_id` or `recommendation_type` could not be matched. |
| `405 Method Not Allowed` | The endpoint only accepts `POST` requests. |
| `500 Server Error` | Internal error. If persistent, contact support. |

  <div slot="code">
    <h4 class="code-section-title">Error responses</h4>

<Tabs>
  <TabItem label="400 Bad Request">
```json
[
  {
    "reason": "tracker_id must be filled"
  }
]
```
  </TabItem>
  <TabItem label="404 Not Found">
```json
[
  {
    "reason": "Unable to find recommender mapping. Check your tracker_id: 'your-tracker-id' and recommendation types: 'bestsellers'."
  }
]
```
  </TabItem>
  <TabItem label="405 Method Not Allowed">
```text
405 Method Not Allowed
The method is not allowed for the requested URL.
```
  </TabItem>
</Tabs>
  </div>
</ApiSection>
