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

# Pagination

> Learn how to navigate through large datasets using pagination

## Overview

The Zochil API uses cursor-based pagination for efficient navigation through large datasets. This approach provides consistent performance regardless of dataset size and handles real-time data changes gracefully.

## Pagination Parameters

Most list endpoints accept the following pagination parameters:

<ParamField query="limit" type="integer" default="20">
  Number of items to return (1-100)
</ParamField>

<ParamField query="offset" type="integer" default="0">
  Number of items to skip (cursor-based)
</ParamField>

<ParamField query="cursor" type="string">
  Cursor for the next page (when available)
</ParamField>

## Response Format

Paginated responses include metadata to help you navigate:

```json theme={null}
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "name": "Example Item",
        "created_at": "2023-01-01T00:00:00Z"
      }
    ],
    "pagination": {
      "limit": 20,
      "offset": 0,
      "total": 150,
      "has_more": true,
      "next_cursor": "eyJpZCI6IjEyM2U0NTY3LWU4OWItMTJkMy1hNDU2LTQyNjYxNDE3NDAwMCIsImNyZWF0ZWRfYXQiOiIyMDIzLTAxLTAxVDAwOjAwOjAwWiJ9"
    }
  }
}
```

## Basic Pagination

### First Page Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zochil.io/catalog/products?limit=20" \
    -H "access-token: your_access_token" \
    -H "device-id: your_device_id"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    "https://api.zochil.io/catalog/products?limit=20",
    {
      headers: {
        "access-token": "your_access_token",
        "device-id": "your_device_id"
      }
    }
  );

  const data = await response.json();
  console.log(`Found ${data.data.pagination.total} total products`);
  console.log(`Page 1: ${data.data.items.length} items`);
  ```
</CodeGroup>

### Next Page Request

Using offset-based pagination:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zochil.io/catalog/products?limit=20&offset=20" \
    -H "access-token: your_access_token" \
    -H "device-id: your_device_id"
  ```

  ```javascript JavaScript theme={null}
  // Using offset
  const nextPage = await fetch(
    "https://api.zochil.io/catalog/products?limit=20&offset=20",
    {
      headers: {
        "access-token": "your_access_token",
        "device-id": "your_device_id"
      }
    }
  );

  // Or using cursor (when available)
  const nextPageCursor = await fetch(
    `https://api.zochil.io/catalog/products?cursor=${encodeURIComponent(cursor)}`,
    {
      headers: {
        "access-token": "your_access_token",
        "device-id": "your_device_id"
      }
    }
  );
  ```
</CodeGroup>

## Advanced Pagination Patterns

### Iterating Through All Pages

```javascript theme={null}
async function fetchAllProducts() {
  const allProducts = [];
  let offset = 0;
  const limit = 50; // Larger page size for efficiency
  let hasMore = true;

  while (hasMore) {
    const response = await fetch(
      `https://api.zochil.io/catalog/products?limit=${limit}&offset=${offset}`,
      {
        headers: {
          "access-token": "your_access_token",
          "device-id": "your_device_id"
        }
      }
    );

    const data = await response.json();

    if (!data.success) {
      throw new Error(`API Error: ${data.error.message}`);
    }

    allProducts.push(...data.data.items);
    hasMore = data.data.pagination.has_more;
    offset += limit;

    // Optional: Add delay to avoid rate limiting
    await new Promise((resolve) => setTimeout(resolve, 100));
  }

  return allProducts;
}
```

### Cursor-Based Pagination (Recommended)

For real-time data and better performance:

```javascript theme={null}
async function fetchProductsWithCursor(cursor = null) {
  const url = cursor
    ? `https://api.zochil.io/catalog/products?cursor=${encodeURIComponent(
        cursor
      )}`
    : "https://api.zochil.io/catalog/products?limit=20";

  const response = await fetch(url, {
    headers: {
      "access-token": "your_access_token",
      "device-id": "your_device_id"
    }
  });

  const data = await response.json();
  return {
    items: data.data.items,
    nextCursor: data.data.pagination.next_cursor,
    hasMore: data.data.pagination.has_more
  };
}

