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

# Pagination

> Working with paginated API responses

## Pagination Parameters

| Parameter   | Type    | Default | Max | Description              |
| ----------- | ------- | ------- | --- | ------------------------ |
| `page`      | integer | 1       | -   | Page number (1-indexed)  |
| `page_size` | integer | 20      | 100 | Number of items per page |

## Request Example

```bash theme={null}
GET /v1/platform/businesses/{business_id}/invoices/?page=1&page_size=50
```

## Response Format

All paginated responses follow this structure:

```json theme={null}
{
  "count": 250,
  "next": "https://sandbox.thredfi.com/v1/platform/businesses/{id}/invoices/?page=2",
  "previous": null,
  "results": [
    {
      "id": "invoice-uuid-1",
      ...
    },
    {
      "id": "invoice-uuid-2",
      ...
    }
  ]
}
```

### Response Fields

| Field      | Type         | Description                                  |
| ---------- | ------------ | -------------------------------------------- |
| `count`    | integer      | Total number of items across all pages       |
| `next`     | string\|null | URL for next page, or null if last page      |
| `previous` | string\|null | URL for previous page, or null if first page |
| `results`  | array        | Array of items for current page              |

## Fetching All Pages

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    def get_all_invoices(business_id, token):
        """Fetch all invoices across all pages."""
        all_invoices = []
        url = f"https://sandbox.thredfi.com/v1/platform/businesses/{business_id}/invoices/"

        while url:
            response = requests.get(
                url,
                headers={"Authorization": f"Bearer {token}"},
                params={"page_size": 100}  # Use max page size
            )

            data = response.json()
            all_invoices.extend(data['results'])

            # Move to next page
            url = data['next']

        return all_invoices

    # Usage
    invoices = get_all_invoices(business_id, business_token)
    print(f"Total invoices: {len(invoices)}")
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    async function getAllInvoices(businessId, token) {
      const allInvoices = [];
      let url = `https://sandbox.thredfi.com/v1/platform/businesses/${businessId}/invoices/?page_size=100`;

      while (url) {
        const response = await fetch(url, {
          headers: {
            'Authorization': `Bearer ${token}`
          }
        });

        const data = await response.json();
        allInvoices.push(...data.results);

        // Move to next page
        url = data.next;
      }

      return allInvoices;
    }

    // Usage
    const invoices = await getAllInvoices(businessId, businessToken);
    console.log(`Total invoices: ${invoices.length}`);
    ```
  </Tab>

  <Tab title="Manual Iteration">
    ```python theme={null}
    page = 1
    all_items = []

    while True:
        response = requests.get(
            url,
            headers={"Authorization": f"Bearer {token}"},
            params={"page": page, "page_size": 50}
        )

        data = response.json()
        all_items.extend(data['results'])

        # Check if there are more pages
        if not data['next']:
            break

        page += 1

    print(f"Fetched {len(all_items)} items across {page} pages")
    ```
  </Tab>
</Tabs>

## Performance Optimization

### Use Maximum Page Size

Always use the maximum `page_size` (100) to minimize API calls:

```python theme={null}
params = {"page_size": 100}  # Fetch 100 items per request
```

### Implement Cursor-Based Pagination (Future)

<Info>
  Cursor-based pagination is planned for future releases to improve performance on large datasets.
</Info>

## Filtering + Pagination

Combine filters with pagination for efficient data retrieval:

```bash theme={null}
GET /v1/platform/businesses/{id}/invoices/
  ?status=unpaid
  &page=1
  &page_size=50
  &sort=-sent_at
```

```python theme={null}
response = requests.get(
    f"{base_url}/v1/platform/businesses/{business_id}/invoices/",
    headers={"Authorization": f"Bearer {token}"},
    params={
        "status": "unpaid",
        "page": 1,
        "page_size": 50,
        "sort": "-sent_at"  # Descending by sent_at
    }
)
```

## Paginated Endpoints

The following endpoints support pagination:

* `/v1/platform/businesses/` - List businesses
* `/v1/platform/businesses/{id}/invoices/` - List invoices
* `/v1/platform/businesses/{id}/invoices/payments/` - List invoice payments
* `/v1/platform/businesses/{id}/bills/` - List bills
* `/v1/platform/businesses/{id}/bills/payments/` - List bill payments
* `/v1/platform/businesses/{id}/customers/` - List customers
* `/v1/platform/businesses/{id}/vendors/` - List vendors
* `/v1/platform/businesses/{id}/general-ledger/chart-of-accounts/` - List accounts
* `/v1/platform/businesses/{id}/general-ledger/journal-entries/` - List journal entries

See the [API Reference](/api-reference) for complete list.

## Best Practices

<CardGroup cols={2}>
  <Card title="Use maximum page size" icon="gauge-high">
    Set `page_size=100` to minimize API calls and improve performance.
  </Card>

  <Card title="Cache results" icon="database">
    Cache paginated results when appropriate to reduce redundant API calls.
  </Card>

  <Card title="Monitor count field" icon="chart-line">
    Use the `count` field to show progress when fetching all pages.
  </Card>

  <Card title="Handle empty results" icon="inbox">
    Always check if `results` array is empty before processing.
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling" icon="triangle-exclamation" href="/implementation/error-handling">
    Handle errors during pagination
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference">
    See which endpoints support pagination
  </Card>
</CardGroup>
