---
title: Search API
description: Use the search endpoint to get a fulltext search functionality with advanced filtering options.
slug: search/api/v1/search
docKind: endpoint
hub: search
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/search" />
  </div>
## Overview

Use the search endpoint to build fulltext search with advanced filtering, faceting, ranking, and merchandising capabilities.

To use Search well, make sure your product data is synchronized with Luigi's Box. See [Indexing](/indexing/) for setup details. Search relevance can also learn from user behavior, so you should integrate [Analytics](/analytics/) alongside the API.

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

<ApiSection>
## Request parameters

### Required parameters

| Parameter | Type | Required | Description |
| :-- | :-- | :-- | :-- |
| `tracker_id` | string | ✓ | Your unique site identifier within Luigi's Box. |
| `q` | string |  | The user's search query. Optional when `f[]` filters are provided. |

### Optional parameters

#### Identity & personalization

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `user_id` | string | Identifier used for personalization. For authenticated users, use the analytics `customer_id`. For anonymous users, use the analytics `client_id`. Omit for non-personalized requests. See [User identification](/platform-foundations/api-principles/#user-identification) and [Events API common parameters](/analytics/api/events/#common-parameters). |
| `client_id` | string | Stable anonymous identifier. Must match the `client_id` sent in analytics. See [Events API common parameters](/analytics/api/events/#common-parameters). |

#### Filtering & ranking

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `f[]` | string | Filter results using `key:value` syntax, for example `category:Shoes`. Filters on the same field are combined with OR, filters on different fields are combined with AND, and numeric/date ranges use the pipe character such as `price:10|100`. Special values like `value_missing` and `geo_range` are also supported. |
| `neg_f[]` | string | Exclude results using `key:value` syntax, for example `category:Shoes`. Negative filters on the same field exclude hits matching any of the provided values. Numeric and date attributes support ranges using the pipe character, such as `price:10|100`, including open-ended ranges like `price:10|`. |
| `f_must[]` | string | Applies filters with strict AND logic. Useful when you need multiple required values on the same field. |
| `size` | integer | Number of hits to return. Default: `10`. Maximum: `200`. |
| `sort` | string | Sort order in `field:direction` format, for example `price:asc`. Explicit sorting overrides the default AI ranking. Sorting by distance requires `context[geo_location]`. |
| `sort_type` | string | Sorts specific result types only, for example `sort_item=price:asc`. |
| `quicksearch_types` | string | Comma-separated secondary content types to include in `quicksearch_hits`, such as `category,brand`. |
| `facets` | string | Comma-separated list of facets to return. You can limit values per facet using `:count`, for example `brand,color:5`. |
| `dynamic_facets_size` | integer | Maximum number of additional AI-selected facets. Default: `0`. |
| `page` | integer | Result page number. Default: `1`. |
| `from` | integer | Result offset. Alternative to `page`. |
| `use_fixits` | boolean | Controls automatic typo correction and redirects. Default: `true`. |
| `prefer[]` | string | Soft filters used for query-time boosting. Syntax is the same as `f[]`, but non-matching items are not excluded. |

#### Context & model selection

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `ctx[]` | string | Arbitrary context tags for model selection, for example `warehouse:berlin`. These must match analytics contexts. |
| `qu` | boolean | Enables Query Understanding. When `true`, Search may return a `suggested_url`. Send it only together with `user_id`. |

#### Output control

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `hit_fields` | string | Comma-separated list of fields to include in the response `attributes`. |
| `remove_fields` | string | Comma-separated list of fields to exclude from the response. |
| `non_collapsed_variants` | boolean | Returns variants as individual hits instead of nesting them under a parent product. Default: `false`. |

### Context parameters

| Parameter | Type | Description |
| :-- | :-- | :-- |
| `context[geo_location]` | string | User coordinates in `lat,lon` format. Required for distance filtering and distance sorting. |
| `context[geo_location_field]` | string | Catalog field that contains coordinates. Default: `geo_location`. |
| `context[availability_field]` | string | Custom field used for availability ranking. Must contain `0` or `1`. |
| `context[availability_rank_field]` | string | Custom field for detailed availability ranking with integer values `1` to `15`. |
| `context[boost_field]` | string | Custom numeric boost field with values `0` to `3`. |
| `context[freshness_field]` | string | Custom ISO 8601 date field used for freshness ranking. |

### Request headers

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

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

```shell
curl "https://live.luigisbox.com/search?tracker_id=YOUR_TRACKER_ID&q=harry+potter&f[]=type:item" \
  -H "Accept-Encoding: gzip, deflate"
```
  </div>
</ApiSection>

<ApiSection>
## How to Make a Request

To make a request:

1. Send a `GET` request to `https://live.luigisbox.com/search`.
2. Include `tracker_id` and optionally `q`.
3. Pass filters, facets, sorting, and personalization through query parameters.
4. Keep `hit_fields` tight to reduce payload size when building a custom UI.

For a full walkthrough, see [Quickstart: Search](/quickstart/search/).

  <div slot="code">
    <h4 class="code-section-title">Code Examples</h4>
    <ApiCodeTabs syncKey="search-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

response = connection.get('/search') do |req|
  req.params['tracker_id'] = 'your_tracker_id'
  req.params['q'] = 'harry potter'
  req.params['f[]'] = 'type:item'
  req.headers['Accept-Encoding'] = 'gzip, deflate'
end

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

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

use GuzzleHttp\Client;

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

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

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

axios
  .get('https://live.luigisbox.com/search', {
    params: {
      tracker_id: 'your_tracker_id',
      q: 'harry potter',
      'f[]': 'type:item',
    },
    headers: {
      'Accept-Encoding': 'gzip, deflate',
    },
  })
  .then((response) => {
    console.log(JSON.stringify(response.data, null, 2));
  })
  .catch((error) => {
    if (error.response) {
      console.error(`Error: HTTP Status ${error.response.status}`);
      console.error(JSON.stringify(error.response.data));
    } else {
      console.error(error.message);
    }
  });
```
      </div>
    </ApiCodeTabs>
  </div>
</ApiSection>

<ApiSection>
## HTTP Response

The response is a structured JSON object containing top-level `results` and `next_page` fields.

### Results fields

| Field | Description |
| :-- | :-- |
| `query` | Requested query string. |
| `corrected_query` | Query correction markup when the query was altered. |
| `total_hits` | Total number of hits for the requested type. |
| `hits` | Result objects for the requested type. |
| `facets` | Facets and their counts. Filtered facets return all values to support multi-select. |
| `filters` | Filters applied to the results. |
| `quicksearch_hits` | Results for secondary types requested via `quicksearch_types`. |
| `suggested_facet` | Optional facet suggested for narrowing the result set. |
| `suggested_url` | Optional redirect URL for direct-match or fixit behavior. |
| `campaigns` | Banner campaigns associated with the query. |

### Hit fields

| Field | Description |
| :-- | :-- |
| `url` | Unique identifier of the result object. |
| `attributes` | Catalog fields stored for the hit, such as title, brand, or price. |
| `pinned` | Present when the result was added by customization. |
| `type` | Result type, for example `item`. |
| `nested` | Nested objects associated with the hit, such as variants. |

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

```json
{
  "results": {
    "query": "putter",
    "corrected_query": "<strike>harry</strike><strike>potter</strike> <b>putter</b>",
    "filters": [
      "type:product"
    ],
    "total_hits": 223,
    "hits": [
      {
        "url": "/jucad-putter-right-hand/?variantId=2448462",
        "attributes": {
          "title": "Jucad Putter Right Hand",
          "price_eur": "149 €",
          "brand": [
            "Jucad"
          ],
          "categories": [
            "Golfers",
            "Clubs",
            "Putters"
          ],
          "image_link": "https://cdn.myshoptet.com/usr/demoshop.luigisbox.com/user/shop/detail/1817277.jpg",
          "availability_rank_text": "In Stock"
        },
        "type": "item",
        "nested": []
      }
    ],
    "facets": [
      {
        "name": "price_amount",
        "type": "float",
        "values": [
          {
            "value": "0.69|30.0",
            "hits_count": 56,
            "normalized_hits_count": 0.18
          },
          {
            "value": "30.0|60.0",
            "hits_count": 34,
            "normalized_hits_count": 0.11
          }
        ]
      }
    ],
    "offset": "20",
    "campaigns": []
  },
  "next_page": "https://live.luigisbox.com/search?q=putter&tracker_id=179075-204259&page=2"
}
```
  </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
{
  "size": [
    "size exceeded limit of 200 hits per page, use pagination instead of fetching too many hits at once"
  ]
}
```
  </TabItem>
  <TabItem label="404 Not Found">
```text
Catalog for tracker_id: "your-tracker-id" not found.
```
  </TabItem>
</Tabs>
  </div>
</ApiSection>
