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

# Paginating Large Result Sets

> How to page through inventory and search results efficiently

Some endpoints return more data than fits in a single response. AutosnapAI uses **page-based pagination** for these — you pass `page` and `per_page` parameters and we return the requested slice plus metadata about the total result set.

## Endpoints that support pagination

| Endpoint                           | Default `per_page` | Pagination style    |
| ---------------------------------- | ------------------ | ------------------- |
| `POST /v1/inventory/fetch`         | 50                 | `page` + `per_page` |
| `GET /v1/ims/vehicles`             | 100 (max 500)      | `page` + `per_page` |
| `GET /v1/webhooks/{id}/deliveries` | 50 (max 100)       | `limit` query param |

<Note>
  `GET /v1/dealers` returns all dealerships under your account in a single response — it does not support pagination.
</Note>

## Request shape

```bash theme={null}
curl -X POST "https://api.autosnap.com/v1/inventory/fetch" \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "'$AUTOSNAP_API_KEY'",
    "dealership_url": "carlblackroswell.com",
    "page": 1,
    "per_page": 50
  }'
```

## Response shape

Paginated responses always include this metadata:

```json theme={null}
{
  "vehicles": [
    /* up to per_page items */
  ],
  "count": 863,
  "page": 1,
  "per_page": 50,
  "total_pages": 18
}
```

| Field         | Description                                                     |
| ------------- | --------------------------------------------------------------- |
| `count`       | Total number of items in the full result set (across all pages) |
| `page`        | The page you requested (1-indexed)                              |
| `per_page`    | How many items per page                                         |
| `total_pages` | Total number of pages available                                 |

The actual items live under a key named after the resource (`vehicles`, `deliveries`, etc).

## Walking all pages

```python theme={null}
import requests

def fetch_all_inventory(dealership_url: str, api_key: str):
    all_vehicles = []
    page = 1
    while True:
        r = requests.post(
            "https://api.autosnap.com/v1/inventory/fetch",
            json={
                "api_key": api_key,
                "dealership_url": dealership_url,
                "page": page,
                "per_page": 200,  # larger pages = fewer requests
            },
        )
        r.raise_for_status()
        data = r.json()
        all_vehicles.extend(data["vehicles"])

        if page >= data["total_pages"]:
            break
        page += 1

    return all_vehicles
```

## Best practices

<Steps>
  <Step title="Use larger per_page values">
    Bigger pages = fewer round trips. The default of 50 is conservative; if you're walking all pages, use a larger value like 200.
  </Step>

  <Step title="Don't store page numbers long-term">
    Page numbers are not stable across mutations. If new vehicles are added between page 1 and page 5, page 5 in your second walk may contain different items than the first. For reliable bulk syncs, use **webhooks** instead.
  </Step>

  <Step title="Cache page count, not pages">
    `total_pages` is fine to display in a UI, but don't cache the actual page contents — they go stale fast.
  </Step>

  <Step title="Combine with filters">
    Pagination is for navigating result sets. **Filters** (e.g. `condition`) reduce the result set. Filter first, paginate second.
  </Step>
</Steps>

## When to use webhooks instead

Walking pages to "sync" inventory is fragile and inefficient. For ongoing inventory sync:

1. Do **one full walk** when you first onboard the dealership
2. From then on, subscribe to `vehicle.created`, `vehicle.updated`, `vehicle.removed` [webhooks](/concepts/webhooks)
3. Apply each event to your local database

This is dramatically more efficient than polling and gives you near-real-time updates.

## Edge cases

| Situation              | Behavior                                                       |
| ---------------------- | -------------------------------------------------------------- |
| `page` > `total_pages` | Empty array returned, `count` and `total_pages` still accurate |
| `page` = 0 or missing  | Treated as page 1                                              |
| Result set is empty    | `count: 0`, `total_pages: 1`, items array empty                |

## Cursor pagination

Some high-volume endpoints will move to **cursor-based pagination** in the future, which is more reliable for large or actively-changing result sets. When that happens, the existing `page`/`per_page` will continue to work for backwards compatibility.

## Related

<CardGroup cols={2}>
  <Card title="Webhooks" icon="webhook" href="/concepts/webhooks">
    Real-time alternative to polling
  </Card>

  <Card title="Inventory fetch endpoint" icon="code" href="/api-reference/endpoints/fetch-inventory">
    Full reference for the inventory fetch endpoint
  </Card>
</CardGroup>
