---
title: "Search records"
method: POST
path: "/v0/search"
tags: ["Search"]
---

# Search records

`POST /v0/search`

## Request

- Base URL: `https://docs.quivr.thevibecompany.co` (the document declares no server; this is the origin it was published from)
- URL: `https://docs.quivr.thevibecompany.co/v0/search`
- Auth: HTTP bearer

Resolve the requested profile, compile mandatory Corpus/Organization prefilters and any requested filter, obtain candidates, then canonically hydrate and reauthorize every returned segment. Lexical-first records remain eligible without embeddings; semantic-only queries require vector coverage. Ordinary hybrid searches use keywords for Corpora whose served vectors are unavailable, reporting their ids in retrieval_profile.degraded. Other Corpora keep their hybrid ranking. Explicit semantic requests remain 422 unsupported_search when vector search cannot run. Unknown coverage alone does not disable a routed space. Profile selection does not change access/currentness rules. When a retrieval plugin is pinned, it ranks. It asks the engine for candidates in up to three rounds and returns its ranking, which may hold only candidates the engine served in this search, each already authorized and hydrated. Each API process admits at most 64 active searches across callers. At capacity it immediately returns retryable 503 search_unavailable with Retry-After before storage or plugin work. A query encoding model that cannot answer returns retryable 503 model_unavailable, including the legacy inference service and the ingestion plugin that owns the requested vector space.

## Request body

