---
title: "Search API"
slug: "search-api"
abstract: "Overview of the SearchService class used to search for content in SitecoreAI indexes."
---
# Search API

The Search API that uses the [`SearchService`](https://github.com/Sitecore/content-sdk/blob/v1.3.1/packages/search/src/search-service.ts#L98) class allows Content SDK apps to query SitecoreAI search indexes to create tailored search experiences for different content types and user needs. This enables quick retrieval of content items and operations such as sorting, paginating, limiting results, etc. It abstracts the underlying search implementation and provides a consistent API.

The API has the following capabilities:

- Use generic types to model documents for better IDE support and type safety
- Sort results and use dot notation for nested properties
- Limit and paginate results
- Use custom fetch options for advanced use cases

## Configuration

To initialize the `SearchService` class, you can create an instance of it using a configuration object as shown.

```csharp
import { SearchService } from '@sitecore-content-sdk/search';

const searchService = new SearchService({
  contextId: 'SITECORE_EDGE_CONTEXT_ID',
});
```

The object expects the `SITECORE_EDGE_CONTEXT_ID` that you can retrieve from the **Developer settings** tab of your environment in the SitecoreAI Deploy App. After initialization, you can use the search method of the `SearchService` to retrieve results from SitecoreAI.

## Supported parameters

The search method expects the ID of the search index and also supports several other parameters used to sort, paginate, limit, and offset results.

<table style="width:100%;" class="informaltable frame-void rules-rows"><thead><tr><th class="th"><p>Parameter</p></th><th class="th"><p>Type</p></th><th class="th"><p>Description</p></th></tr></thead><tbody><tr><td class="td"><p><code class="code">searchIndexID</code></p></td><td class="td"><p>string</p></td><td class="td"><p>The ID of the SitecoreAI search index to retrieve results from.</p><p><span class="emphasis"><em>Required</em></span></p></td></tr><tr><td class="td"><p><code class="code">keyphrase</code></p></td><td class="td"><p>string</p></td><td class="td"><p>Use phrases to search the index for specific content. Mutually exclusive with <code class="code">seedItemId</code> and <code class="code">seedItemUrl</code>.</p></td></tr><tr><td class="td"><p><code class="code">seedItemId</code></p></td><td class="td"><p>string</p></td><td class="td"><p>ID of the item to use as the seed for a More Like This (MLT) query. Mutually exclusive with <code class="code">keyphrase</code> and <code class="code">seedItemUrl</code>. Only available in versions <code class="code">2.4.0</code> and above.</p></td></tr><tr><td class="td"><p><code class="code">seedItemUrl</code></p></td><td class="td"><p>string</p></td><td class="td"><p>URL of the item to use as the seed for a More Like This (MLT) query. Mutually exclusive with <code class="code">keyphrase</code> and <code class="code">seedItemId</code>. Only available in versions <code class="code">2.4.0</code> and above.</p></td></tr><tr><td class="td"><p><code class="code">sort</code></p></td><td class="td"><p>Object or Array of objects</p></td><td class="td"><p>Specify an object or array of objects containing the name and order to sort results by.</p></td></tr><tr><td class="td"><p><code class="code">limit</code></p></td><td class="td"><p>number</p></td><td class="td"><p>Specify the limit to restrict the number of results returned.</p></td></tr><tr><td class="td"><p><code class="code">offset</code></p></td><td class="td"><p>number</p></td><td class="td"><p>Specify a number to drop that many results. Use with <code class="code">limit</code> for pagination.</p></td></tr><tr><td class="td"><p><code class="code">locale</code></p></td><td class="td"><p>string</p></td><td class="td"><p>Specify the locale for the search. Required for multi-locale index configurations (for example, <code class="code">'en'</code>, <code class="code">'fr-FR'</code>, <code class="code">'el-GR'</code>). Omit for single-locale indexes. Only available in versions <code class="code">2.3.0</code> and above.</p></td></tr><tr><td class="td"><p><code class="code">facet</code></p></td><td class="td"><p><code class="code">FacetRequest</code></p></td><td class="td"><p>Specify facet configuration to retrieve facet counts and/or filter results by facet values. Use <code class="code">all: true</code> to return counts for all enabled facets, fields to filter by specific values, or both combined. Only available in versions <code class="code">2.3.0</code> and above.</p></td></tr></tbody></table>

> [!important]
> `seedItemUrl` can only be used with indexes of type `site`. These indexes are the result of a site crawl.

## Examples

The following sections demonstrate examples using the SearchService for common scenarios.

### Simple search

A basic search only requires the `searchIndexId`. The default limit is 10, so it returns only 10 results.

```csharp
const response = await searchService.search({
  searchIndexId: '1234567890',
});

console.log(`Found ${response.total} results`);
response.results.forEach((result) => {
  console.log(result);
});
```

### Search with keyphrase

You can also search using a keyphrase as shown:

```csharp
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'sitecore',
});

console.log(`Found ${response.total} results matching "sitecore"`);
```

### Search with a generic type

The `SearchService` supports TypeScript generics, allowing you to define the shape of your search document for type safety and better IDE support.

The following example demonstrates using a type called `Article` to retrieve results and display its contents. This ensures predictable results.

```csharp
import { SearchService } from '@sitecore-content-sdk/search';

type Article = {
  id: string;
  title: string;
  description: string;
  publishDate: string;
  author: {
    name: string;
    email: string;
  };
  tags: string[];
}

const searchService = new SearchService({
  contextId: 'your-context-id',
});

// TypeScript now knows the shape of the search document
const response = await searchService.search<Article>({
  searchIndexId: '1234567890',
  keyphrase: 'typescript',
});

// Type-safe access to properties
response.results.forEach((article) => {
  console.log(article.title);
  console.log(article.author.name);
  console.log(article.tags.join(', '));
});
```

### Search with basic sorting

The `SearchService` supports sorting results using a single object specifying the name and order. The following example sorts the search results by the `publishDate` in the descending order (most recent first).

```csharp
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'article',
  sort: {
    name: 'publishDate',
    order: 'desc', // Most recent first
  },
});
```

### Search with multi-field sorting

You can also specify multiple fields to sort. Instead of a single object, you should specify this as an array of objects. The following example sorts the search results by `category` in the ascending order, followed by `price` in ascending order, and finally by `rating` in the descending order.

```csharp
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'electronics',
  sort: [
    {
      name: 'category',
      order: 'asc', // First sort by category
    },
    {
      name: 'price',
      order: 'asc', // Then by price within each category
    },
    {
      name: 'rating',
      order: 'desc', // Finally by rating (highest first)
    },
  ],
});
```

### Search with type sorting

You can sort fields when you're using generics. TypeScript verifies the existence of the sort field in this case.

```csharp
type Product = {
  id: string;
  name: string;
  price: number;
  rating: number;
  category: string;
}

const response = await searchService.search<Product>({
  searchIndexId: '1234567890',
  sort: {
    name: 'category', // TypeScript hints that this field exists
    order: 'desc',
  },
});

/* TypeScript error: Property 'invalidField' does not exist
const invalidSort = {
  name: 'invalidField',
  order: 'asc',
};
*/
```

### Search with nested sorting

Using dot notation (`.`), you can sort nested properties.

```csharp
type Order = {
  id: string;
  orderDate: string;
  customer: {
    name: string;
    email: string;
  };
  items: Array<{
    productId: string;
    quantity: number;
  }>;
}

const response = await searchService.search<Order>({
  searchIndexId: '1234567890',
  sort: {
    name: 'customer.name', // TypeScript hints that this field exists
    order: 'asc',
  },
});
```

### Search with limited results

To limit the number of results returned, you can use the limit property. The default value is 10 and the maximum value allowed is 500.

```csharp
// Retrieve 5 results
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'product',
  limit: 5,
});

// Retrieve up to 500 results
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'article',
  limit: 500, // Maximum value
});
```

### Search with pagination

Use the offset parameter to implement pagination. Combined with limit, you can fetch results in pages.

```csharp
async function getPage(
  searchService: SearchService,
  searchIndexId: string,
  keyphrase: string,
  page: number,
  pageSize: number = 10
) {
  const response = await searchService.search({
    searchIndexId,
    keyphrase,
    limit: pageSize,
    offset: (page - 1) * pageSize,
  });

  return {
    results: response.results,
    total: response.total,
    page,
    pageSize,
    totalPages: Math.ceil(response.total / pageSize),
  };
}

// Usage
const page1 = await getPage(searchService, 'your-search-index-id', 'article', 1, 10);
const page2 = await getPage(searchService, 'your-search-index-id', 'article', 2, 10);
```

### Search with custom fetch options

The `SearchService` allows you to customize the underlying fetch request by passing a `[RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit)` object as the second parameter. This is useful for adding custom headers, setting timeouts, or configuring other request options.

#### Custom headers

You can set custom headers using the `headers` object containing key-value pairs of the header name and value.

```csharp
const response = await searchService.search(
  {
    searchIndexId: '1234567890',
    keyphrase: 'product',
  },
  {
    headers: {
      'X-Custom-Header': 'custom-value',
    },
  }
);
```

#### Request timeout

You can set a custom request timeout using the `signal` object that references the `AbortController`'s `signal` property.

```csharp
// Using AbortController for timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout

try {
  const response = await searchService.search(
    {
      searchIndexId: '1234567890',
      keyphrase: 'product',
    },
    {
      signal: controller.signal,
    }
  );

  clearTimeout(timeoutId);

  console.log(response.results);
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Request timed out');
  } else {
    throw error;
  }
}
```

### Search with locale

Specify the locale using the `locale` parameter. For single-locale indexes, you can omit this parameter. This is only available in versions `2.3.0` and above.

```ts
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'article',
  locale: 'fr-FR',
});
```

### Search with facets - retrieve all facet counts

Set the facet value to `all: true` to return counts for all enabled facets. You can also set the facet value to specific `fields` to narrow the results to items matching given values or use a combination of both `all:true` and specific fields.

This is only available in versions `2.3.0` and above.

```ts
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'shoes',
  facet: { all: true },
});

// response.facets contains an array of facet results
// e.g. [{ name: 'Category', value: [{ text: 'Running', count: 42 }] }]
response.facets?.forEach((facet) => {
  console.log(facet.name, facet.value);
});
```

### Search with More Like This (MLT)

Use `seedItemId` or `seedItemUrl` instead of `keyphrase` to retrieve items that are similar to a seed item. These three query fields are mutually exclusive, so provide only one of them per request. `SearchService` throws a `TypeError` if more than one is provided, or if a seed field is empty or contains only whitespace.

```ts
import { SearchService } from '@sitecore-content-sdk/search';

const searchService = new SearchService({
  contextId: 'SITECORE_EDGE_CONTEXT_ID',
});

const response = await searchService.search({
  searchIndexId: '1234567890',
  seedItemId: 'item-123',
  limit: 5,
});

response.results.forEach((result) => {
  console.log(result);
});
```

You can also seed the query using the item's URL instead of its ID:

```ts
const response = await searchService.search({
  searchIndexId: '1234567890',
  seedItemUrl: 'https://example.com/articles/cloud',
});
```

MLT responses use the same mapped `SearchResponse` shape as keyword searches:

```ts
{
  results: SearchDocument[];
  total: number;
  facets?: FacetResult[];
}
```

You can use `limit`, `offset`, `sort`, `locale`, and `facet` with an MLT query in the same way as with a keyword search.

## Search with typeahead suggestions

The `SearchService.suggest()` function retrieves query completions and document previews as a user types a search phrase. The method requires a search index ID and a non-empty `keyphrase`, and trims leading and trailing whitespace before sending the request.

```ts
const response = await searchService.suggest({
  searchIndexId: '1234567890',
  keyphrase: 'running sho',
});

response.querySuggestions.forEach((suggestion) => {
  console.log(suggestion.text);
  console.log(suggestion.queryPlusText);
});

response.previewResults.forEach((result) => {
  console.log(result);
});
```

You can provide `locale` when the search index supports multiple locales:

```ts
const response = await searchService.suggest({
  searchIndexId: '1234567890',
  keyphrase: 'chaussures de',
  locale: 'fr-FR',
});
```

The response contains query completions and document previews:

```ts
{
  querySuggestions: QuerySuggestionItem[];
  previewResults: SearchDocument[];
}
```

Each `QuerySuggestionItem` contains `text`, the completion text, and `queryPlusText`, the full query with the completion applied. Seed fields (`seedItemId`, `seedItemUrl`) are not supported by `suggest()`.

## Error handling

The `SearchService` throws specific errors that you should handle appropriately:

```csharp
try {
  const response = await searchService.search({
    searchIndexId: '1234567890',
    keyphrase: 'product',
    limit: 10,
  });
} catch (error) {
  if (error instanceof RangeError) {
    // Handle validation errors (limit, offset)
    console.error('Invalid parameter:', error.message);
  } else if (error instanceof TypeError) {
    // Handle type errors (missing searchIndexId, invalid sort,
    // or more than one of keyphrase/seedItemId/seedItemUrl provided)
    console.error('Type error:', error.message);
  } else if (error instanceof Error) {
    // Handle network/API errors
    console.error('Search failed:', error.message);
  }
}
```