> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyborg.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Vectors (Binary)

Search for nearest neighbors in the encrypted index using binary-encoded query vectors for more efficient transfer of large batch queries.

## Authentication

Required - API key via `X-API-Key` header:

```http theme={null}
X-API-Key: cyborg_your_api_key_here
```

Any valid credential is accepted — the root key or a per-user `cdbk_` token. When RBAC is not enabled (`CYBORGDB_SERVICE_ROOT_KEY` unset), no header is required.

## Request Body

```json theme={null}
{
  "index_name": "my_index",
  "index_key": "64_character_hex_string_representing_32_bytes",
  "batch": {
    "vectors_b64": "BASE64_ENCODED_FLOAT32_ARRAY",
    "dimension": 384
  },
  "top_k": 10,
  "n_probes": 5,
  "greedy": false,
  "rerank_mult": 50,
  "filters": {"category": "research"},
  "include": ["distance", "metadata"]
}
```

<Expandable title="parameters">
  <ParamField body="index_name" type="string" required="true">
    Name of the target index
  </ParamField>

  <ParamField body="index_key" type="string">
    32-byte encryption key as a hex string. Required for indexes created with the SDK-supplied KEK path; omit for KMS-backed indexes (the service resolves the key from the index's stored key envelope).
  </ParamField>

  <ParamField body="batch" type="object" required="true">
    Batch of query vectors in binary format:

    <Expandable title="batch parameters">
      <ParamField body="vectors_b64" type="string" required="true">
        Base64-encoded float32 array. The decoded bytes represent a flat array of `n_queries x dimension` little-endian float32 values
      </ParamField>

      <ParamField body="dimension" type="integer" required="true">
        Dimensionality of each query vector
      </ParamField>
    </Expandable>
  </ParamField>

  <ParamField body="top_k" type="integer">
    Number of nearest neighbors to return per query. Defaults to 100
  </ParamField>

  <ParamField body="n_probes" type="integer">
    Number of clusters to probe during search. Auto-determined when not specified
  </ParamField>

  <ParamField body="greedy" type="boolean">
    Whether to use greedy search algorithm. Defaults to false
  </ParamField>

  <ParamField body="rerank_mult" type="integer" default={50}>
    Multiplier for stage 1 retrieval in reranking indexes. Stage 1 returns `top_k * rerank_mult` candidates before the rerank pass narrows the result down to `top_k`. Higher values trade query latency for recall. Ignored by indexes that do not rerank. `top_k * rerank_mult` must not exceed 10,000.
  </ParamField>

  <ParamField body="filters" type="object">
    Metadata filters to apply to the search
  </ParamField>

  <ParamField body="include" type="array[string]">
    Fields to include in response: `"distance"`, `"metadata"`. Defaults to `[]` (only `id` is returned). `"contents"` and `"vector"` are **not** valid values — fetch stored vectors or contents via `POST /v1/vectors/get` with the matching IDs afterwards.
  </ParamField>

  <ParamField body="text" type="string">
    Query text for a BM25 full-text leg. Setting it makes the query **hybrid**: the BM25 ranking is fused with the vector ranking by weighted RRF and each result carries `score` instead of `distance`. Requires an index with at least one `full_text` field.
  </ParamField>

  <ParamField body="text_fields" type="array[string]">
    Which `full_text` fields the text leg searches. Omitted means all designated fields. Naming a non-`full_text` field returns 400.
  </ParamField>

  <ParamField body="text_field_weights" type="array[number]">
    Per-field weights on the summed per-field BM25 scores, parallel to the searched fields. Omitted means 1.0 each.
  </ParamField>

  <ParamField body="require_all_terms" type="boolean" default="false">
    Require every query term to match (AND) instead of any (OR, the default).
  </ParamField>

  <ParamField body="alpha" type="number" default={0.5}>
    Leg blend in `[0, 1]`: `0` = pure BM25, `1` = pure vector. An exact endpoint skips the dead leg's retrieval.
  </ParamField>

  <ParamField body="rrf_k" type="number" default={60}>
    RRF rank-smoothing constant (must be `> 0`). Higher rewards agreement further down each leg's list.
  </ParamField>

  <ParamField body="window_mult" type="integer" default={3}>
    Per-leg candidate depth as a **multiple of `top_k`** (must be `>= 1`), so each leg looks deeper than the final cut.
  </ParamField>
</Expandable>

<Note>Hybrid queries accept fewer filters than pure vector queries. Filtering on a `full_text` or `filterable: false` field, or using `$regex`/`$contains` on a non-`pattern` field, works in a pure query but is rejected with 400 when `text` is set. See the [query endpoint](./query) for details.</Note>

All leg combinations from the standard query endpoint work here too, including the three-way form (`query_vectors` + `text` + `filters`) — see [Combining search legs](./query#combining-search-legs).

## Response

The response format is the same as the standard [query endpoint](./query). When `text` is set, each result carries a `score` (fused BM25 + vector relevance, higher = more relevant) instead of `distance`:

```json theme={null}
{
  "results": [
    [
      {"id": "doc1", "distance": 0.125, "metadata": {"category": "research"}},
      {"id": "doc2", "distance": 0.234, "metadata": {"category": "research"}}
    ],
    [
      {"id": "doc3", "distance": 0.156, "metadata": {"category": "research"}},
      {"id": "doc4", "distance": 0.278, "metadata": {"category": "research"}}
    ]
  ]
}
```

## Exceptions

<AccordionGroup>
  <Accordion title="400 Bad Request">
    Invalid values (e.g. vector dimension mismatch with the index), or a filter disallowed on a hybrid (`text`) query
  </Accordion>

  <Accordion title="401 Unauthorized">
    Authentication failed (invalid API key) **or** wrong `index_key` on SDK-supplied indexes — see [error model](../introduction#error-model-api-keys-index-keys-and-kms)
  </Accordion>

  <Accordion title="404 Not Found">
    Index not found
  </Accordion>

  <Accordion title="422 Unprocessable Entity">
    Request body failed validation (missing/mistyped fields)
  </Accordion>

  <Accordion title="500 Internal Server Error">
    Internal server error
  </Accordion>
</AccordionGroup>

## Example Usage

```bash theme={null}
# Encode query vectors as base64 float32 array (example using Python)
# query_vectors = np.array([[0.1, 0.2, 0.3, 0.4]], dtype=np.float32)
# vectors_b64 = base64.b64encode(query_vectors.tobytes()).decode()

curl -X POST "http://localhost:8000/v1/vectors/query_binary" \
     -H "X-API-Key: cyborg_your_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{
       "index_name": "my_index",
       "index_key": "your_64_character_hex_key_here",
       "batch": {
         "vectors_b64": "zczMPc3MTD6amZk+zczMPg==",
         "dimension": 4
       },
       "top_k": 5
     }'
```

<Tip>The binary format is more efficient than the standard JSON query for large batch queries, as it avoids the overhead of encoding each float as a JSON number. The SDK clients automatically use this format when query vectors are passed as typed arrays (e.g., `np.ndarray` in Python, `Float32Array` in JS/TS).</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.