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

# Pagination & Filtering

> Paginate, filter, and sort results from the Gumnut API

Most list endpoints in the Gumnut API support pagination, filtering, and sorting to help you efficiently retrieve the data you need.

## Pagination

List endpoints support cursor-based pagination using `limit` and `starting_after_id`:

```http theme={null}
# Get first 50 assets
GET /api/assets?limit=50

# Get next page, starting after the last asset ID from the previous response
GET /api/assets?limit=50&starting_after_id=asset_abc123
```

Paginated responses include a `has_more` field indicating whether additional results exist:

```json theme={null}
{
  "data": [
    { "id": "asset_abc123", "type": "IMAGE", ... },
    { "id": "asset_def456", "type": "IMAGE", ... }
  ],
  "has_more": true
}
```

To fetch the next page, pass the `id` of the last item as `starting_after_id`.

<Note>
  If you're using one of our [SDKs](../sdks/overview), pagination is handled automatically with built-in iterators.
</Note>

## Filtering

Use query parameters to filter results:

```http theme={null}
# Filter by date range
GET /api/assets?local_datetime_after=2024-01-01T00:00:00&local_datetime_before=2024-02-01T00:00:00

# Filter by library
GET /api/assets?library_id=lib_123

# Filter by album or person
GET /api/assets?album_id=album_456
GET /api/assets?person_ids=person_789
```

### Filtering by capture time

`local_datetime_after` and `local_datetime_before` filter on the asset's capture time:

* Send offsetless values such as `2024-01-01T00:00:00` when you want wall-clock filtering.
* Send offset-aware values such as `2024-01-01T00:00:00-05:00` when you want an absolute time window.
* Keep both bounds consistent. Mixing an offsetless value with an offset-aware value in the same request is rejected.
* Assets with a known capture offset are compared using that offset. Assets without one fall back to wall-clock comparison, so offsetless captures still participate in aware range filters.

```http theme={null}
# Filter by an absolute window in US Eastern time
GET /api/assets?local_datetime_after=2024-01-01T00:00:00-05:00&local_datetime_before=2024-02-01T00:00:00-05:00
```

### Filtering semantic search

Use `GET /api/search` when you want natural-language or metadata search. The endpoint accepts the same canonical date and album filters as asset lists:

```http theme={null}
# Find beach photos in one album during a date range
GET /api/search?query=beach&album_id=album_456&local_datetime_after=2024-06-01T00:00:00&local_datetime_before=2024-09-01T00:00:00
```

Use an album ID, not an album name, for `album_id`. You can also pass `person_ids` for one or more people. Include at least one search criterion such as `query`, `album_id`, `person_ids`, or a date bound; a location filter only narrows those results. The same filters are available on `POST /api/search` when you submit a multipart request for image-aware search.

Use the canonical parameter names shown above. The legacy search spellings `captured_after`, `captured_before`, and `album_ids` are no longer supported; replace them with `local_datetime_after`, `local_datetime_before`, and `album_id`.

### Filtering by location

`GET /api/assets` supports two location filter shapes:

* `center` + `radius` for a circular search area in meters
* `bbox` for a rectangular viewport in `min_longitude,min_latitude,max_longitude,max_latitude` order

```http theme={null}
# Assets within 1 km of a point
GET /api/assets?center=-77.05,38.95&radius=1000

# Assets inside a bounding box
GET /api/assets?bbox=-77.1,38.9,-77.0,39.0
```

Use `center` and `radius` together. Don't combine them with `bbox`.

A viewport that crosses the antimeridian is a single box whose west longitude is greater than its east longitude. It selects the band running east from `min_longitude` over ±180° to `max_longitude`, so you don't split it into two requests.

Because longitude order carries that meaning, it's significant: a box with west and east transposed reads as a crossing viewport rather than an error. A viewport 360° or wider must be sent as the full range `-180,...,180,...`, which the wrapped form can't express.

For semantic search, `GET /api/search` supports both `center` + `radius` and `bbox` as mutually exclusive location filters. A location filter only narrows a search; include at least one search criterion such as `query`, `album_id`, `person_ids`, or a date bound.

See [Requests & Responses](./requests-and-responses#asset-timestamp-fields) for how `local_datetime` is serialized, and see the **API Reference** tab for the full list of available filter parameters for each endpoint.

## Map views with geo clusters

When you need a map-friendly summary of geotagged assets inside a viewport, use `GET /api/assets/geo-clusters` instead of paging through `GET /api/assets` and grouping results client-side.

The endpoint takes a `bbox` string in `min_longitude,min_latitude,max_longitude,max_latitude` order plus a `cell_size` in decimal degrees.

```http theme={null}
GET /api/assets/geo-clusters?bbox=-77.1,38.9,-77.0,39.0&cell_size=0.01
```

It also supports the same top-level filters you already use on asset lists: `library_id`, `album_id`, `person_ids`, `local_datetime_after`, `local_datetime_before`, and `state`.

Each item in `data` represents one non-empty grid cell and includes a centroid (`latitude`, `longitude`), the number of matching assets (`count`), and a `representative_asset_id` you can use as a cover image or lookup key.

<Note>
  `GET /api/assets/geo-clusters` is not paginated. The response is capped at 1000 non-empty cells, so a dense viewport returns `422` instead of partial results. If that happens, increase `cell_size` or zoom in and retry. A viewport crossing the antimeridian is clustered as one wrap-around band — send it as a single box whose west longitude is greater than its east longitude. Note that the 1000-cell cap then applies to that one response, so a viewport both very wide and very dense across ±180° may need a coarser `cell_size` than each half would have.
</Note>

See the **API Reference** tab for the full request and response schema.
