> For the complete documentation index, see [llms.txt](https://docs.snackprompt.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.snackprompt.com/bring-your-data-into-ai/how-to/how-to-paginate-results.md).

# How to Paginate Results

Learn how to fetch large volumes of data efficiently.

### Problem

You need to fetch many results but don't want to overload the API or your application.

### Solution

Use the `limit` parameter to control the number of results per request.

### Basic Usage of Limit

```bash
curl -X POST https://api-integrations.snackprompt.com/v1/kb/search \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "query": "products",
    "filters": {
      "tenant_id": "your-tenant-id"
    },
    "limit": 10
  }'
```

### Recommended Values

| Use Case     | Limit  | Reason                           |
| ------------ | ------ | -------------------------------- |
| Chat/RAG     | 3-5    | Focused context, better response |
| Results list | 10-20  | Good UX/performance balance      |
| Export       | 50-100 | Higher volume per request        |

### Pagination Strategies

#### 1. Pagination by Relevance (recommended)

Since semantic search orders by relevance, use `limit` to get the top N most relevant:

```javascript
// First page - 10 most relevant
const page1 = await search(query, { limit: 10 });

// If you need more, increase the limit
const moreResults = await search(query, { limit: 20 });
```

#### 2. Filters to Segment

Use filters to "paginate" by categories:

```javascript
// Search in each category separately
const categories = ['Marketing', 'Sales', 'HR'];

for (const category of categories) {
  const results = await search(query, {
    filters: {
      tenant_id: tenantId,
      tag_names: [category]
    },
    limit: 10
  });

  processResults(category, results);
}
```

#### 3. Incremental Search

For "load more" interfaces:

```javascript
let currentLimit = 10;

async function loadMore() {
  currentLimit += 10;
  const results = await search(query, { limit: currentLimit });
  displayResults(results.items);
}
```

### Complete Example: List with "See More"

```javascript
class PaginatedSearch {
  constructor(tenantId, apiKey) {
    this.tenantId = tenantId;
    this.apiKey = apiKey;
    this.currentQuery = '';
    this.currentLimit = 10;
    this.totalFound = 0;
  }

  async search(query) {
    this.currentQuery = query;
    this.currentLimit = 10;

    const response = await fetch('/v1/kb/search', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': this.apiKey
      },
      body: JSON.stringify({
        query,
        filters: { tenant_id: this.tenantId },
        limit: this.currentLimit
      })
    });

    const data = await response.json();
    this.totalFound = data.total_found;

    return {
      items: data.items,
      hasMore: data.items.length < this.totalFound
    };
  }

  async loadMore() {
    this.currentLimit += 10;

    const response = await fetch('/v1/kb/search', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': this.apiKey
      },
      body: JSON.stringify({
        query: this.currentQuery,
        filters: { tenant_id: this.tenantId },
        limit: this.currentLimit
      })
    });

    const data = await response.json();

    return {
      items: data.items,
      hasMore: data.items.length < this.totalFound
    };
  }
}

// Usage
const paginator = new PaginatedSearch('tenant-123', 'YOUR_API_KEY');

// Initial search
const { items, hasMore } = await paginator.search('products');
displayResults(items);

if (hasMore) {
  showLoadMoreButton();
}

// On "See More" click
loadMoreButton.onclick = async () => {
  const { items, hasMore } = await paginator.loadMore();
  displayResults(items);

  if (!hasMore) {
    hideLoadMoreButton();
  }
};
```

### Python Example

```python
class PaginatedSearch:
    def __init__(self, tenant_id: str, api_key: str):
        self.tenant_id = tenant_id
        self.api_key = api_key
        self.current_query = ''
        self.current_limit = 10
        self.total_found = 0

    def search(self, query: str):
        self.current_query = query
        self.current_limit = 10

        response = requests.post(
            'https://api-integrations.snackprompt.com/v1/kb/search',
            headers={'x-api-key': self.api_key},
            json={
                'query': query,
                'filters': {'tenant_id': self.tenant_id},
                'limit': self.current_limit
            }
        )

        data = response.json()
        self.total_found = data['total_found']

        return data['items'], len(data['items']) < self.total_found

    def load_more(self):
        self.current_limit += 10

        response = requests.post(
            'https://api-integrations.snackprompt.com/v1/kb/search',
            headers={'x-api-key': self.api_key},
            json={
                'query': self.current_query,
                'filters': {'tenant_id': self.tenant_id},
                'limit': self.current_limit
            }
        )

        data = response.json()
        return data['items'], len(data['items']) < self.total_found


# Usage
paginator = PaginatedSearch('tenant-123', 'YOUR_API_KEY')

items, has_more = paginator.search('products')
print(f"Found {len(items)} items")

while has_more:
    input("Press Enter to load more...")
    items, has_more = paginator.load_more()
    print(f"Now showing {len(items)} items")
```

### Performance Considerations

#### 1. Maximum Recommended Limit

```diff
- limit: 1000  // Too heavy
+ limit: 100   // Maximum recommended
```

#### 2. Cache Results

```javascript
const cache = new Map();

async function cachedSearch(query, filters, limit) {
  const cacheKey = JSON.stringify({ query, filters, limit });

  if (cache.has(cacheKey)) {
    return cache.get(cacheKey);
  }

  const result = await search(query, filters, limit);
  cache.set(cacheKey, result);

  // Clear cache after 5 minutes
  setTimeout(() => cache.delete(cacheKey), 5 * 60 * 1000);

  return result;
}
```

#### 3. Debounce for Incremental Searches

```javascript
function debounce(fn, delay) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

const debouncedSearch = debounce(search, 300);
```

### Related

* [Semantic Search](/bring-your-data-into-ai/get-started/semantic-search.md)
* [Filter Reference](/bring-your-data-into-ai/reference/filters.md)
* [Endpoints](/bring-your-data-into-ai/reference/endpoints.md)
