Get started
Quickstart
Four steps: get an API key, set two environment variables, run a search, and read what came back. It takes a few minutes.
1. Get an API key
- Sign in at
https://13-63-0-55.sslip.io/sign-inand create or join an organisation. - Open API keys in the dashboard and choose Create API key.
- Copy the key. It starts with
sk_live_and is shown once; TRIVDA keeps only a hash of it.
To try everything first without spending credits, switch on Sandbox key when you create it. A sandbox key (sk_test_) gets synthetic results from the same API, marked "sandbox": true, and is never charged. See sandbox keys.
Your organisation starts with 5 free searches. After those, searches are paid from the organisation's wallet; top it up under Settings → Billing.
2. Set your host and key
export TRIVDA_URL="https://13-63-0-55.sslip.io" # the host you sign in on
export TRIVDA_API_KEY="sk_live_..." # the key from step 1
Keep the key out of source control and out of browser code: anyone holding it can spend your organisation's credits.
3. Run a search
curl
curl -sS "$TRIVDA_URL/api/v1/search/query" \
-H "Authorization: Bearer $TRIVDA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"query": "How often should the compressor be serviced?", "top_k": 5}' \
-D -
-D - prints the response headers too, so you can see what the search cost.
With the SDK
from trivda import Trivda
client = Trivda() # reads TRIVDA_URL and TRIVDA_API_KEY
result = client.search("How often should the compressor be serviced?", top_k=5)
for hit in result.results:
print(hit.rank, hit.license.spdx, hit.citation.source_uri, hit.text[:120])
print("cost EUR", result.cost.query_cost_eur)
The TypeScript client is npm install trivda, and trivda search "..." does the same from a shell. See SDKs and CLI. The examples below call the API without an SDK.
Python
import os
import uuid
import requests
res = requests.post(
f"{os.environ['TRIVDA_URL']}/api/v1/search/query",
headers={
"Authorization": f"Bearer {os.environ['TRIVDA_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={"query": "How often should the compressor be serviced?", "top_k": 5},
timeout=60,
)
res.raise_for_status()
body = res.json()
for hit in body["results"]:
licence = hit["license"].get("spdx")
print(f"{hit['rank']}. {hit['score']:.2f} [{licence}] {hit['source_uri']}")
print(" ", hit["text"][:160])
print("cost EUR", res.headers["X-Query-Cost"],
"| tokens", res.headers["X-Tokens-Used"],
"| credits left", res.headers["X-Credits-Remaining"])
JavaScript (Node 18 or later)
import { randomUUID } from "node:crypto";
const res = await fetch(`${process.env.TRIVDA_URL}/api/v1/search/query`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRIVDA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({
query: "How often should the compressor be serviced?",
top_k: 5,
}),
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
const { results, billing } = await res.json();
for (const hit of results) {
console.log(hit.rank, hit.score, hit.license?.spdx, hit.source_uri);
}
console.log("cost EUR", res.headers.get("X-Query-Cost"), billing);
4. Read the response
{
"query_id": "qry_8f31c0...",
"latency_ms": 412,
"results": [{
"rank": 1,
"score": 0.91,
"text": "Every 2,000 operating hours, or once a year, whichever comes first.",
"source_uri": "s3://acme/model-7.pdf",
"readiness_tier": "gold",
"license": { "spdx": "CC-BY-4.0", "odrl": { ... }, "duo": null },
"citation": { "dataset_id": "acme-maintenance", "license_spdx": "CC-BY-4.0",
"jurisdiction": "EU", "attribution": ["attribution"], ... },
"content_class": null,
"pii_tier": "green"
}],
"billing": { "tokens": 1412, "cost_eur": 1.412, "credits_charged": 1412,
"free_query_used": false, "balance_credits": 48588, "replayed": false }
}
textis the passage. Ground your answer on it.licenseandcitationsay what you may do with it and what you must do in return, for example attribute the source. See the licence and provenance object.billingand theX-Query-Costheader say what this call cost.- An empty
resultslist means nothing licensed answered the question. That search was free.
Next
- Narrow the search with filters and
use_case. - Handle errors and rate limits, including the 402 when the wallet runs low.
- Prefer to search from an assistant? Add the MCP connector.