- SearchRequest: Text-only top-k query. Resolve all Corpora in the authenticated Organization and require read/search permission for every requested Corpus before querying. Never silently drop an unauthorized Corpus. Unknown/unsupported profile or mode returns 422; a dependency outage is an error, not an empty successful result. Query token limits are checked against the resolved profile; no silent truncation. An optional filter narrows candidates inside the engine query, before ranking and the limit, in every mode. The first-party retrieval plugin returns each Record once, with its best matching passage; custom plugins can request individual passages. Pagination is outside this surface.
  - `query` string, required: At most 8192 code points on the wire. A semantic or hybrid query is also limited by the owner of the searched vector space (the first-party core.ingest plugin accepts at most 256 tokens of its model's tokenizer); a longer query is refused with 422 query_too_long, whose message names the limit, never truncated.
  - `corpus_ids` string[], required
  - `mode` 'lexical' | 'semantic' | 'hybrid'
  - `profile` string: A configured short name or a full plugin/profile name this deployment answers (listSearchProfiles). retrieval.profiles maps short names, including default, to full names. An unknown profile returns 422 unsupported_profile.
  - `limit` integer
  - `evaluation_plugin` string: Ingestion plugin whose independent projection to measure. Requires evaluation_space; omitted searches follow served routing.
  - `evaluation_space` string: Vector space owned by evaluation_plugin. Both fields are required together; invalid selections return 422 unsupported_search.
  - `filter` SearchFilter: Candidate filter applied before ranking. Every present condition must hold. A requested Corpus served by a Projection Generation built before source filtering existed returns 422 source_filter_unavailable; rebuild that Corpus once (rebuildCorpusProjection) to enable it. Unfiltered search is unaffected.
    - `source_namespaces` string[]: Keep only Records whose Source Namespace is one of these values. Ranking and the limit apply within the filtered set, so a source's best matches are returned even when other sources outrank them.
    - `record_ids` string[]: Exact canonical Record identities. Requires an item-keyword generation; rebuild older Corpora first (422 metadata_filter_unavailable).
    - `version_ids` string[]: Exact canonical Version identities; currentness and authorization still apply.
    - `metadata` MetadataFilter[]: ANDed typed filters. Common fields use metadata.language, metadata.published_at, metadata.source_type, metadata.source, metadata.author, metadata.subjects, metadata.tags, metadata.country and metadata.place. Other names require the filter role in the Corpus's effective retrieval mapping. Corpora missing a requested filter field are excluded and reported. A metadata-capable generation is required; rebuild older Corpora first (422 metadata_filter_unavailable).
      - union: Every present condition must hold. Field names are unique within a request; at most 16 predicates. Wrong types and reversed bounds return 422 invalid_query. Missing/mistyped source values do not match. Datetimes are normalized to UTC milliseconds (submillisecond digits are truncated).
        - object
          - `field` string, required
          - `any_of` union[], required: Exact equality (one value) or any-of equality. String-array fields match any element; values retain their declared type. Datetime equality uses RFC3339 strings.
            - union
              - …
          - `gte` string, date-time: Inclusive lower datetime bound. Requires a datetime field.
          - `lte` string, date-time: Inclusive upper datetime bound. Requires a datetime field.
        - object
          - `field` string, required
          - `any_of` union[]: Exact equality (one value) or any-of equality. String-array fields match any element; values retain their declared type. Datetime equality uses RFC3339 strings.
            - union
              - …
          - `gte` string, date-time, required: Inclusive lower datetime bound. Requires a datetime field.
          - `lte` string, date-time: Inclusive upper datetime bound. Requires a datetime field.
        - object
          - `field` string, required
          - `any_of` union[]: Exact equality (one value) or any-of equality. String-array fields match any element; values retain their declared type. Datetime equality uses RFC3339 strings.
            - union
              - …
          - `gte` string, date-time: Inclusive lower datetime bound. Requires a datetime field.
          - `lte` string, date-time, required: Inclusive upper datetime bound. Requires a datetime field.

## Response `200`

Successful response

- SearchResponse: Bounded top-k results after canonical rechecks. May contain fewer hits than requested; no total count, completeness promise or stable pagination snapshot. Empty results still name the resolved profile.
  - `excluded_corpora` CorpusExclusion[]
    - `corpus_id` string, required
    - `fields` string[], required
  - `items` SearchHit[], required
    - `record_id` string, required
    - `version_id` string, required
    - `part_key` string, required
    - `segment_id` string, required
    - `segmentation_id` string, required
    - `projection_generation_id` string, required
    - `embedding_artifact_id` string
    - `vector_space_id` string
    - `rank` integer, required
    - `excerpt` SearchExcerpt, required: Exact canonical normalized Part text slice [start,end), using Unicode code points, not UTF-8 bytes or UTF-16 units. End must be >= start and end-start must equal the excerpt code-point length. Bounds are checked against the referenced immutable Part. No synthetic highlights or rewritten snippets.
      - `text` string, required
      - `start` integer, required
      - `end` integer, required
      - `coordinate_system` 'unicode_codepoint', required
    - `passage_text` string: Exact packed passage text used for the hit, when source-range metadata is available.
    - `source_excerpts` object[]
      - `part_key` string, required
      - `text` string, required
      - `start` integer, required
      - `end` integer, required
      - `coordinate_system` 'unicode_codepoint', required
    - `availability` Availability, required
      - `state` 'materialized' | 'building_baseline' | 'retrieval_ready' | 'quarantined', required
      - `is_current` boolean, required
      - `searchable` boolean, required
    - `explanation` string: Why the retrieval plugin ranked this hit here, when it says so.
  - `retrieval_profile` SearchProfile, required: Resolved retrieval profile identity. Name is the requested short or full name (default when the request named none). Version identifies what ranked as plugin:<plugin id>@<version>/<profile>, naming the retrieval plugin, its version and the profile.
    - `name` string, required
    - `version` string, required
    - `degraded` SearchDegradation[]: Omitted when fully served. Ordinary hybrid searches report the authorized, non-excluded Corpora whose vector half is unavailable and whose results use keywords. Present even when no documents match.
      - `reason` 'vectors_unavailable', required: No usable served vector route or current coverage confirms no vectors; keywords remain available. Stale and unknown counts do not disable current routes.
      - `corpus_ids` string[], required
  - `usage` SearchUsage: What a search answered by a retrieval plugin spent; rounds of the plugin, elapsed time, the paid calls and total cost across all profiles, and the time spent in each phase.
    - `rounds` integer, required
    - `elapsed_ms` integer, required
    - `paid_calls` integer, required
    - `cost_cents` number, required
    - `profiles` SearchProfileUsage[]: Each profile invocation, outer first; paid calls and cost belong to that plugin only.
      - `profile` string, required: Full plugin/profile name.
      - `plugin_version` string, required
      - `rounds` integer, required
      - `paid_calls` integer, required
      - `cost_cents` number, required
    - `phases` SearchPhases: Milliseconds a search spent in each phase. routing_ms authorizes the request and routes it to projection generations; coverage_ms reads the vector spaces and their coverage; plugin_rounds_ms waits for the retrieval plugin's rounds; query_encoding_ms encodes the query with the plugin that owns each vector space, 0 when no candidate request needs a vector; index_query_ms queries the index; hydration_ms rechecks and reads candidates from canonical storage. The phases do not add up to elapsed_ms, which also counts the engine's own work between them.
      - `routing_ms` integer, required
      - `coverage_ms` integer, required
      - `plugin_rounds_ms` integer, required
      - `query_encoding_ms` integer, required
      - `index_query_ms` integer, required
      - `hydration_ms` integer, required

## Other responses

- `default`: Structured error; 400 malformed, 401 unauthenticated, 403 unauthorized scope/action, 404 absent/inaccessible, 409 idempotency conflict, 422 unsupported_profile, query_too_long (the query is over the profile's or the vector space owner's length limit; the message names it), unsupported_search or source_filter_unavailable, 502 retrieval_plugin_invalid (the retrieval plugin broke its contract, for example ranked a segment the engine never served it), 503 model_unavailable (the query encoding model could not answer) or search_unavailable (another search dependency is unavailable), 504 search_deadline_exceeded (the retrieval plugin's rounds outran the profile's hard bound, four times max_latency_ms; a dependency that does not answer in time is 503). At search capacity, 503 search_unavailable includes Retry-After; retry only after that delay.

---

[API](https://skmtc.dev/thevibecompany/apis/quivr-http-api.md) - [All operations](https://skmtc.dev/thevibecompany/apis/quivr-http-api/llms.txt) - [OpenAPI document](https://skmtc.dev/thevibecompany/apis/quivr-http-api/revisions/4f4e30ba8f4e?raw)
