Search assets
Searches for assets using rank fusion across dense visual retrieval and authoritative-metadata full-text retrieval, with typed structured filters on albums, people, and date range. Use this tool when the user describes what's in the photos they want — subjects, scenes, places, activities, moods, objects — optionally narrowed by album, person, date, or location.
Prefer typed filters for anything the request states exactly: album_id for album membership, person_ids for people, local_datetime_before/local_datetime_after for date ranges, and center + radius or bbox for location. There is no typed camera or place-name filter — pass those terms in the free-text query; the metadata full-text stage can match those terms, while dense retrieval adds visual-semantic matches. For example, 'photos of my kids at the beach last summer' becomes query='kids at the beach' + local_datetime_after=2025-06-01 + local_datetime_before=2025-09-01.
Use list_assets instead for a plain structured browse that album, person, date-range, location, or asset-ID filters can answer with no content query — it's cheaper and more deterministic than semantic search.
Location filtering is by coordinate, in two mutually-exclusive modes: a radius (center + radius) or a bounding box (bbox).
At least one of query, album_id, person_ids, local_datetime_before, or local_datetime_after must be provided; a location filter only narrows those results and is not a search criterion on its own.
Query parameters
Library to search. Optional if the user has a single library; required when they have multiple.
Library to search. Optional if the user has a single library; required when they have multiple.
Natural-language search text. It runs independently through dense visual retrieval and authoritative-metadata full-text retrieval, then the ranked lists are fused. Concrete visual concepts work well in the dense stage, while exact metadata terms can match through full-text search.
Resolve album and people names to IDs and pass them as album_id and person_ids; convert date phrases like 'in 2023' into ISO 8601 bounds on local_datetime_after/local_datetime_before (here, 2023-01-01 and 2024-01-01). None of those belong in query.
Natural-language search text. It runs independently through dense visual retrieval and authoritative-metadata full-text retrieval, then the ranked lists are fused. Concrete visual concepts work well in the dense stage, while exact metadata terms can match through full-text search.
Resolve album and people names to IDs and pass them as album_id and person_ids; convert date phrases like 'in 2023' into ISO 8601 bounds on local_datetime_after/local_datetime_before (here, 2023-01-01 and 2024-01-01). None of those belong in query.
Filter to assets containing ALL of these person IDs (intersection, not union). Accepts multiple person_ids= query params or a single comma-delimited value (e.g., person_123,person_abc). Person IDs are carried by the entries of an asset's people field (returned with include=people).
Filter to assets containing ALL of these person IDs (intersection, not union). Accepts multiple person_ids= query params or a single comma-delimited value (e.g., person_123,person_abc). Person IDs are carried by the entries of an asset's people field (returned with include=people).
Return only assets in this album — the album's album_ ID, not its name.
Return only assets in this album — the album's album_ ID, not its name.
Only include assets captured strictly after this instant (ISO 8601; exclusive). Convert a relative or natural-language date phrase ('in 2023') into an explicit bound before sending. local_datetime is the photo's wall-clock time in the device's own timezone. Naive values compare directly against local_datetime. Timezone-aware values: assets with a known offset are compared in UTC (local_datetime - offset); assets without an offset fall back to wall-clock comparison against local_datetime.
Only include assets captured strictly after this instant (ISO 8601; exclusive). Convert a relative or natural-language date phrase ('in 2023') into an explicit bound before sending. local_datetime is the photo's wall-clock time in the device's own timezone. Naive values compare directly against local_datetime. Timezone-aware values: assets with a known offset are compared in UTC (local_datetime - offset); assets without an offset fall back to wall-clock comparison against local_datetime.
Only include assets captured strictly before this instant (ISO 8601; exclusive). Same conversion requirement and awareness/offset semantics as local_datetime_after.
Only include assets captured strictly before this instant (ISO 8601; exclusive). Same conversion requirement and awareness/offset semantics as local_datetime_after.
Center point of a radius location filter: two comma-separated decimal-degree numbers longitude,latitude, e.g. -77.05,38.95. Supply with radius.
Center point of a radius location filter: two comma-separated decimal-degree numbers longitude,latitude, e.g. -77.05,38.95. Supply with radius.
Radius of the center location filter, in meters (greater than 0, at most 50,000).
Radius of the center location filter, in meters (greater than 0, at most 50,000).
Bounding-box (map viewport) location filter: 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 crosses the antimeridian: it selects the band running east from min_longitude over ±180° to max_longitude, so there is no need to split it client-side. Longitude order is therefore significant — transposed corners read as a crossing viewport, not as an error. A viewport 360° or wider must be sent as the full range -180,...,180,..., which the wrapped form cannot express.
Bounding-box (map viewport) location filter: 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 crosses the antimeridian: it selects the band running east from min_longitude over ±180° to max_longitude, so there is no need to split it client-side. Longitude order is therefore significant — transposed corners read as a crossing viewport, not as an error. A viewport 360° or wider must be sent as the full range -180,...,180,..., which the wrapped form cannot express.
1-indexed page number; increment it to fetch subsequent pages. search_assets pages by number rather than by cursor because it ranks a fixed top-200 fused candidate population by relevance, so pages beyond that population are empty. The sibling list_assets cursors with starting_after_id over a stable capture-time ordering.
1-indexed page number; increment it to fetch subsequent pages. search_assets pages by number rather than by cursor because it ranks a fixed top-200 fused candidate population by relevance, so pages beyond that population are empty. The sibling list_assets cursors with starting_after_id over a stable capture-time ordering.
Maximum number of results per page (1–200). Defaults to 20.
Maximum number of results per page (1–200). Defaults to 20.
Deprecated compatibility parameter. Accepted and validated during the transition window but ignored because rank-fused results do not have one meaningful cosine-distance cutoff.
Deprecated compatibility parameter. Accepted and validated during the transition window but ignored because rank-fused results do not have one meaningful cosine-distance cutoff.
Opt-in expansion fields. Supported values: metadata (camera/EXIF/GPS and location names), faces, people, metrics (ML quality scores), file_data (a group token populating the nested file_data object with the file/provenance scalars device_asset_id, device_id, file_created_at, file_modified_at, checksum, checksum_sha1, file_size_bytes), and variants (the non-thumbnail asset_urls size variants; without it asset_urls carries only its lean rung — thumbnail, or thumbnail_image for a video with an extracted still, or original for a still-less video — so callers that render non-thumbnail variants must pass it). Accepts multiple include= query params or a single comma-delimited value (e.g. include=faces,people). Unknown values return 422. When omitted, only the lean core is returned (id, mime_type, local_datetime, dimensions, description, thumbhash, asset_urls) and each data field above is null/absent until you request it.
Opt-in expansion fields. Supported values: metadata (camera/EXIF/GPS and location names), faces, people, metrics (ML quality scores), file_data (a group token populating the nested file_data object with the file/provenance scalars device_asset_id, device_id, file_created_at, file_modified_at, checksum, checksum_sha1, file_size_bytes), and variants (the non-thumbnail asset_urls size variants; without it asset_urls carries only its lean rung — thumbnail, or thumbnail_image for a video with an extracted still, or original for a still-less video — so callers that render non-thumbnail variants must pass it). Accepts multiple include= query params or a single comma-delimited value (e.g. include=faces,people). Unknown values return 422. When omitted, only the lean core is returned (id, mime_type, local_datetime, dimensions, description, thumbhash, asset_urls) and each data field above is null/absent until you request it.
Response
Successful Response