Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ivory.finance/llms.txt

Use this file to discover all available pages before exploring further.

Overview

POST /v1/documents/search runs a hybrid search — BM25 keyword matching combined with KNN vector similarity — over your tenant’s private document index. The two result sets are merged so that documents matching either meaning or exact terms rank highly. IAM pre-filtering is mandatory on every query. Before the search runs, the caller’s identity, roles, and barrier memberships are evaluated against each document’s visibility, allowed_identity_ids, allowed_roles, and barrier_id fields. A document the caller cannot access returns zero results — it appears not to exist.

How hybrid search works

User query

    ├── BM25 (keyword) ─────────────────────► chunk_text match
    │                                          (exact terms, clause numbers,
    │                                           tickers, metric names)

    └── KNN (vector) ────────────────────────► chunk_vector cosine similarity
                                               (semantic meaning, paraphrases,
                                                conceptual matches)
         Both results merged
         ───────────────────
         Final ranked list (by combined score)
Use BM25-heavy queries for exact lookups (“clause 8.3”, “EBITDA covenant”) and semantic queries for conceptual search (“working capital concerns”, “management’s growth strategy”).

IAM filter logic

The search applies this filter before executing the BM25/KNN query:
tenant_id = caller's tenant
AND
(
  visibility = "tenant_wide"
  OR (visibility = "deal_private"  AND caller_identity_id IN allowed_identity_ids)
  OR (visibility = "team_only"     AND any caller_role IN allowed_roles)
)
AND
(
  barrier_id = ""                        ← document has no barrier
  OR barrier_id IN caller's crossed barriers
)
Supply caller_roles and crossed_barrier_ids to unlock the full filter. Omitting them restricts results to tenant_wide documents only.

Request

query
string
required
Natural language or keyword search query.
tenant_id
string
required
Your tenant UUID.
identity_id
string
required
The identity UUID of the user performing the search. Used for deal_private visibility checks.
caller_roles
string
Comma-separated role slugs the caller holds. Used for team_only visibility checks. Example: analyst,banker
crossed_barrier_ids
string
Comma-separated barrier UUIDs the caller has crossed. Documents behind uncrossed barriers are excluded.
entity_id
string
Scope the search to documents associated with a specific entity (deal, company, or person UUID).
doc_type
string
Filter by document type: cim · nda · management_accounts · dd_report · board_pack · research_note · legal_agreement · pitch · other
limit
integer
default:"10"
Maximum number of chunks to return. Each result is one chunk — multiple chunks from the same document may appear.

Response

query
string
The original query string.
total
integer
Number of results returned.
results
array
Array of matching chunks, ordered by relevance score.

Examples

curl -X POST https://api.ivory.finance/v1/documents/search \
  -H "X-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query":      "management concerns about leverage and covenant headroom",
    "tenant_id":  "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
    "identity_id": "usr_abc123",
    "caller_roles": "banker",
    "entity_id":  "deal_xyz789",
    "limit":      5
  }'
Response:
{
  "query": "management concerns about leverage and covenant headroom",
  "total": 4,
  "results": [
    {
      "doc_id":      "3f7a2b1c-4e8d-4a9f-b2c1-d3e4f5a6b7c8",
      "title":       "target_cim_v3.pdf",
      "doc_type":    "cim",
      "entity_id":   "deal_xyz789",
      "chunk_index": 31,
      "chunk_text":  "Management acknowledges net leverage of 4.6x as of Q3 2025, with limited headroom against the 5.0x maintenance covenant. The CFO indicated in the October board pack that a refinancing is being evaluated...",
      "s3_uri":      "",
      "score":       0.94
    },
    ...
  ]
}

Using results with the agent

Pass doc_id values from search results into POST /v1/rag/answer/agent as document_ids. The agent will blend document chunks with SEC filings and web results, citing documents as [D1], [D2], … inline.