// Usage
let cursor = null;
do {
  const page = await fetchProductsWithCursor(cursor);
  console.log(`Fetched ${page.items.length} products`);

  // Process items
  page.items.forEach((product) => {
    console.log(product.name);
  });

  cursor = page.nextCursor;
} while (cursor);
```

## Pagination with Filtering and Sorting

Combine pagination with filters and sorting:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.zochil.io/catalog/products?limit=20&offset=0&category=electronics&sort=price&order=asc" \
    -H "access-token: your_access_token" \
    -H "device-id: your_device_id"
  ```

  ```javascript JavaScript theme={null}
  const params = new URLSearchParams({
    limit: "20",
    offset: "0",
    category: "electronics",
    sort: "price",
    order: "asc"
  });

  const response = await fetch(
    `https://api.zochil.io/catalog/products?${params}`,
    {
      headers: {
        "access-token": "your_access_token",
        "device-id": "your_device_id"
      }
    }
  );
  ```
</CodeGroup>

## React Hook Example

Here's a custom hook for handling pagination in React:

```javascript theme={null}
import { useState, useEffect } from "react";

function usePagination(endpoint, options = {}) {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [pagination, setPagination] = useState({
    offset: 0,
    limit: 20,
    total: 0,
    hasMore: false
  });

  const fetchData = async (reset = false) => {
    setLoading(true);
    setError(null);

    try {
      const offset = reset ? 0 : pagination.offset;
      const params = new URLSearchParams({
        limit: pagination.limit.toString(),
        offset: offset.toString(),
        ...options.filters
      });

      const response = await fetch(`${endpoint}?${params}`, {
        headers: {
          "access-token": options.accessToken,
          "device-id": options.deviceId
        }
      });

      const result = await response.json();

      if (!result.success) {
        throw new Error(result.error.message);
      }

      if (reset) {
        setData(result.data.items);
      } else {
        setData((prev) => [...prev, ...result.data.items]);
      }

      setPagination({
        offset: offset + result.data.items.length,
        limit: pagination.limit,
        total: result.data.pagination.total,
        hasMore: result.data.pagination.has_more
      });
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const loadMore = () => {
    if (!loading && pagination.hasMore) {
      fetchData(false);
    }
  };

  const refresh = () => {
    fetchData(true);
  };

  useEffect(() => {
    fetchData(true);
  }, [endpoint, JSON.stringify(options.filters)]);

  return {
    data,
    loading,
    error,
    pagination,
    loadMore,
    refresh
  };
}

// Usage
function ProductList() {
  const { data, loading, pagination, loadMore } = usePagination(
    "https://api.zochil.io/catalog/products",
    {
      accessToken: "your_token",
      deviceId: "your_device_id",
      filters: { category: "electronics" }
    }
  );

  return (
    <div>
      {data.map((product) => (
        <div key={product.id}>{product.name}</div>
      ))}

      {pagination.hasMore && (
        <button onClick={loadMore} disabled={loading}>
          {loading ? "Loading..." : "Load More"}
        </button>
      )}
    </div>
  );
}
```

## Performance Tips

<Tip>
  **Optimal Page Sizes** - Use 20-50 items per page for most use cases - Use
  smaller pages (10-20) for complex items with large payloads - Use larger pages
  (50-100) for simple list items
</Tip>

<Tip>
  **Cursor vs Offset** - Prefer cursor-based pagination for real-time data - Use
  offset-based pagination when users need random page access - Cursor pagination
  performs better with large datasets
</Tip>

<Warning>
  **Avoid Deep Pagination** Very high offset values (>10,000) may have
  performance impacts. Consider using search filters or cursor-based pagination
  instead.
</Warning>

## Common Patterns by Endpoint

| Endpoint              | Pagination Style | Max Limit | Default Limit |
| --------------------- | ---------------- | --------- | ------------- |
| `/catalog/products`   | Cursor + Offset  | 100       | 20            |
| `/user/orders`        | Cursor           | 50        | 10            |
| `/admin/users`        | Offset           | 100       | 25            |
| `/marketplace/search` | Offset           | 50        | 20            |

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/api-reference">
    Explore all paginated endpoints
  </Card>

  <Card title="Webhooks" icon="webhook" href="/essentials/webhooks">
    Real-time notifications and events
  </Card>
</CardGroup>
