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

# Cluster assets by map location

> Clusters geotagged assets in a map viewport (bounding box) onto a grid of square cells and returns one entry per non-empty cell — its centroid, asset count, and a representative cover asset. Use this to render a clustered map or to count how many photos fall in each part of a viewport at a chosen zoom granularity.

The result is a single un-paginated list capped at 1000 cells; a viewport that is too dense at the given `cell_size` returns 422 (coarsen `cell_size` or zoom in). A viewport whose `min_longitude` exceeds `max_longitude` (crossing the antimeridian) returns no cells — split it into two requests client-side. To list the individual assets behind a cell, call `list_assets` with a tighter bounding box over the same filters.



## OpenAPI

````yaml https://api.gumnut.ai/openapi.json get /api/assets/geo-clusters
openapi: 3.1.0
info:
  title: Gumnut API
  description: API for using Gumnut to manage photos and videos
  version: 0.1.0
servers: []
security: []
paths:
  /api/assets/geo-clusters:
    get:
      tags:
        - assets
      summary: Cluster assets by map location
      description: >-
        Clusters geotagged assets in a map viewport (bounding box) onto a grid
        of square cells and returns one entry per non-empty cell — its centroid,
        asset count, and a representative cover asset. Use this to render a
        clustered map or to count how many photos fall in each part of a
        viewport at a chosen zoom granularity.


        The result is a single un-paginated list capped at 1000 cells; a
        viewport that is too dense at the given `cell_size` returns 422 (coarsen
        `cell_size` or zoom in). A viewport whose `min_longitude` exceeds
        `max_longitude` (crossing the antimeridian) returns no cells — split it
        into two requests client-side. To list the individual assets behind a
        cell, call `list_assets` with a tighter bounding box over the same
        filters.
      operationId: get_geo_clusters
      parameters:
        - name: bbox
          in: query
          required: true
          schema:
            type: string
            description: >-
              Map viewport as four comma-separated decimal-degree numbers
              `min_longitude,min_latitude,max_longitude,max_latitude`
              (west,south,east,north), e.g. `-77.1,38.9,-77.0,39.0`. A box whose
              `min_longitude` exceeds `max_longitude` (antimeridian-crossing)
              returns no cells — split it client-side.
            title: Bbox
          description: >-
            Map viewport as four comma-separated decimal-degree numbers
            `min_longitude,min_latitude,max_longitude,max_latitude`
            (west,south,east,north), e.g. `-77.1,38.9,-77.0,39.0`. A box whose
            `min_longitude` exceeds `max_longitude` (antimeridian-crossing)
            returns no cells — split it client-side.
        - name: cell_size
          in: query
          required: true
          schema:
            type: number
            description: >-
              Grid cell edge in decimal degrees — the clustering granularity.
              Larger values give coarser clusters; the client maps map-zoom to
              `cell_size`. Must be at least 0.0001 (~11 m).
            title: Cell Size
          description: >-
            Grid cell edge in decimal degrees — the clustering granularity.
            Larger values give coarser clusters; the client maps map-zoom to
            `cell_size`. Must be at least 0.0001 (~11 m).
        - name: library_id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: >-
              Library to cluster assets from. Optional if the user has a single
              library; required when they have multiple.
            title: Library Id
          description: >-
            Library to cluster assets from. Optional if the user has a single
            library; required when they have multiple.
        - name: album_id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Return only assets that are in the album with this ID.
            title: Album Id
          description: Return only assets that are in the album with this ID.
        - name: person_id
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Return only assets containing a face belonging to this person.
            title: Person Id
          description: Return only assets containing a face belonging to this person.
        - name: local_datetime_after
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: 'null'
            description: >-
              Only include assets captured strictly after this instant (ISO
              8601; exclusive). Same awareness/offset semantics as on
              `list_assets`.
            title: Local Datetime After
          description: >-
            Only include assets captured strictly after this instant (ISO 8601;
            exclusive). Same awareness/offset semantics as on `list_assets`.
        - name: local_datetime_before
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                format: date-time
              - type: 'null'
            description: >-
              Only include assets captured strictly before this instant (ISO
              8601; exclusive). Same awareness/offset semantics as on
              `list_assets`.
            title: Local Datetime Before
          description: >-
            Only include assets captured strictly before this instant (ISO 8601;
            exclusive). Same awareness/offset semantics as on `list_assets`.
        - name: state
          in: query
          required: false
          schema:
            enum:
              - live
              - trashed
              - all
            type: string
            description: >-
              Which set of assets to cluster: `live` (default — excludes trashed
              assets), `trashed` (only trashed assets), or `all` (both).
            default: live
            title: State
          description: >-
            Which set of assets to cluster: `live` (default — excludes trashed
            assets), `trashed` (only trashed assets), or `all` (both).
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeoClustersResponse'
        '404':
          description: Not found
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
components:
  schemas:
    GeoClustersResponse:
      properties:
        data:
          items:
            $ref: '#/components/schemas/GeoCluster'
          type: array
          title: Data
          description: >-
            Non-empty grid cells within the requested viewport. Not paginated:
            the list is capped at 1000 cells and a denser viewport returns 422
            instead — coarsen `cell_size` or zoom in.
      type: object
      required:
        - data
      title: GeoClustersResponse
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    GeoCluster:
      properties:
        latitude:
          type: number
          title: Latitude
          description: >-
            Cluster centroid latitude in decimal degrees — the average latitude
            of the cell's members.
        longitude:
          type: number
          title: Longitude
          description: >-
            Cluster centroid longitude in decimal degrees — the average
            longitude of the cell's members.
        count:
          type: integer
          title: Count
          description: Number of assets in this grid cell.
        representative_asset_id:
          type: string
          title: Representative Asset Id
          description: >-
            ID of a cover asset for the cell — the most recently captured
            geotagged asset in it (ties broken by descending id).
      type: object
      required:
        - latitude
        - longitude
        - count
        - representative_asset_id
      title: GeoCluster
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError

````