Searching

POST /api/v1/search searches the key owner's team library. It requires the search scope and accepts a JSON object; every field is optional.

Request

FieldTypeDefaultDescription
qstringnoneNon-empty free-text query. Without one, files are newest-first.
modestringhybridhybrid, text, or vector; used when q is present.
filtersobject{}Structured filters described below.
limitnumber50Integer from 1 through 100.
cursorstringnoneOpaque cursor returned by the previous page.

hybrid combines BM25 full-text relevance with semantic similarity. text uses BM25 only, and vector uses semantic similarity only.

json
{
  "q": "sunset at the beach",
  "mode": "hybrid",
  "filters": {
    "media_type": { "image": "include" },
    "rating": { "3:4": "include", "3:5": "include" }
  },
  "limit": 25
}
bash
curl --fail-with-body \
  -X POST "$NEW_ARCHIVE_URL/api/v1/search" \
  -H "Authorization: Bearer $NEW_ARCHIVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "sunset at the beach",
    "mode": "hybrid",
    "filters": {"media_type": {"image": "include"}},
    "limit": 10
  }'

Response

json
{
  "items": [
    {
      "id": "0198c9a0-7d3e-7c41-b7a2-3f9d1c2e4a5b",
      "status": "ready",
      "original_name": "sunset.jpg",
      "mime_type": "image/jpeg",
      "size_bytes": 2481931,
      "width": 4000,
      "height": 3000,
      "taken_at": "2026-06-30T18:41:02.000Z",
      "created_at": "2026-07-11T09:12:44.201Z",
      "thumbnail_url": "https://storage.example/signed-thumbnail"
    }
  ],
  "next_cursor": "eyJvIjoyNX0"
}

Items use the same schema as GET /api/v1/files/:fileId. Ready files include a signed small-thumbnail URL. next_cursor is omitted when the result set is exhausted.

Pagination

Pass next_cursor back unchanged and keep the query, mode, filters, and limit the same. Cursors are opaque and must not be constructed or decoded by clients.

js
async function searchAll(request) {
  const items = []
  let cursor

  do {
    const response = await fetch(
      `${process.env.NEW_ARCHIVE_URL}/api/v1/search`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.NEW_ARCHIVE_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ ...request, cursor }),
      }
    )
    const page = await response.json()
    if (!response.ok)
      throw new Error(`${page.error.code}: ${page.error.message}`)
    items.push(...page.items)
    cursor = page.next_cursor
  } while (cursor)

  return items
}

Filter behavior

Most filter categories are tristate maps. Each value maps to include or exclude; a missing value is neutral. Includes within one category are ORed, active categories are ANDed, and exclusions always subtract.

json
{
  "filters": {
    "media_type": { "image": "include" },
    "date": { "2026-06": "include" },
    "camera_make": { "Canon": "exclude" }
  }
}

This selects images taken in June 2026 that were not made by a Canon camera.

Filter reference

CategoryAccepted keys
date, import_dateYYYY, YYYY-MM, or YYYY-MM-DD.
media_typeimage, video, other.
orientationlandscape, portrait, square.
format1:1, 4:3, 3:2, 16:9, other.
isolow, medium, high, or an exact integer such as 400.
focal_length, focal_length_35mmsuper-wide, wide-angle, normal, tele, super-tele, or exact integer millimetres.
aperturevery-wide, wide, medium, narrow, very-narrow, or an exact f-number such as 1.8.
shutter_speedvery-fast, fast, normal, slow, long, or exact seconds such as 0.002.
resolutionsd, hd, fhd, 4k, 6k, 8k. The long edge determines the bucket.
file_sizetiny, small, medium, large, xlarge, huge.
person_countnone, single, two, three, small-group, big-group, crowd.
lensExact lens string from metadata.
color_spacesrgb, display-p3, adobe-rgb, prophoto-rgb, uncalibrated.
bit_depthString value such as 8, 10, 12, 14, 16, or 32.
file_typeLowercase extension such as jpg, cr3, or mp4.
camera_makeExact manufacturer string.
camera_modelMake:Model, for example Canon:EOS R5.
geographyhas_location or no_location.
versionshas_versions (more than the original version) or no_versions.
country, state, city, suburbStringified location IDs.
categoriesStringified category IDs; a parent includes its subtree.
labelsStringified label IDs.
collectionsCollection UUIDs.
rating<criterionId>:<stars>, <criterionId>:unrated, avg:<stars>, any:unrated, or any:incomplete.
custom<fieldId>:<value>, <fieldId>:__has__, or <fieldId>:__empty__.

File-size buckets use decimal bytes: tiny is below 1 MB, small is 1–10 MB, medium is 10–50 MB, large is 50–250 MB, xlarge is 250 MB–1 GB, and huge is at least 1 GB.

avg:<stars> buckets each file on the rounded mean of its per-criterion average ratings. Only system and team-scoped criteria the file has ratings on count; ratings on collection-scoped criteria are excluded from the API's average.

ID-based values come from your own records or the app. API v1 does not provide facet or taxonomy-listing endpoints.

Numeric custom fields

custom_ranges is not a tristate map. Its keys are custom-field IDs; either bound may be omitted.

json
{
  "filters": {
    "custom_ranges": {
      "7": { "min": 10, "max": 500 }
    }
  }
}

Semantic query controls

Descriptive phrases work well with semantic search. Prefix an individual word with - to exclude that concept, for example dog on a beach -people.

When q or filters.similar_to is present, filters.max_distance sets a cosine-distance cutoff from 0 through 1. Lower values are stricter; 1 disables the cutoff. Omitting it uses the server default (0.55).

json
{
  "q": "golden hour",
  "filters": { "max_distance": 0.4 }
}

Search by image

filters.similar_to takes the id of one of your files and ranks the results by visual similarity to it: closest first, the seed itself excluded, every other filter narrowing the ranked set. When similar_to is present, q and mode are ignored. A seed that has been deleted or has no image embedding yet (videos and documents never get one) returns an empty list.

json
{
  "filters": {
    "similar_to": "019b1a2c-3d4e-7f80-9a1b-2c3d4e5f6a7b",
    "labels": { "12": "include" }
  }
}