Search

The search API

POST /api/v1/search/query takes a question in plain language and returns ranked passages from the licensed data your organisation may search: its own data and everything partners offer on the marketplace. Retrieval is hybrid (dense, sparse and late-interaction vectors from BGE-M3), and every passage comes with its licence and provenance.

Request

RequestHTTP
POST /api/v1/search/query
Authorization: Bearer sk_live_...
Content-Type: application/json
Idempotency-Key: 7d0c2e4a-5f1b-4c8e-9a3d-2b6f1e0c9a77

{
  "query": "Which notice period applies to a fixed-term contract?",
  "top_k": 8,
  "domain": "legal",
  "use_case": "rag",
  "scope": "all"
}
FieldTypeMeaning
query requiredstring, 1–4,000 charactersWhat to search for, in plain language. A blank query is refused with 422.
top_kinteger, 1–50, default 8How many passages to return at most. You pay for the tokens in what is returned, so ask for what you will use.
domainstring or nullA subject domain such as legal, finance or medical. It steers query expansion and, where one is configured, the domain's own index.
content_typestring, default generalThe kind of content to search; picks the index. Most searches leave it as general.
use_casestring, default ragWhat you will do with the passages: search, rag, finetune, train, export or redistribute. Only passages whose licence allows that use are returned, and the use is recorded with the search.
collectionstring or nullAn index name. Needed only to check a scoped key; a scoped key may only name an index in its scopes.
scopestring or nullWhere to search: mine, marketplace, all or listing:<id>. Left out, your default applies. See Search scope.
min_tierstring or nullReserved. Accepted but not applied yet.

Unknown fields are ignored, never rejected.

Filters

The filters are domain, content_type and use_case, plus what your key's scopes allow. Partners' private data is never searched, whatever the scope.

Search scope

scope narrows what a search may reach; it never widens it.

ScopeSearches
mineOnly your organisation's own data. Nothing from another organisation, not even data another organisation has shared with you.
marketplaceOnly other organisations' published data. None of your own, published or not.
allBoth.
listing:<id>One listing. GET /api/v1/search/listings lists them, each with the scope value that searches only it. Until collections ship, a listing is one dataset.

A search that names no scope uses, in order: the default_scope:<scope> its API key was created with (add it to the key's scopes); your organisation's intent, where knowledge_bank means mine; otherwise all. An existing key and organisation therefore search what they always did.

An invalid scope is refused with 422 before anything is charged.

Response

Response200, 1 of 8 results
{
  "query_id": "qry_5b0e7d1c9a2f4e3b8c6d0a1f2e3d4c5b",
  "latency_ms": 486,
  "results": [{
    "rank": 1,
    "score": 0.8731,
    "text": "A fixed-term employment ends when the term expires ...",
    "readiness_tier": "gold",
    "source_uri": "https://example.org/handbook/chapter-4.pdf",
    "concept_ids": ["eurovoc:1234"],
    "license": {
      "spdx": "CC-BY-4.0",
      "odrl": { "permission": [ ... ], "duty": [ ... ] },
      "duo": null
    },
    "citation": {
      "source_uri": "https://example.org/handbook/chapter-4.pdf",
      "license_spdx": "CC-BY-4.0",
      "odrl": { ... },
      "dataset_id": "labour-law-handbook",
      "jurisdiction": "SE",
      "attribution": ["attribution"],
      "pii_tier": "green"
    },
    "content_class": null,
    "pii_tier": "green",
    "origin": "marketplace",
    "listing_id": "labour-law-handbook"
  }],
  "scope": "all",
  "listings": [
    { "listing_id": "labour-law-handbook", "source": "Example Publishing", "hits": 3, "ranks": [1, 2, 5] }
  ],
  "query_expansion": { ... },
  "used": { ... },
  "billing": {
    "tokens": 2210, "cost_eur": 2.21, "list_cost_eur": 2.21,
    "credits_charged": 2210, "free_query_used": false,
    "balance_credits": 47790, "replayed": false
  }
}
query_id
The id of this search. Use it to fetch the results again for free (below) and to find the search in your usage.
results[]
Up to top_k passages, best first. Empty when nothing licensed answers the question; you never get the nearest unlicensed match instead.
rank, score
Position and relevance score (higher is better; comparable within one search, not across searches).
text
The passage itself, ready to ground an answer.
readiness_tier
bronze, silver or gold: how thoroughly the source was parsed, screened and checked before it was indexed.
concept_ids
Open-ontology concepts the passage mentions.
origin, listing_id
own for your organisation's data, marketplace for another's; and the listing the passage belongs to.
scope
The scope the search ran in.
listings[]
The marketplace passages grouped by listing, best rank first: listing_id, source, hits and the ranks they hold in results. Your own passages are not grouped.
query_expansion, used
How the query was expanded and which retrieval stages ran. For debugging; the shape may change.
billing
What this call cost. See Cost of a search.

The licence and provenance object

Every passage carries the terms it is licensed under and where it came from. Read them before you use the passage, and pass the duties on to your users.

license.spdx
The SPDX identifier of the licence (CC-BY-4.0, CC0-1.0, ...) or a LicenseRef- id for the owner's own terms.
license.odrl
The owner's machine-readable policy in ODRL: what is permitted, prohibited and required.
license.duo
Data-use ontology terms, for research data that carries them; otherwise null.
citation.source_uri
The document the passage came from, for the citation in your answer.
citation.dataset_id
The dataset that holds the passage.
citation.jurisdiction
Where the data's rights were granted, for example SE, EU or global.
citation.attribution
The duties your answer must honour, such as attribution. When it lists attribution, name the source where you show the passage.
pii_tier
The personal-data band of the passage, green, yellow, red or black. green means none was found. The licence check blocks red and black passages by default.
content_class
fiction or synthetic when the owner labelled the content as not factual; null otherwise. Never present such a passage as fact.

Licence checks run per passage before the results are returned, against the use_case you sent. Searches and their licence decisions are recorded in TRIVDA's tamper-evident audit ledger.

Idempotency-Key

Send an Idempotency-Key header (any string up to 255 characters; a UUID is a good choice) so that a retry after a timeout or a dropped connection is not charged twice.

Cost of a search

The cost is in the response headers and in billing, so you can meter spend without parsing the results.

HeaderMeaning
X-Query-CostEuros charged for this call, with 6 decimals, for example 2.210000. 0.000000 for a free search, a search with no results and a replay.
X-Tokens-UsedBillable tokens in the returned passages. 0 on a replay.
X-Credits-RemainingWallet credits left after this call. 1,000 credits = €1.
Idempotent-Replayedtrue when the response is a stored replay. Absent otherwise.
billing.tokens
Billable tokens in the returned passages.
billing.cost_eur
What was charged. 0 when a free search was used.
billing.list_cost_eur
The price of what was returned, whether or not it was charged.
billing.credits_charged
Credits taken from the wallet.
billing.free_query_used
true when this search used one of the organisation's free searches.
billing.balance_credits
Credits left after the call, the same as X-Credits-Remaining.
billing.replayed
true for an Idempotency-Key replay.

How the price is computed is on Pricing and billing.

Fetching results again

GET /api/v1/search/results/{query_id} returns a search's results again for 7 days, free. It is rate-limited like a search, and only the organisation that ran the search can fetch it.

curl
curl -sS "$TRIVDA_URL/api/v1/search/results/qry_5b0e7d1c..." \
  -H "Authorization: Bearer $TRIVDA_API_KEY"

Full schemas are in the API reference.