# 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.snackprompt.com/bring-your-data-into-ai/how-to/how-to-paginate-results.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
