---
title: "Retrieval Query"
method: POST
path: "/api/v1/retrieval/query"
tags: ["Retrieval"]
---

# Retrieval Query

`POST /api/v1/retrieval/query`

## Request

- Base URL: `https://api.gemina.co` (the document declares no server; this is the origin it was published from)
- URL: `https://api.gemina.co/api/v1/retrieval/query`
- Auth: one of:
  - API key in header `X-API-Key`
  - OAuth 2 (password, token URL `token`)

Structured filters, semantic or hybrid search over the tenant's index.

Auth: X-API-Key (server-to-server; ``filters.endUserId`` is a trusted
filter) OR a Bearer retrieval token (embedded SDK; a token-pinned
end-user scope is ENFORCED server-side and cannot be widened by the
request body). The tenant boundary always comes from the credential.

## Request body

- RetrievalQueryInDTO
  - `mode` 'structured' | 'semantic' | 'hybrid'
  - `text` string, nullable: Natural-language query (semantic/hybrid modes)
  - `filters` RetrievalFiltersDTO: Structured filters over promoted index columns. Tenant scope is NOT part of this DTO by design: ``user_id`` always comes from the authenticated context, server-side. ``end_user_id`` is a trusted within-tenant filter on the server-to-server path (PRD §6.6).
    - `vendorName` string, nullable
    - `vendorNames` string[], nullable
    - `docNumbers` string[], nullable
    - `documentIds` string[], nullable
    - `documentTypes` string[], nullable
    - `currencies` string[], nullable
    - `vendorTaxId` string, nullable
    - `buyerName` string, nullable
    - `docNumber` string, nullable
    - `documentType` string, nullable
    - `currency` string, nullable
    - `expenseType` string, nullable
    - `paymentMethod` string, nullable
    - `externalId` string, nullable
    - `endUserId` string, nullable
    - `documentId` string, uuid, nullable
    - `issueDateFrom` string, date, nullable
    - `issueDateTo` string, date, nullable
    - `dueDateFrom` string, date, nullable
    - `dueDateTo` string, date, nullable
    - `totalAmountMin` number, nullable
    - `totalAmountMax` number, nullable
  - `topK` integer
  - `skip` integer
  - `limit` integer
  - `structuredFilters` StructuredFilterDTO[]: Self-query conditions over any structured field (whitelisted ops)
    - `path` string, required
    - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'contains' | 'exists' | 'in', required
    - `value` union
      - string
      - integer
      - number
      - boolean
      - union[]
        - union
          - string
          - integer
          - number
  - `sortField` 'issue_date' | 'due_date' | 'total_amount' | 'vendor_name' | 'created_at', nullable
  - `sortMethod` 'asc' | 'desc'

## Response `200`

Successful Response

- RetrievalQueryOutDTO
  - `servedAt` string, date-time
  - `servedAtTimestamp` number
  - `createdAt` string, date-time, nullable
  - `createdAtTimestamp` number, nullable
  - `items` QueryResultItemDTO[]
    - `documentId` string, uuid, required
    - `documentExtractionId` string, uuid, required
    - `externalId` string, nullable
    - `endUserId` string, nullable
    - `documentType` string, nullable
    - `vendorName` string, nullable
    - `vendorTaxId` string, nullable
    - `buyerName` string, nullable
    - `docNumber` string, nullable
    - `issueDate` string, date, nullable
    - `dueDate` string, date, nullable
    - `currency` string, nullable
    - `totalAmount` number, nullable
    - `netAmount` number, nullable
    - `vatAmount` number, nullable
    - `expenseType` string, nullable
    - `paymentMethod` string, nullable
    - `structured` object, nullable
    - `score` number, nullable: Similarity score (semantic mode only)
    - `matchedChunks` MatchedChunkDTO[]: Line-item/section snippets that matched the query (chunk search)
      - `chunkType` string
      - `text` string, required
      - `score` number, nullable
  - `meta` QueryMetaDTO, required
    - `mode` string, required
    - `count` integer, required
    - `skip` integer
    - `limit` integer, nullable

## Other responses

- `422`: Validation Error
- `429`: Rate or quota limit exceeded; `errors[0].error_code` says which. Retryable limits (`FILETAG_RATE_LIMIT_EXCEEDED`, burst limits) send a `Retry-After` header: back off and retry after it. `CREDIT_EXHAUSTED` for an account with no active subscription or trial sends no `Retry-After` and is not resolved by waiting: start the free trial (once per account) or choose a plan in the console.

---

[API](https://skmtc.dev/gemina/apis/gemina-api.md) · [All operations](https://skmtc.dev/gemina/apis/gemina-api/llms.txt) · [OpenAPI document](https://skmtc.dev/gemina/apis/gemina-api/revisions/152fd3f6f6ec?raw)
