---
title: "GET /search/query"
method: GET
path: "/search/query"
tags: ["search"]
---

# GET /search/query

`GET /search/query`

Execute a structured search query against the local encrypted search index.
Every query requires an unlocked session because result rendering decrypts
the encrypted payload.

ADR-008 wire change: `total`/`hasMore` are no longer top-level siblings of
the envelope — they are folded INTO the `data` payload alongside the renamed
`items` array (`SearchQueryResultDto`). The response is the canonical
`ApiEnvelope<SearchQueryResultDto>` (`{ data: { items, total, hasMore, state }, ts }`).

Index-not-ready handling is query-type-aware (§4.7): a filter-less browse
degrades to a direct main-store read and returns HTTP 200 with
`state: "degraded"`; a keyword or filtered query instead returns HTTP 503
`index_rebuilding`.

## Query parameters

- `query` string, required
- `operator` string, nullable
- `timePreset` string, nullable
- `fromMs` integer, nullable
- `toMs` integer, nullable
- `contentTypes` string, nullable
- `extensions` string, nullable
- `sourceDevices` string, nullable
- `tags` string, nullable
- `limit` integer
- `offset` integer

## Response `200`

Search results page (state ready or degraded)

- SearchQueryEnvelope — Canonical success envelope: `{ "data": T, "ts": <unix millis i64> }`. `ts` is `chrono::Utc::now().timestamp_millis()`, set in the webserver handler via [`ApiEnvelope::now`] (the contract carries only the type + the clock helper, not a hard dependency on when the handler reads the clock). `rename_all = "camelCase"` is a no-op for the single-word fields here but is declared for forward-compat. IMPORTANT (utoipa v4): every concrete `ApiEnvelope<X>` that needs a named OpenAPI component is declared in the `#[aliases(...)]` block below. Add a new alias line whenever a new payload type needs enveloping. NEVER register the bare `ApiEnvelope` in `components(schemas(...))` — utoipa errors on a bare generic, and an un-aliased generic inlines an anonymous schema.
  - `data` SearchQueryResultDto, required — Folded payload for `GET /search/query` (ADR-008 §0.1). The current handler returns `total` and `hasMore` as top-level siblings of the `{data,ts}` envelope (`data` is the items array). This DTO folds those siblings INTO the payload (renaming `data` → `items`) so the endpoint can return `ApiEnvelope<SearchQueryResultDto>` with no bespoke wrapper. P1 only defines the type; the handler is rewired in P2.
    - `hasMore` boolean, required
    - `items` SearchResultDto[], required
      - `activeTimeMs` integer, required
      - `charCount` integer, nullable — Full character count of the entry's primary text content, so the UI shows the real total length rather than the capped `textPreview` length. `null` for entries with no inline text (image / file / payload lost).
      - `contentType` string, required
      - `entryId` string, required
      - `fileExtensions` string[], required
      - `fileNames` string[], required — Display names of referenced files; empty when none.
      - `filePaths` string[], required — Local filesystem paths of referenced files, aligned with `file_names` by index; empty when none.
      - `linkUrls` string[], required — Web URLs (http/https) carried by this entry; empty when none.
      - `mimeType` string, required
      - `payloadState` string, nullable — `"Lost"` when the paste payload is unrecoverable, else `null`.
      - `sourceDevice` string, nullable — Originating device id, or `null` when the source is unknown.
      - `tags` string[], required — Derived/user-state tag ids (e.g. `"link"`, `"favorited"`). The favorite marker is expressed by the presence of `"favorited"`, not a separate flag.
      - `textPreview` string, nullable
    - `state` string, required — `"ready"` when served from the index, or `"degraded"` when the index was not ready and this filter-less browse was served from the main store (§4.7). Filtered/keyword queries never return `"degraded"` — they surface an `index_rebuilding` error instead.
    - `total` integer, required
  - `ts` integer, required — Server time when the response was built (unix epoch milliseconds).

## Other responses

- `400` — Invalid or malformed query
- `423` — Encryption session is locked (all query forms require an unlocked session)
- `500` — Internal server error
- `503` — Search index not ready, rebuilding, or unavailable

---

[API](https://skmtc.net/uniclipboard/apis/uniclipboard-daemon-api.md) · [All operations](https://skmtc.net/uniclipboard/apis/uniclipboard-daemon-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/uniclipboard/uniclipboard-daemon-api/versions/a5d29889448a/schema)
