---
title: Top Items API
description: Retrieve most popular items of any type using the Top Items API.
slug: autocomplete/api/v1/top-items
docKind: endpoint
hub: autocomplete
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="GET" url="https://live.luigisbox.com/v1/top_items" />
  </div>
## Overview

The Top Items API returns the most popular or most relevant objects from the index, even when the user has not entered a search query. It is commonly used for “popular items” or “recommended for you” widgets.

<Aside type="caution">
  If you show top items inside an autocomplete dropdown when the user focuses an empty search box, track the rendered list as a recommendation event, not as autocomplete. Use `autocomplete_popup` as the placement identifier. See [Events API](/analytics/api/events/#recommendation-event).
</Aside>
</ApiSection>

<ApiSection>
## Request parameters

To request global top items, provide your tracker ID and the object types you want returned.

### Required parameters

| Parameter | Type | Required | Description |
| :-- | :-- | :-- | :-- |
| `tracker_id` | string | ✓ | Your unique site identifier within Luigi's Box. |
| `type` | string | ✓ | Result types and counts in the format `type:count`, for example `item:6,category:3`. |

### Optional parameters

<table>
  <thead>
    <tr>
      <th style={{ textAlign: "left" }}>Parameter</th>
      <th style={{ textAlign: "left" }}>Type</th>
      <th style={{ textAlign: "left" }}>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>f_type[]</code></td>
      <td>string</td>
      <td>
        Filters results for a specific type in the format <code>f_&lt;type&gt;[]=&lt;field&gt;:&lt;value&gt;</code>. Supports exact matches, repeated OR filters, and ranges such as <code>price:10|50</code>.
      </td>
    </tr>
    <tr>
      <td><code>hit_fields</code></td>
      <td>string</td>
      <td>
        Comma-separated list of fields to return, for example <code>title,url,price</code>.
      </td>
    </tr>
    <tr>
      <td><code>ctx[]</code></td>
      <td>string</td>
      <td>
        Model-selection context in `key:value` format, for example <code>ctx[]=warehouse:berlin</code>. Keys must match contexts reported in [Analytics](/analytics/#concepts-context).
      </td>
    </tr>
  </tbody>
</table>

### Request headers

| Header | Value | Required | Description |
| :-- | :-- | :-- | :-- |
| `Accept-Encoding` | `gzip, deflate` | Recommended | Enables compressed responses to reduce payload size. |

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

```shell
curl "https://live.luigisbox.com/v1/top_items?tracker_id=YOUR_TRACKER_ID&type=item:10" \
  -H "Accept-Encoding: gzip, deflate"
```
  </div>
</ApiSection>

<ApiSection>
## How to Make a Request

To make a valid request:

1. Send a `GET` request to `https://live.luigisbox.com/v1/top_items`.
2. Provide `tracker_id` and the requested `type` counts.
3. Add filters or model context only when needed for the placement.

For implementation guidance, see [Quickstart: Top Items API](/quickstart/autocomplete/top-items-api/).

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

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

connection = Faraday.new(url: 'https://live.luigisbox.com')
response = connection.get('/v1/top_items') do |req|
  req.params['tracker_id'] = 'your_tracker_id'
  req.params['type'] = 'item:10'
  req.headers['Accept-Encoding'] = 'gzip, deflate'
end

puts response.body if response.success?
```
      </div>
      <div slot="php">

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

use GuzzleHttp\Client;

$client = new Client();
$response = $client->request('GET', 'https://live.luigisbox.com/v1/top_items', [
    'query' => [
        'tracker_id' => 'your_tracker_id',
        'type' => 'item:10',
    ],
    'headers' => [
        'Accept-Encoding' => 'gzip, deflate',
    ],
]);

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

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

axios
  .get('https://live.luigisbox.com/v1/top_items', {
    params: {
      tracker_id: 'your_tracker_id',
      type: 'item:10',
    },
    headers: {
      'Accept-Encoding': 'gzip, deflate',
    },
  })
  .then((response) => console.log(response.data))
  .catch((error) => console.error(error));
```
      </div>
    </ApiCodeTabs>
  </div>
</ApiSection>

<ApiSection>
## Response structure

The response is a JSON object containing the resulting items.

### Response attributes

| Field | Type | Description |
| :-- | :-- | :-- |
| `hits` | array | The list of returned objects. |
| `hits[].type` | string | Object type, for example `item` or `category`. |
| `hits[].url` | string | Unique identity of the result object. |
| `hits[].attributes` | object | Indexed fields such as title, price, or image links. |
| `hits[].pinned` | boolean | Present when the result was added by customization. |
| `hits[].exact` | boolean | Indicates whether the result is an exact match. |

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

```json
{
  "hits": [
    {
      "url": "http://www.e-shop.com/products/123456",
      "attributes": {
        "image_link": "http://www.e-shop.com/assets/imgs/products/123456.jpg",
        "title": "Product X",
        "price": "5.52 EUR",
        "availability_rank_text": "true"
      },
      "type": "item",
      "exact": true
    },
    {
      "url": "http://www.e-shop.com/products/456789",
      "attributes": {
        "image_link": "http://www.e-shop.com/assets/imgs/products/456789.jpg",
        "title": "Product Y",
        "price": "12.14 EUR"
      },
      "type": "item",
      "exact": true
    }
  ]
}
```
  </div>
</ApiSection>

<ApiSection>
  <div slot="code">
    <ApiEndpoint method="GET" url="https://live.luigisbox.com/v1/personalized_top_items" />
  </div>
## Get personalized top items

Use this endpoint to retrieve recommendations based on a specific user's history.

- For standard item recommendations, request `type=item:10`.
- If you request `type=queries`, the endpoint returns the last queries performed by that user.
</ApiSection>

<ApiSection>
## Request parameters (personalized)

### Required parameters

| Parameter | Type | Required | Description |
| :-- | :-- | :-- | :-- |
| `tracker_id` | string | ✓ | Your site identifier. |
| `user_id` | string | ✓ | User ID to personalize for. |
| `type` | string | ✓ | Requested object types and counts. |

### Optional parameters

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `ctx[]` | string | Model-selection context parameters. |

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

```shell
curl "https://live.luigisbox.com/v1/personalized_top_items?tracker_id=YOUR_TRACKER_ID&user_id=UID&type=item:10" \
  -H "Accept-Encoding: gzip, deflate"
```
  </div>
</ApiSection>

<ApiSection>
## How to Make a Personalized Request

Include the `user_id` parameter whenever you want Luigi's Box to rank results for a specific user profile.

  <div slot="code">
    <h4 class="code-section-title">Code Examples</h4>
    <ApiCodeTabs syncKey="personalized-top-items-request">
      <div slot="ruby">

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

connection = Faraday.new(url: 'https://live.luigisbox.com')
response = connection.get('/v1/personalized_top_items') do |req|
  req.params['tracker_id'] = 'your_tracker_id'
  req.params['user_id'] = 'UID'
  req.params['type'] = 'item:10'
  req.headers['Accept-Encoding'] = 'gzip, deflate'
end

puts response.body if response.success?
```
      </div>
      <div slot="php">

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

use GuzzleHttp\Client;

$client = new Client();
$response = $client->request('GET', 'https://live.luigisbox.com/v1/personalized_top_items', [
    'query' => [
        'tracker_id' => 'your_tracker_id',
        'user_id' => 'UID',
        'type' => 'item:10',
    ],
    'headers' => [
        'Accept-Encoding' => 'gzip, deflate',
    ],
]);

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

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

axios
  .get('https://live.luigisbox.com/v1/personalized_top_items', {
    params: {
      tracker_id: 'your_tracker_id',
      user_id: 'UID',
      type: 'item:10',
    },
    headers: {
      'Accept-Encoding': 'gzip, deflate',
    },
  })
  .then((response) => console.log(response.data))
  .catch((error) => console.error(error));
```
      </div>
    </ApiCodeTabs>
  </div>
</ApiSection>

<ApiSection>
## Error handling

The API uses standard HTTP status codes to indicate success or failure.

| HTTP Status | Description |
| :-- | :-- |
| `200 OK` | The request succeeded and results are returned. |
| `400 Bad Request` | The request was malformed — missing or invalid parameters. |
| `404 Not Found` | The `tracker_id` does not match any known catalog. |
| `500 Server Error` | Internal error. If persistent, contact support. |
| `504 Gateway Timeout` | The request took too long to process. Retrying may succeed. |

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

<Tabs>
  <TabItem label="400 Bad Request">
```json
{
  "tracker_id": ["tracker_id must be filled"]
}
```
  </TabItem>
  <TabItem label="404 Not Found">
```text
Catalog for tracker_id: "your-tracker-id" not found.
```
  </TabItem>
</Tabs>
  </div>
</ApiSection>
