---
title: "POST /search/count"
method: POST
path: "/search/count"
tags: ["search"]
---

# POST /search/count

`POST /search/count`

## Request

- The document declares no server URL.
- Auth: one of:
  - API key in query parameter `auth`
  - API key in header `Authorization`

Batch-count matching entries for up to 32 filter combinations in one
round trip, in request order. Powers the composite search box's
per-candidate hit counts and the zero-result "try removing this chip"
suggestions — both need many small counts without paginated items, which
a body of `GET /search/query` calls would make expensive.

Counts only ever reflect the index (never the degraded main-store
fallback): an approximate count would be worse than none. Returns HTTP
503 `index_rebuilding` while the index is not ready, same as a filtered
`query`.

## Request body

- SearchCountRequestDto: Request body for `POST /search/count` — up to 32 filter combinations, counted in one round trip.
  - `queries` SearchCountQueryDto[], required
    - `contentTypes` string, nullable
    - `extensions` string, nullable
    - `fromMs` integer, nullable
    - `operator` string, nullable
    - `query` string
    - `sourceDevices` string, nullable
    - `tags` string, nullable
    - `timePreset` string, nullable
    - `toMs` integer, nullable

## Response `200`

Counts in request order

- SearchCountEnvelope: 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` SearchCountResultDto, required: Response payload for `POST /search/count` — counts in the same order as the request's `queries`.
    - `counts` integer[], required
  - `ts` integer, required: Server time when the response was built (unix epoch milliseconds).

## Other responses

- `400`: Invalid query or more than 32 queries in one batch
- `423`: Encryption session is locked
- `500`: Internal server error
- `503`: Search index not ready, rebuilding, or unavailable

## Changes

- **2026-10-15** `4c664cabd0c5`: 4 info
  - added the optional property `requestId` to the response with the `400` status
  - added the optional property `requestId` to the response with the `423` status
  - added the optional property `requestId` to the response with the `500` status
  - added the optional property `requestId` to the response with the `503` status
- **2026-10-06** `2684828254c6`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/changes/search/count/post.md)

---

[API](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api.md) - [All operations](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/llms.txt) - [OpenAPI document](https://skmtc.dev/uniclipboard/apis/uniclipboard-daemon-api/revisions/48a01cf04e4c?raw)
