> For a complete page index of the Captain API documentation, fetch https://docs.captain.dev/llms.txt?excludeSpec=true

# Batch Query - v3

POST https://api.captain.dev/v3/collections/batch-query
Content-Type: application/json

Query up to 10 collections in one request. Each entry in `collections` takes every [Query](/reference/v3/query) parameter plus `collection`, and the top-level `query` fills any entry that omits its own.

`results[i]` answers `collections[i]` with that collection's own ranked list. Lists are never merged, and scores from different collections are not comparable. Check each entry's `status` before reading its `results`: errors found before any search fail the whole request, and a failure during a search stays in its own slot.

See [Query Several Collections](/guides/advanced-querying#query-several-collections) for the full guide.

Reference: https://docs.captain.dev/reference/v3/batch-query

## Request

### Body (application/json)

This endpoint expects a MultiQueryRequestV3.

- `collections` (list of MultiQueryItemV3, required) — One entry per collection to query, 1 to 10. Each entry takes every v3 Query parameter plus `collection`. `results[i]` in the response answers `collections[i]`. The same collection may appear more than once.
- `query` (string, optional, nullable) — Query used by every entry that does not set its own `query`.

## Response

### 200

One result per entry, in request order.

- `execution_time_ms` (integer, required) — Wall-clock time for the whole request, in milliseconds.
- `request_id` (string, required)
- `results` (list of MultiQueryResponseV3ResultsItems, required) — One entry per requested collection, in request order: `results[i]` answers `collections[i]`. Each entry is its own ranked list; results are never merged across collections, and scores from different collections are not comparable. Check `status` before reading an entry's `results`.

## Errors

### 400 Bad Request Error

An entry has an invalid setting, such as an unknown `exclude_chunk_types` value or a malformed filter. Nothing ran.

- `error` (string, required) — Error kind. `HTTP_ERROR` for errors raised by the route.
- `message` (string, required) — What went wrong.
- `path` (string, required) — The request path.
- `status_code` (integer, optional) — The HTTP status code.

### 401 Unauthorized Error

Missing or invalid authentication.

- `error` (string, required) — Error kind. `HTTP_ERROR` for errors raised by the route.
- `message` (string, required) — What went wrong.
- `path` (string, required) — The request path.
- `status_code` (integer, optional) — The HTTP status code.

### 403 Forbidden Error

The API key lacks the `query` permission, or an entry names an inactive collection. Nothing ran.

- `error` (string, required) — Error kind. `HTTP_ERROR` for errors raised by the route.
- `message` (string, required) — What went wrong.
- `path` (string, required) — The request path.
- `status_code` (integer, optional) — The HTTP status code.

### 404 Not Found Error

An entry names a collection that does not exist or was deleted. Nothing ran.

- `error` (string, required) — Error kind. `HTTP_ERROR` for errors raised by the route.
- `message` (string, required) — What went wrong.
- `path` (string, required) — The request path.
- `status_code` (integer, optional) — The HTTP status code.

### 422 Unprocessable Entity Error

No query for an entry, a blank query, or fewer than 1 or more than 10 entries. Nothing ran.

- `error` (string, required) — `VALIDATION_ERROR`.
- `message` (string, required)
- `details` (list of V3CollectionsBatchQueryPostResponsesContentApplicationJsonSchemaDetailsItems, required) — One entry per invalid field, with `type`, `loc` and `msg`.
- `path` (string, required)

### 504 Gateway Timeout Error

The request could not finish its checks in time. Nothing ran.

- `error` (string, required) — Error kind. `HTTP_ERROR` for errors raised by the route.
- `message` (string, required) — What went wrong.
- `path` (string, required) — The request path.
- `status_code` (integer, optional) — The HTTP status code.

## Types

### MultiQueryItemV3

One entry of a multi-collection query: every v3 Query parameter, plus the collection it runs against. `query` may be omitted, in which case the request's top-level `query` is used.

- `collection` (string, required) — Name of the collection this entry queries.
- `boost` (list of BoostClauseV3, optional, nullable) — Optional metadata-based ranking: a list of up to 10 boost rules, each naming some of your own custom_metadata and how much to favour the chunks carrying it. Use it when a chunk is the right answer but does not match the query's wording, for example one a reviewer tagged as the answer to this question, or one your application already cited earlier in a conversation. Each rule both retrieves chunks carrying that metadata and multiplies their retrieval score by `weight`. With reranking on the reranker still decides the final order unless a rule sets `reserve`. Omit the field entirely and retrieval is unchanged. See the Advanced Search guide for choosing a weight.
- `exclude_chunk_types` (list of enum, optional, nullable) — Layout roles to drop from results: body, table, heading, page_header, page_footer, footnote, figure. Useful for removing repeated page furniture such as running headers and footnotes. Applied during retrieval, before reranking, so excluded chunks never occupy a result slot. Chunks with no layout label always pass. Unknown values return a 400.
  - Allowed values: `body`, `table`, `heading`, `page_header`, `page_footer`, `footnote`, `figure`
- `filter` (MultiQueryItemV3Filter, optional, nullable) — Document metadata filter expression. Keys are top-level field names, never nested under `metadata` or `custom_metadata`. A bare value is an implicit `$eq` (`{"policy_area": "payments"}`). Supported operators: `$eq` (=), `$ne` (≠), `$gt` (>), `$gte` (≥), `$lt` (\<), `$lte` (≤), `$in`, `$nin`, and the logical `$and` and `$or`. `$in` and `$nin` take a list; every other operator takes a scalar. Max nesting depth is 10. To scope a query to specific documents, filter on `file_id` with `$in`. See the [Advanced Querying guide](/guides/advanced-querying) for more.
- `include` (QueryIncludeV3, optional) — Controls which optional result objects are included in the response.
- `limit` (integer, optional, default: 10) — Maximum number of ranked chunks to return.
- `max_chunks_per_document` (integer, optional, nullable) — Cap on how many chunks any single document may occupy in `results`. Ranking is unchanged: the same ranked chunks come back, minus a document's surplus beyond the cap, backfilled with the next best chunks from other documents so `limit` results still come back whenever the ranked pool has them. The cap is applied inside retrieval itself, so the candidate pool spans many documents rather than being thinned after the fact. Omitted (the default) applies no cap. The two numbers compose: `limit = N x K` returns up to N documents with up to K chunks each, in document-rank order, and each result's `document` object (`include.document`, on by default) carries the document's id, filename, and source. For the five most relevant documents, send `limit: 5` with `max_chunks_per_document: 1`.
- `query` (string, optional, nullable) — Query for this entry. Omit it to use the request's top-level `query`.
- `relation_direction` (enum, optional, default: outgoing) — Which graph edge direction to include for relation context.
  - Allowed values: `outgoing`, `incoming`, `both`
- `relation_types` (list of string, optional, nullable) — Optional relation type filter when `include.relations` or `include.related_chunks` is enabled.
- `rerank` (MultiQueryItemV3Rerank, optional, default: false) — Rerank this entry's retrieved candidates before returning its top results. Boolean form uses the default reranker over a pool of `limit` x 3 candidates. Object form tunes reranking (see RerankOptions). Same behavior as `rerank` on a single-collection query.
- `semantic_ratio` (double, optional, default: 0.5) — Balance between semantic and keyword retrieval. Captain searches both ways at once: keyword (sparse, BM25) matches the words in the query, semantic (dense vector) matches its meaning. 0.0 is keyword only, 1.0 is semantic only, and 0.5 (the default) weighs them equally. Lower it for corpora full of exact terms such as part numbers or error codes; raise it when callers phrase questions in their own words. Between the endpoints both searches run, so a result found only by the down-weighted side still appears, just lower. The endpoints skip the other search entirely: 0.0 also skips embedding the query, making it the fastest option, though queries using `boost` and collections holding images, video, or audio keep vector search running. See the Advanced Querying guide for more.
- `top_k` (integer, optional, nullable, deprecated) — Deprecated alias for `limit`, accepted so v2 callers migrating to v3 are not silently given the default page size. Use `limit`.

### MultiQueryResponseV3ResultsItems

- `status`: `failed` (CollectionQueryFailedV3)
  - `collection` (string, required) — The collection this entry queried.
  - `error` (CollectionQueryErrorV3, required)
- `status`: `succeeded` (CollectionQuerySucceededV3)
  - `collection` (string, required) — The collection this entry queried.
  - `limit` (integer, required) — Result limit applied to the request.
  - `query` (string, required) — Echo of the submitted query.
  - `rerank` (QueryRerankV3, required) — Whether reranking was applied and why.
  - `results` (list of FileSearchResultV3, required) — Retrieved source chunks sorted by final retrieval score.
  - `timing` (QueryTimingV3, required) — Timing for this entry's own query only, not the whole request's authentication and collection lookup. The top-level `execution_time_ms` covers the whole request. Stage offsets share one monotonic origin; overlapping durations must not be summed.
  - `total_results` (integer, required) — Number of results returned in this response.
  - `boost` (list of BoostAppliedV3, optional) — The boost rules this query applied, each with `matched`, `in_pool`, and `on_page` counts. Always present; empty when no boost was sent.
  - `exclude_chunk_types` (list of string, optional) — The layout roles this query excluded, echoed back so a caller can confirm what the server applied. Empty when none were requested.
  - `execution_time_ms` (integer, optional, nullable) — Compatibility alias for this entry's `timing.total_ms`.
  - `query_id` (string, optional, nullable) — Id of this query in your history. Fetch it back with GET /v2/queries/\{query\_id}. Present when the query was stored (completed, non-streamed queries).
  - `request_id` (string, optional, nullable) — Request identifier for support and trace lookup.
  - `semantic_ratio` (double, optional, default: 0.5) — The semantic/keyword balance applied to this query. Always present; 0.5 when the request did not set one.
  - `warnings` (list of string, optional) — Non-fatal notices about the request or response, such as forced reranking for multimodal collections.

### V3CollectionsBatchQueryPostResponsesContentApplicationJsonSchemaDetailsItems

### BoostClauseV3

One boost rule. A boost rule is one entry in the request's `boost` array: some metadata to look for, and how much to favour the chunks carrying it. Each rule is exactly one of three shapes, and anything else returns a 422: * `{ "field": ..., "eq": ..., "weight": ... }` - one metadata value * `{ "field": ..., "in": [...], "weight": ... }` - any of several values, and list-valued metadata * `{ "chunk_ids": [...], "weight": ... }` - specific chunks, by id `weight` is always required. The other properties are marked optional only because which ones apply depends on the shape: `field` is required with `eq` or `in`, and unused by a `chunk_ids` rule.

- `weight` (double, required) — Required. Multiplier on the matching chunk's retrieval score, 0.2 to 5.0. The rule's retrieval pass is what makes a chunk appear; the weight decides where it lands. 1.5 to 2.0 is a good default and is usually enough to lift a tagged chunk to the top. Use 3.0 to 5.0 when boosted chunks compete with each other, or when a rule matches many chunks. Below 1.0 demotes, and only reorders chunks the query already found. When several rules match the same chunk their weights multiply, capped at 5.0.
- `field` (string, optional, nullable) — Required with `eq` or `in`; omit it for a `chunk_ids` rule. One of your own custom_metadata keys, the same keys `filter` accepts. Anything filterable is boostable, with no re-indexing. Captain's internal attributes (file_id, job_id, chunk_index and similar) return a 400.
- `eq` (BoostClauseV3Eq, optional, nullable) — Requires `field`. Boost chunks whose `field` equals this value. Strings, numbers, and booleans are supported. A list-valued field matches when any element equals it. Use `in` instead for several values.
- `in` (list of BoostClauseV3InItems, optional, nullable) — Requires `field`. Boost chunks whose `field` matches any of these values, up to 50. Use it for one key with several acceptable values, and for list-valued metadata.
- `chunk_ids` (list of string, optional, nullable) — Use instead of `field`/`eq`/`in` to boost specific chunks, up to 100. Accepts a `chunk_id` from a previous response, or `document_id:chunk_index`, which keeps resolving after the document is re-indexed. Use it to keep a follow-up question anchored to passages an earlier answer cited.
- `reserve` (integer, optional, default: 0) — With reranking on, guarantee this many of this rule's chunks a place on the page, chosen by reranker order. Reranking runs after boosting and can otherwise drop a boosted chunk whose text does not resemble the query. 0 (default) leaves the reranker's judgement in charge. The sum across all boost rules cannot exceed `limit`.

### MultiQueryItemV3Filter

Document metadata filter expression. Keys are top-level field names, never nested under `metadata` or `custom_metadata`. A bare value is an implicit `$eq` (`{"policy_area": "payments"}`). Supported operators: `$eq` (=), `$ne` (≠), `$gt` (>), `$gte` (≥), `$lt` (\<), `$lte` (≤), `$in`, `$nin`, and the logical `$and` and `$or`. `$in` and `$nin` take a list; every other operator takes a scalar. Max nesting depth is 10. To scope a query to specific documents, filter on `file_id` with `$in`. See the [Advanced Querying guide](/guides/advanced-querying) for more.

### QueryIncludeV3

Optional expansions for v3 query results. Leave expensive context off unless the caller needs it.

- `document` (boolean, optional, default: true) — Include the parent document object for each returned chunk.
- `metadata` (boolean, optional, default: true) — Include Captain-generated retrieval metadata and application-supplied chunk metadata.
- `regions` (boolean, optional, default: false) — Include extracted layout regions, including bounding boxes when available.
- `relations` (boolean, optional, default: false) — Include graph relations connected to each returned chunk.
- `related_chunks` (boolean, optional, default: false) — Include linked chunks for returned relations.
- `neighboring_chunks` (boolean, optional, default: false) — Include the chunk immediately before and after each result in the source file.
- `document_metadata` (boolean, optional, default: false)
- `archived` (boolean, optional, default: false) — Include chunks archived by a sync `archive` deletion policy. Archived content is excluded from search by default; set true to surface it.

### MultiQueryItemV3Rerank

Rerank this entry's retrieved candidates before returning its top results. Boolean form uses the default reranker over a pool of `limit` x 3 candidates. Object form tunes reranking (see RerankOptions). Same behavior as `rerank` on a single-collection query.

- boolean
- Rerank Options: RerankOptions

### CollectionQueryErrorV3

- `message` (string, required)
- `status_code` (integer, required) — HTTP status the entry would have returned on its own.
- `detail` (CollectionQueryErrorV3Detail, optional, nullable) — Structured error detail, when the error carries one.
- `retry_after_seconds` (integer, optional, nullable) — Seconds to wait before retrying this entry, when the error is temporary (the single-collection query sends this as a Retry-After header).

### QueryRerankV3

Reranking status for the query response.

- `used` (boolean, required) — Whether reranking was applied.
- `reason` (enum, required) — Why reranking was applied or skipped.
  - Allowed values: `requested`, `disabled`, `required_for_multimodal`, `default_for_multimodal`
- `model` (string, optional, nullable) — The reranker model that ran. Null when reranking was not applied.
- `candidate_limit` (integer, optional, nullable) — The candidate pool size that was reranked. Null when reranking was not applied.
- `fallback` (string, optional, nullable) — Recorded rerank fallback outcome, when available. Read alongside used, reason, model, candidate_limit, and warnings.

### FileSearchResultV3

A retrieved chunk from an indexed file.

- `chunk_id` (string, required) — Stable identifier for the retrieved chunk. Chunk IDs include the parent document identifier and chunk index.
- `score` (double, required) — Final retrieval score used to rank the result. Use it to compare results within the same response, not across unrelated collections.
- `text` (string, required) — Retrieved chunk text.
- `modality` (enum, optional, default: unknown) — Indexed content type that matched the query.
  - Allowed values: `text`, `pdf`, `document`, `image`, `audio`, `video`, `spreadsheet`, `unknown`
- `match_sources` (list of enum, optional) — Retrieval signals that contributed to the match, such as `content_embedding`, `keyword`, `ocr`, `table`, `transcript`, `metadata`, or `summary`.
  - Allowed values: `content_embedding`, `transcript`, `ocr`, `table`, `metadata`, `summary`, `keyword`
- `document` (FileSearchDocumentV3, optional, nullable) — Parent file for the chunk when `include.document` is enabled.
- `location` (FileSearchLocationFromV3, optional, nullable) — Where the chunk appears inside the source file. PDF and document results use page fields, media results use time fields, and spreadsheet results use sheet, row, and column fields.
- `media` (FileSearchMediaV3, optional, nullable) — Media-specific context for audio and video results, such as transcript data for the retrieved segment.
- `regions` (list of FileSearchRegionFromV3, optional, nullable) — Extracted layout regions when `include.regions` is enabled. Regions can represent OCR text, form fields, headings, tables, charts, or image areas.
- `metadata` (FileSearchResultV3Metadata, optional, nullable) — Captain-generated retrieval, ranking, source location, and indexed content metadata.
- `custom_metadata` (FileSearchResultV3CustomMetadata, optional, nullable) — Application-supplied chunk metadata from indexing or chunk metadata update endpoints.
- `rerank_score` (double, optional, nullable) — Score assigned by the reranker for this result when reranking is applied.
- `relations` (list of ChunkRelationFromV3, optional, nullable) — Graph edges connected to the retrieved chunk when relation context is requested.
- `related_chunks` (list of RelatedChunkV3, optional, nullable) — Linked chunks returned with relation context, including their text, location, and metadata when available.
- `neighboring_chunks` (ChunkNeighborsV3, optional, nullable) — The chunk immediately before and after this result in the source file, when `include.neighboring_chunks` is enabled.
- `chunk_type` (enum, optional, nullable) — Layout role of this chunk, classified from the parser's block structure at indexing time: body, table, heading, page_header, page_footer, footnote, or figure. Null when the chunk has no label: content indexed before chunk types shipped, plain-text and media content, or regions the parser returned without block structure. Treat unknown future values as additive.
  - Allowed values: `body`, `table`, `heading`, `page_header`, `page_footer`, `footnote`, `figure`
- `boost` (ResultBoostV3, optional, nullable) — Set when a boost rule matched this result; null otherwise.

### QueryTimingV3

- `stages` (list of QueryStageV3, required) — Measured stage groups ordered by start offset. Each stage name appears once; repeated work is preserved in segments. Groups can overlap. Skipped operations are omitted. Asset signing, when performed during hydration, is nested inside that hydration interval, not additional disjoint time. Offsets and endpoints use one monotonic origin, rounded down to milliseconds.
- `total_ms` (integer, required) — Query processing time from handler entry before authentication through response model construction. Excludes gateway routing, request-body parsing, JSON serialization, compression, network transfer, client decoding, and background tracking. Measured independently, never summed from stages.

### BoostAppliedV3

One boost rule, echoed back with what it did. See BoostClauseV3 on the request for what each property means.

- `weight` (double, required) — The multiplier this rule applied.
- `field` (string, optional, nullable) — The metadata key this rule targeted.
- `eq` (BoostAppliedV3Eq, optional, nullable) — The value this rule matched on.
- `in` (list of BoostAppliedV3InItems, optional, nullable) — The values this rule matched on.
- `chunk_ids` (list of string, optional, nullable) — The chunks this rule targeted.
- `reserve` (integer, optional, default: 0) — Page slots this rule guaranteed. 0 means the reranker decided.
- `matched` (integer, optional, default: 0) — Retrieved chunks this rule matched.
- `in_pool` (integer, optional, default: 0) — Matched chunks that reached reranking. Equals `matched` when reranking is off.
- `on_page` (integer, optional, default: 0) — Matched chunks in the results returned.
- `applied` (boolean, optional, default: true) — False when boosts were skipped; a warning explains why.

### BoostClauseV3Eq

Requires `field`. Boost chunks whose `field` equals this value. Strings, numbers, and booleans are supported. A list-valued field matches when any element equals it. Use `in` instead for several values.

- string
- integer
- double
- boolean

### BoostClauseV3InItems

- string
- integer
- double
- boolean

### RerankOptions

Object form of the `rerank` parameter. The boolean form stays valid: `true` is equivalent to sending this object with every field at its default.

- `enabled` (boolean, optional, default: true) — Whether to rerank. Sending the object without this field means enabled — the object form exists to tune reranking.
- `candidate_limit` (integer, optional, nullable) — How many fused retrieval candidates are fetched and reranked before the top `limit` results are returned. Defaults to `limit` x 3 (the measured configuration). Must be >= `limit`; capped at 200. Larger pools can lift recall on corpora with many near-duplicate documents, at the cost of rerank latency.
- `model` (string, optional, nullable) — Reranker model. Voyage cross-encoders: `voyage-rerank-2.5` (default) and `voyage-rerank-3` (aliases `rerank-2.5`, `rerank-3`). Gemini LLM rerankers: `gemini-2.5-flash` and `gemini-3.8-flash` — higher quality ceiling on complex queries, higher latency; best with small candidate pools. The family aliases `voyage` and `gemini` resolve to each family's default. Unknown values return a 400 listing the allowed set.

### CollectionQueryErrorV3Detail

Structured error detail, when the error carries one.

### FileSearchDocumentV3

Parent document for a returned chunk.

- `id` (string, optional, nullable) — Document identifier.
- `filename` (string, optional, nullable) — Original or indexed filename.
- `source` (FileSearchSourceV3, optional, nullable) — Original source location and MIME type for the document.
- `custom_metadata` (map from string to any, optional, nullable)

### FileSearchLocationFromV3

- `page_start` (integer, optional, nullable)
- `page_end` (integer, optional, nullable)
- `chunk_index` (integer, optional, nullable)
- `parent_chunk_index` (integer, optional, nullable)
- `start_seconds` (double, optional, nullable)
- `end_seconds` (double, optional, nullable)
- `sheet_name` (string, optional, nullable)
- `row_start` (integer, optional, nullable)
- `row_end` (integer, optional, nullable)
- `col_start` (integer, optional, nullable)
- `col_end` (integer, optional, nullable)

### FileSearchMediaV3

Media-specific context for audio and video chunks.

- `transcript` (string, optional, nullable) — Transcript text associated with the returned media segment.

### FileSearchRegionFromV3

- `type` (string, optional, nullable) — Region category, such as `text`, `title`, `section_header`, `key_value`, `table`, `figure`, `chart`, or `image`. Regions of type `figure`, `chart`, or `image` also carry a cropped `image_url` (a visual citation).
- `text` (string, optional, nullable)
- `page` (integer, optional, nullable)
- `bbox` (map from string to double, optional, nullable)
- `confidence` (string, optional, nullable)
- `image_url` (string, optional, nullable) — Short-lived presigned URL to a cropped image of the region (a visual citation), returned for `figure`, `chart`, and `image` regions when `include.regions` is true. Null for text regions and for documents indexed before figure cropping was enabled. Fetch promptly — the link expires within minutes.
- `description` (string, optional, nullable)

### FileSearchResultV3Metadata

Captain-generated retrieval, ranking, source location, and indexed content metadata.

### FileSearchResultV3CustomMetadata

Application-supplied chunk metadata from indexing or chunk metadata update endpoints.

### ChunkRelationFromV3

- `relation_id` (string, required)
- `source_chunk_id` (string, required)
- `target_chunk_id` (string, required)
- `relation_type` (string, required)
- `target_document_id` (string, optional, nullable)
- `target_status` (enum, optional, default: unknown)
  - Allowed values: `found`, `missing`, `unknown`
- `metadata` (ChunkRelationFromV3Metadata, optional)
- `created_at` (string, optional, nullable)
- `updated_at` (string, optional, nullable)

### RelatedChunkV3

Chunk linked to a search result through a requested relation.

- `chunk_id` (string, required) — Related chunk identifier.
- `document_id` (string, optional, nullable) — Parent document identifier for the related chunk.
- `text` (string, optional, nullable) — Related chunk text when included.
- `location` (FileSearchLocationFromV3, optional, nullable) — Source position for the related chunk.
- `metadata` (RelatedChunkV3Metadata, optional, nullable) — Metadata associated with the related chunk.
- `chunk_type` (enum, optional, nullable) — Layout role of this chunk, classified from the parser's block structure at indexing time: body, table, heading, page_header, page_footer, footnote, or figure. Null when the chunk has no label: content indexed before chunk types shipped, plain-text and media content, or regions the parser returned without block structure. Treat unknown future values as additive. Present on related and neighboring chunks as well.
  - Allowed values: `body`, `table`, `heading`, `page_header`, `page_footer`, `footnote`, `figure`

### ChunkNeighborsV3

The chunks immediately before and after a result in the source file, returned when `include.neighbors` is enabled.

- `prev` (RelatedChunkV3, optional, nullable) — The chunk immediately before this result in the source file. Null when this result is the first chunk.
- `next` (RelatedChunkV3, optional, nullable) — The chunk immediately after this result in the source file. Null when this result is the last chunk.

### ResultBoostV3

Why a result was boosted, and where it stood before the boost.

- `multiplier` (double, required) — The combined weight applied to this chunk, capped at 5.0.
- `clauses` (list of integer, optional, default: []) — Which boost rules matched, as positions in the request's `boost` array.
- `pre_boost_rank` (integer, optional, nullable) — This chunk's retrieval rank before the boost, 1-based.
- `pre_boost_score` (double, optional, nullable) — This chunk's retrieval score before the boost.
- `reserved` (boolean, optional, default: false) — True when `reserve` placed this result on the page rather than its score.

### QueryStageV3

- `name` (string, required) — Public operation name. New names may be added; clients must tolerate unknown names.
- `start_ms` (integer, required) — Start offset in milliseconds from the shared query-processing origin.
- `duration_ms` (integer, required) — Wall-clock extent from this stage's first start to last finish. May overlap other stages. Use segments when present to preserve gaps and concurrent intervals.
- `segments` (list of QueryStageSegmentV3, optional, nullable) — Actual intervals when a stage runs more than once. Do not add overlapping durations or infer continuous work between them.

### BoostAppliedV3Eq

The value this rule matched on.

- string
- integer
- double
- boolean

### BoostAppliedV3InItems

- string
- integer
- double
- boolean

### FileSearchSourceV3

Original source information for an indexed file.

- `type` (string, optional, nullable) — Source kind, such as uploaded file, cloud object, URL, or Captain-managed file.
- `uri` (string, optional, nullable) — Original file URI or Captain-managed URI.
- `mime_type` (string, optional, nullable) — MIME type when known.

### ChunkRelationFromV3Metadata

### RelatedChunkV3Metadata

Metadata associated with the related chunk.

### QueryStageSegmentV3

- `start_ms` (integer, required)
- `duration_ms` (integer, required)

## Examples

**Request**

```json
{
  "collections": [
    {
      "collection": "contracts",
      "filter": {
        "region": "EU"
      },
      "limit": 3
    },
    {
      "collection": "emails",
      "limit": 2,
      "query": "contract renewal reminder"
    }
  ],
  "query": "renewal terms"
}
```

**Response**

```json
{
  "execution_time_ms": 431,
  "request_id": "req_1790600000_3f9a1c2e",
  "results": [
    {
      "status": "succeeded",
      "collection": "contracts",
      "limit": 3,
      "query": "renewal terms",
      "rerank": {
        "used": false,
        "reason": "disabled"
      },
      "results": [
        {
          "chunk_id": "7c2e9a41d5b84f0e9a3c6d18b2f47e05:4",
          "score": 0.0833,
          "text": "12.1 Renewal. This Agreement renews automatically for successive twelve-month terms unless either party gives written notice of non-renewal at least ninety days before the end of the current term.",
          "modality": "pdf",
          "match_sources": [
            "content_embedding",
            "keyword"
          ],
          "document": {
            "id": "7c2e9a41d5b84f0e9a3c6d18b2f47e05",
            "filename": "msa-northwind-2025.pdf",
            "source": {
              "type": "file",
              "uri": "captain://org_example/users/user_example/collections/contracts/msa-northwind-2025.pdf",
              "mime_type": "application/pdf"
            }
          },
          "location": {
            "page_start": 9,
            "page_end": 9,
            "chunk_index": 4,
            "parent_chunk_index": 4,
            "start_seconds": null,
            "end_seconds": null,
            "sheet_name": null,
            "row_start": null,
            "row_end": null,
            "col_start": null,
            "col_end": null
          },
          "custom_metadata": {
            "region": "EU"
          }
        }
      ],
      "timing": {
        "stages": [
          {
            "name": "preparation",
            "start_ms": 0,
            "duration_ms": 22
          },
          {
            "name": "embedding",
            "start_ms": 22,
            "duration_ms": 171
          },
          {
            "name": "retrieval",
            "start_ms": 193,
            "duration_ms": 142
          },
          {
            "name": "fusion",
            "start_ms": 335,
            "duration_ms": 9
          },
          {
            "name": "hydration",
            "start_ms": 344,
            "duration_ms": 44
          }
        ],
        "total_ms": 388
      },
      "total_results": 1,
      "boost": [],
      "exclude_chunk_types": [],
      "execution_time_ms": 388,
      "query_id": "019b8e41-6c2a-7d13-a5f0-2e7c9b4d1a60",
      "request_id": "req_1790600000_3f9a1c2e-0",
      "semantic_ratio": 0.5,
      "warnings": []
    },
    {
      "status": "succeeded",
      "collection": "emails",
      "limit": 2,
      "query": "contract renewal reminder",
      "rerank": {
        "used": false,
        "reason": "disabled"
      },
      "results": [
        {
          "chunk_id": "b41f0d7a93e2468c8e5a1f27c9d30b6e:0",
          "score": 0.0909,
          "text": "Subject: Northwind renewal notice window\n\nA reminder that the Northwind agreement renews on March 1. Notice of non-renewal is due by December 1.",
          "modality": "email",
          "match_sources": [
            "content_embedding",
            "keyword"
          ],
          "document": {
            "id": "b41f0d7a93e2468c8e5a1f27c9d30b6e",
            "filename": "northwind-renewal-reminder.eml",
            "source": {
              "type": "file",
              "uri": "captain://org_example/users/user_example/collections/emails/northwind-renewal-reminder.eml",
              "mime_type": "message/rfc822"
            }
          }
        }
      ],
      "timing": {
        "stages": [
          {
            "name": "preparation",
            "start_ms": 0,
            "duration_ms": 25
          },
          {
            "name": "embedding",
            "start_ms": 25,
            "duration_ms": 176
          },
          {
            "name": "retrieval",
            "start_ms": 201,
            "duration_ms": 150
          },
          {
            "name": "fusion",
            "start_ms": 351,
            "duration_ms": 8
          },
          {
            "name": "hydration",
            "start_ms": 359,
            "duration_ms": 43
          }
        ],
        "total_ms": 402
      },
      "total_results": 1,
      "boost": [],
      "exclude_chunk_types": [],
      "execution_time_ms": 402,
      "query_id": "019b8e41-6c2b-7a88-9d34-5b1e0f7c2a91",
      "request_id": "req_1790600000_3f9a1c2e-1",
      "semantic_ratio": 0.5,
      "warnings": []
    }
  ]
}
```

**SDK Code**

```python Python REST
import requests

BASE_URL = "https://api.captain.dev"
API_KEY = "your_api_key"

response = requests.post(
    f"{BASE_URL}/v3/collections/batch-query",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json={
        "query": "renewal terms",
        "collections": [
            {"collection": "contracts", "limit": 3, "filter": {"region": "EU"}},
            {"collection": "emails", "limit": 2, "query": "contract renewal reminder"},
        ],
    },
    timeout=60.0,
)
response.raise_for_status()

for entry in response.json()["results"]:
    if entry["status"] == "failed":
        print(entry["collection"], "failed:", entry["error"]["message"])
        continue
    for result in entry["results"]:
        print(entry["collection"], result["chunk_id"], round(result["score"], 4))

```

```typescript TypeScript REST
const BASE_URL = "https://api.captain.dev";
const API_KEY = "your_api_key";

const response = await fetch(`${BASE_URL}/v3/collections/batch-query`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "renewal terms",
    collections: [
      { collection: "contracts", limit: 3, filter: { region: "EU" } },
      { collection: "emails", limit: 2, query: "contract renewal reminder" },
    ],
  }),
});

const data = await response.json();
if (!response.ok) {
  throw new Error(`${response.status}: ${data.message}`);
}
for (const entry of data.results) {
  if (entry.status === "failed") {
    console.log(entry.collection, "failed:", entry.error.message);
    continue;
  }
  for (const result of entry.results) {
    console.log(entry.collection, result.chunk_id, result.score.toFixed(4));
  }
}

```