> ## Documentation Index
> Fetch the complete documentation index at: https://docs.neuronsearchlab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Search

> Free-text search over your catalogue, ranked and personalised by the same contexts as recommendations. Or keep your own search engine and send NSL its results.

Search lets your application send a free-text query and receive ranked catalogue items through the same pipeline used for recommendations, at `POST https://api.neuronsearchlab.com/v1/search`. Results use the same item shape as recommendations, so the same rendering code works for both.

> [!NOTE]
>
> Call search from your backend with an access token that has the `neuronsearchlab-api/read` scope. The console's own search box uses a different, internal endpoint that is not meant for your product.

## When to use search

Use search when the user types what they want: a product search box, a content discovery query, a help-article lookup. NSL matches the query by meaning and, if enabled, by keywords, then applies the context's filters, ranking and rules.

Recommendations start from a user or item embedding. Search starts from the query text.

## Call the REST API

```bash theme={null}
curl -X POST "https://api.neuronsearchlab.com/v1/search" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "waterproof trail shoes",
    "user_id": "user-123",
    "context_id": 101,
    "limit": "10",
    "filter": ["category:footwear"]
  }'
```

| Field | Type | Required | Description |
| - | - | - | - |
| `query` | string | yes | Free-text search query. |
| `user_id` | string | no | End-user identifier for telemetry, personalization context, and event attribution. |
| `context_id` | integer | no | Context ID generated by the dashboard. |
| `limit` | string | no | Number of results to return. Defaults to `20`, maximum `100`. |
| `filter` | string or string\[] | no | Metadata filter shorthand such as `category:footwear`. |
| `scope` | string | no | JSON-encoded structured filters, for example `{"filters":[{"column":"brand","operator":"=","value":"Acme"}]}`. |

Hybrid retrieval options are also accepted per request: `query_retrieval_enabled`, `fusion_method` (`rrf` or `weighted`), `semantic_weight`, `keyword_weight` and `keyword_fields`. Set these on the context's pipeline instead where you can, so every caller gets the same behaviour. See [Pipeline](https://docs.neuronsearchlab.com/console/pipeline.md).

## Use the JavaScript SDK

```ts theme={null}
const results = await sdk.search({
  query: "waterproof trail shoes",
  userId: "user-123",
  contextId: 101,
  limit: 10,
  filter: ["category:footwear"],
});

console.log(results.data);
```

The JavaScript SDK posts to `/v1/search` and captures the returned `request_id` for subsequent `trackEvent()` calls. Pass `resultItemIds` to send your own engine's results.

## Use the PHP SDK

```php theme={null}
$results = $sdk->search([
    'query' => 'waterproof trail shoes',
    'userId' => 'user-123',
    'contextId' => '101',
    'limit' => 10,
    'filter' => ['category:footwear'],
]);

var_dump($results['data']);
```

The PHP SDK uses the same Core API endpoint and mirrors the request ID propagation behavior.

## Bring your own search engine

If your product already has search (Algolia, Elasticsearch, Typesense or your own database), keep it. Send NSL the query and the item IDs your engine showed, and NSL records the search and returns recommendations that complement those results:

```bash theme={null}
curl -X POST "https://api.neuronsearchlab.com/v1/search" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "waterproof trail shoes",
    "user_id": "user-123",
    "result_item_ids": [3187, 3190, 3201],
    "limit": "6"
  }'
```

The IDs you send are excluded from the response, so what comes back can sit beside your results. If you only want to record the search, send it to `/v1/events` with `query` and no `item_id`, or call `trackSearch()` in the SDKs.

Either way, the search becomes an event that steers the user's later recommendations by the weight of your Search event. See [Searches are events](https://docs.neuronsearchlab.com/integrate/events.md#searches-are-events).

## Response shape

Search responses use the standard list envelope:

```json theme={null}
{
  "object": "list",
  "message": "Search results fetched",
  "request_id": "66666666-6666-4666-8666-666666666666",
  "url": "/v1/search",
  "query": "waterproof trail shoes",
  "data": [
    {
      "id": 3187,
      "object": "recommendation",
      "item_id": 3187,
      "rank": 1,
      "score": 0.94,
      "item": {
        "id": 3187,
        "object": "item",
        "name": "Waterproof Trail Shoes",
        "description": "Lightweight trail shoes with a waterproof upper.",
        "metadata": {
          "category": "footwear"
        }
      }
    }
  ],
  "recommendations": [
    {
      "id": 3187,
      "object": "recommendation",
      "item_id": 3187,
      "rank": 1,
      "score": 0.94
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "limit": 10
}
```

Each item includes explanation metadata when available. The request-level explanation shows whether semantic, keyword, or hybrid search candidates were used.

## Measure search engagement

Every search with a user is also recorded as a search event that steers that user's later recommendations. Use the returned `request_id` when sending click, view, add-to-cart, or conversion events. The official SDKs handle this automatically after `search()`. If you call REST directly, include `request_id` in your event payload so analytics can attribute engagement to the search result set.

See the [search endpoint reference](https://docs.neuronsearchlab.com/api-reference/endpoint/search.md) for the full contract.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.