Tutorials
The complete guide — account → project → pipeline → search → integrate the API. Every screen, every endpoint.
1. Getting started
What troveGEN is
A RAG pipeline and hybrid search API you integrate into your own application.
troveGEN ingests your content — text, files, crawled pages, or synced buckets — parses and chunks it, embeds it, and stores it in a vector database. You then call troveGEN’s /search API from your own application to retrieve the most relevant chunks for a query: hybrid semantic + keyword search, reranked, filtered, permission-scoped. What you build on top of those results — the LLM you call, the prompt you write, the UI you show — is entirely yours.
- RAG Pipeline — ingest → parse → chunk → embed → upsert into your vector database.
- RAG Search — hybrid search + reranking over your vector database.
- troveGEN-Z — managed: troveGEN also hosts the vectors, so you don’t need a vector database of your own to get started.
The technical flow above is identical no matter which tier you’re on — only the billed boundary changes, shown as the bands underneath it. Buy Pipeline and Search separately against a vector database you already run, or take troveGEN-Z and let troveGEN host that middle stage too.
/ask) also exists for teams that want built-in citations and grounded answers — see Optional: the generation API. It’s off by default because generation quality and its checks are intentionally left to you — a workspace owner or admin can turn it on for the whole tenant from Billing → Generation API, which immediately reveals the Chat and Ask tabs in every project and unblocks the /ask endpoint (it 403s with GENERATION_DISABLED until then). Chat is a Claude-style conversational window (threaded history, streaming, a per-message model picker, and — when the project ingests more than one domain profile — a Domain selector that scopes retrieval to just one) for end users; Ask is the same /ask endpoint exposed as a playground with every retrieval knob visible, for testing configuration. Every Chat thread is private to the team member who started it — nobody else on the tenant, including another owner or admin, can read it; an owner/admin instead sees content-free usage counts per person under Settings → Usage → Team chat usage.Create your account
Register, sign in, and land on the dashboard — no card required.
- 1Go to
/registerand create an account with an email and password. This creates your tenant — every project, connection and key you create belongs to it. - 2You land on a Free Trial automatically: the full troveGEN-Z product (managed vectors, pipeline, hybrid search, evaluation), capped by volume rather than capability — 1 project, a one-time budget of 500 pages and 2,000 searches (it does not refill each month), 1 GB storage, 100 MB per document.
- 3Ingestion is metered in pages, not documents. A page is the parser’s real page count for a PDF, or ~3,000 characters of extracted text for formats that have no pages. That way a one-line note and a 400-page manual don’t cost the same, and you can forecast a bill before you upload.
- 4Embedding and reranking are metered only when troveGEN supplies the model. Connect your own OpenAI, Cohere or self-hosted endpoint under Connections and those meters stay at zero — you pay that provider directly instead.
- 5The Dashboard shows your plan, live usage against those caps, and a Getting started checklist that mirrors this tutorial’s sequence.
Invite your team and set roles
Admins, developers and users — who can do what, and how to bring people in.
Open Team in the left menu (owners and admins only). Press Invite people, enter an email, pick a role, and — for the User role — tick the projects they may chat with. They receive a link that works once and lasts 7 days; they choose their own password. If your deployment has no mail relay, the link is shown to you so you can send it yourself.
| Role | What they can do |
|---|---|
| Owner | Everything. The account holder cannot be changed or removed. |
| Admin | Manages the whole workspace: team, settings, billing, projects, connections, API keys. Manages developers and users; only the owner manages other admins. |
| Developer | Builds with the API: projects, documents, search, evaluation, connections, API keys, and the SDK & MCP downloads. Cannot see the team or change billing and workspace settings. |
| User | Uses Chat on the projects an admin assigned to them. Nothing else — not search, documents, keys or settings. |
Changes apply on the person’s very next request — demoting someone, withdrawing a project or removing them does not wait for a sign-in to expire. Every member signs in with their own email; one address can belong to one workspace.
Create an API key
Scoped keys for programmatic access — the credential your app actually uses.
Everything you do in the console, your own backend can do over the API with a key. Go to API Keys → Create key.
- Scopes control what the key may do:
search(query only — the right scope for a search-only backend or an MCP agent),pipeline(ingest documents, run source syncs),projects/connections(manage resources). Give a key the minimum it needs. - The full key is shown once, at creation. Store it in your backend’s secret manager — troveGEN never displays it again.
- Send it as
Authorization: Bearer trv_...or thex-api-keyheader.
curl -X POST https://trovegen.com/api/v1/projects/$PROJECT_ID/search \
-H "Authorization: Bearer trv_..." \
-H "Content-Type: application/json" \
-d '{"query":"When do refunds arrive?","mode":"hybrid"}'2. Projects & connections
What a project is
A separate knowledge base — its own documents, engines and settings — and the boundary search works within.
A project is one self-contained knowledge base. Everything you configure or ingest belongs to exactly one project:
- Documents and vectors — stored in the project’s own index (its own namespace or collection), so nothing mixes between projects.
- Engines — its own embedding model, vector store (managed by troveGEN or your own), and optional reranker and LLM connections. Two projects can use completely different models.
- Pipeline settings — chunking strategy and size, default document type, OCR mode, PII redaction.
- Retrieval settings — search mode, relevance threshold (
minScore), reranking, query expansion, model routing. - Access control — its ACL mode and signing secret.
- Quality tools — eval sets and runs, data health, taxonomy and the entity graph are all computed per project.
How search is scoped. A project’s Search tab and POST /projects/:id/search search that project only. To search several projects — or all of them — use the Search page in the left menu or POST /search; see Searching several projects.
Why the boundary exists. It keeps results relevant (an HR handbook doesn’t compete with bank statements), lets each project use the model that suits its content, and means an integration pointed at one project cannot read another’s documents.
How to organise:
- Separate apps, customers or teams → one project each.
- One knowledge base with sub-areas (HR, Finance…) → one project. Use folders or the document type, and narrow a search with a metadata filter such as
{ "domain": "finance" }. - Different users may see different documents → one project with access control, passing each user’s groups (see Access control).
Create a project
One knowledge base with its own documents, settings and API surface.
A project is the unit everything else attaches to: documents, sources, search config, eval sets. Go to Projects → New project.
- Managed (default) — create it with just a name. troveGEN hosts the vectors; no connections required. This is the fastest path and what the free trial is built for.
- BYO — pick your own vector-store connection (and optionally embedding/reranker connections) in the create form. Your vectors never touch troveGEN’s infrastructure.
POST /api/v1/projects
{ "name": "Support KB" }Connections (bring your own stack)
Vector database, embedding model, reranker, LLM — encrypted, write-only credentials.
Optional — skip entirely on managed mode. Go to Connections → New connection to register infrastructure you control. Credentials are AES-256-GCM encrypted and never returned by the API once saved.
- Vector store — Qdrant, Pinecone, pgvector, or plain Postgres (JSONB brute-force, no extension required).
- Embedding — OpenAI, Azure OpenAI, or any OpenAI-compatible endpoint (self-hosted vLLM/TEI/etc.).
- Reranker — Cohere or a self-hosted TEI (BGE) endpoint, for the cross-encoder rerank pass in Search.
- LLM (reranking) — used when Search’s rerank mode is set to
llm, and by the optional generation API if you use it.
# keyless example — no API keys needed to try it provider: openai-compatible baseURL: http://localhost:8091/v1 model: multilingual-e5-small # ~100 languages, cross-lingual dimensions: 384 # English-only alternative, same width: # model: bge-small
Note that both models are 384-dimensional but embed into different spaces, so they are not interchangeable once a project has content. troveGEN checks the model name as well as the dimension and refuses a swap on a non-empty project — delete the documents or start a new project, then re-ingest.
Every connection has a Test action that round-trips a real request before you save it, so a typo in an endpoint fails fast instead of during your first real ingest.
3. RAG Pipeline — adding knowledge
Documents tab: three ways in
Paste text, upload files, or crawl a URL — each becomes searchable chunks.
Open a project → Documents. Three ingestion paths:
- Text — paste content directly with a title and optional metadata. Fastest way to test retrieval on a paragraph.
- File — upload PDF, DOCX, TXT, Markdown and more. PDFs keep page numbers (useful for citations later); up to 100 MB per document on every plan that includes ingestion.
- URL — ingest one page, or turn on Crawl to follow links up to a Max depth and Max pages budget. A crawl job runs in the background; the panel shows live progress and, on completion, an honest breakdown of what was fetched vs. discovered vs. skipped as non-content.
Expand any document row to see its pipeline timeline — parse → OCR → chunk → embed → upsert, each stage timed, plus the chunks it produced. A failed ingest tells you exactly which stage broke and carries a request ID you can hand to support.
Deleting a document. The trash icon on a document opens a confirmation that first lists exactly what will go with it, then deletes. A delete removes the document and everything created from it, in one step:
- its text chunks and search vectors, extracted tables, figures, and the masked sensitive values in the secure vault;
- knowledge-graph names that appear only in that document, and the connection counts it contributed;
- graph communities and relations that quoted it, and Eval test questions written from it;
- the quoted passage and title in chat citations (the chat answers themselves stay as written).
Afterwards you get a receipt of what was removed plus any next step, such as rebuilding graph communities. A document that came from a connected source is imported again on the next sync unless you remove it at the source. Through the API, call GET …/documents/:id/deletion-impact to preview, then DELETE …/documents/:id.
OCR and table-aware chunking
Scanned PDFs and spreadsheets are parsed, not just stored.
- Scanned / image-only PDFs need OCR — the words are pixels, not text. OCR is the most expensive step in the pipeline (roughly 10–100× a normal parse), so it is your choice and is metered separately as OCR pages. Set it per project under Settings → Chunking → OCR, or per upload.
- Auto (the default) uses the fast text parsers and falls back to OCR only when a document has no readable text. Off never runs OCR — and a file that needs it is rejected with a clear message rather than being indexed as an unreadable shell, because we won’t claim retrieval quality on content we couldn’t read. Always forces OCR even when a text layer exists. The pipeline timeline shows an explicit OCR stage with its duration.
- Tables get table-aware chunking: rows stay whole, headers stay attached to their rows, instead of being shredded across arbitrary chunk boundaries the way naive chunking would. This is what makes tabular content in a PDF or spreadsheet actually searchable.
Metadata & filtering
Tag documents at ingest time so you can scope search later.
Attach arbitrary JSON metadata to any document at ingest — it travels onto every chunk and becomes filterable in Search.
{ "region": "eu", "year": 2026, "tier": "gold" }The GET /projects/:id/metadata-keys endpoint lists every key/value your project has seen, which is what powers the visual filter builder in the Search tab.
Sources tab: continuous sync
Point troveGEN at an S3 bucket or HTTP manifest and it stays in sync — including deletions.
Open a project → Sources → Add source for content that changes over time instead of one-off uploads.
- S3-compatible — AWS, MinIO, R2, Backblaze B2. Uses each object’s ETag as a content hash, so unchanged files are never re-embedded on a re-sync.
- HTTP manifest — publish a small JSON list (
{"items":[{ref,url,hash?}]}) from any internal system; troveGEN polls it and ingests what changed. - Deletion propagates — remove a file at the source and the next sync removes its document, chunks, and vectors. Each run shows a +added / ~updated / −deleted / =unchanged summary and per-item error detail.
4. Search — retrieval
Search tab, screen by screen
The retrieval playground — every control here maps directly to an API parameter.
Open a project → Search. This is where you tune retrieval before wiring it into your app. It searches that project only; the Search page in the left menu has the same controls plus a project picker (see Searching several projects).
- Mode —
hybrid(recommended: fuses semantic vectors with keyword BM25 via reciprocal-rank fusion),vector(finds paraphrases with zero shared words), orkeyword(exact-term matching only, useful as a baseline to see what hybrid adds). - Top K — how many results come back. 3–8 is typical for a chat UI, 8–12 for feeding an LLM. Retrieval considers a wider candidate pool internally before trimming.
- Rerank — a second-pass cross-encoder re-orders the top candidates for precision:
tei(self-hosted, keyless),cohere(needs a reranker connection), orllm(needs an LLM connection). - Trace — shows the score breakdown per result (semantic similarity, keyword overlap, fused/reranked position) plus raw chunk metadata, so you can see why a result ranked where it did.
- Filters — the visual filter builder (or raw-JSON mode) scopes results by metadata you attached at ingest.
- Act as end user (ACL testing) — simulates permission-aware retrieval; see Access control below.
Searching several projects
Pick one, several or all projects on the Search page or with POST /search; results are merged by rank.
- 1Open Search in the left menu.
- 2Select the projects to search with the chips at the top (Select all picks every project). Your choice is remembered in this browser.
- 3Enter a query and set the same options as a project’s Search tab (mode, Top K, rerank, filters…).
- One project selected — identical to that project’s own Search tab.
- Several projects — each project is searched with its own model and settings, then the lists are merged by rank (reciprocal-rank fusion). Raw scores are not used to merge, because different embedding models produce scores on different scales.
- Every result shows which project it came from. Read its score against that project’s own relevance bands.
- If one project can’t be searched (for example a filter its vector store doesn’t support), it is listed in a notice and the other projects’ results still show.
- Billing: each project searched counts as one search.
POST https://trovegen.com/api/v1/search
{
"query": "travel expense approval",
"projectIds": ["<project id or slug>", "<another>"], // omit to search every project (max 25)
"mode": "hybrid",
"topK": 8
}
→ data.results[i] { content, score, documentId, chunkIndex, metadata,
projectId, projectName, projectSlug, relevance, fusedScore }
→ data.projects[i] { id, name, slug, resultCount, error? }
→ data.pipeline { mode, topK, fusion: "none" | "rrf", projectCount, failedProjects }x-trovegen-end-user) is signed with one project’s secret, so other projects reject it and report an error. For ACL-scoped searches across projects, send onBehalfOf.principals, or call each project separately.Understanding relevance scores
What the number next to each result means, and what it doesn’t.
Every result carries a relevance score from 0 to 1 — how strongly that chunk matches your query: the stronger of its semantic similarity and keyword overlap, or the reranker’s relevance when reranking is on. It is not a judgement of the document’s quality.
- ≥ 0.75 — Strong match. Safe to quote or feed to an LLM.
- 0.50 – 0.75 — Moderate. Related; worth a skim before trusting.
- < 0.50 — Weak. Likely tangential. Raise
Min scorein Settings to hide these.
Order can differ from the raw score: hybrid mode ranks by a fused ordering of both signal rankings, and a reranker re-orders the top candidates afterward. Turn on Trace to see the full breakdown per result.
Access control (ACLs)
Permission-aware retrieval, pre-filtered on both retrieval paths, never post-filtered.
Configured in a project’s Settings → Access control card.
- Off (default) — ACLs from sources are captured but not enforced.
- Permissive — logs what enforcement would hide, without hiding it. Safe migration on-ramp.
- Enforced — both retrieval halves are pre-filtered by the caller’s principals; a document with no ACL is treated as public-only.
Your backend asserts the end user two ways: pass onBehalfOf.principals directly in the request (fine for testing — that’s what the Search tab’s “Act as end user” field does), or mint a short-lived signed token for production:
POST /api/v1/projects/:id/acl-secret # generate/rotate — secret shown once
# your backend then mints a token (HS256, ≤15m expiry):
# { sub, principals: ["group:support"], exp }
# and sends it as a header on search/ask requests:
x-trovegen-end-user: <signed-token>onBehalfOf under enforcement — the review-grade posture for production.5. Quality & configuration
Eval tab: test search and answers on your own documents
Generate test questions from your documents, run them, and compare settings by the questions that got better or worse.
Open a project → Eval. Evaluation answers one question: does search find the right information in my documents, and are the answers right? You don’t need to write test questions yourself.
- 1Press Generate from documents, choose how many questions (20 is a good start) and which documents. troveGEN reads real passages and writes the questions a user would ask, each with its correct answer.
- 2Wait for the progress bar (it runs in the background). Then Review questions: fix the wording, correct an answer, or remove questions you don’t want. Nothing is saved until you press Save.
- 3Press Run. Every question goes through the real search and answer pipeline and is scored.
- 4Change a setting (or use the run’s overrides — mode, top K, rerank, expansion) and run again. Tick two runs and Compare to see exactly which questions got better or worse.
How the questions are made — the same approach as widely used evaluation tools (RAGAS, the Hugging Face RAG-evaluation recipe), with extra checks:
- Passages are picked across all your documents, skipping ones too short or noisy to ask about.
- Each question comes with a quote from the document. If that quote isn’t found word-for-word in the passage, the question is thrown away — the AI model’s word is never taken on trust.
- A second review drops questions that are vague, unrealistic or not clearly answered.
- Three kinds: fact (one passage), multi-part (needs two neighbouring passages) and not in documents (checks the system says so instead of inventing an answer — confirmed unanswerable from the text before it is kept).
What the scores mean
- Found right doc — search returned the document holding the answer.
- Rank (MRR) — how high it ranked (100% = always first).
- Facts found — the key facts each answer needs were in what search returned.
- Answer correct — the answer matches the correct answer (graded by the AI model; partly right counts half).
- Grounded — how much of the answer is backed by the passages it cites.
- Says “not covered” — for questions the documents don’t answer, it said so.
Already have test questions? Use Write questions and paste them as JSON:
[
{ "question": "How many days of paid leave do full-time employees get?",
"expected": {
"documentIds": ["<document id from the Documents tab>"],
"referenceAnswer": "24 days per calendar year.",
"contextContains": ["24 days of paid leave"] } },
{ "question": "What is the interest rate on the savings account?",
"expected": { "shouldRefuse": true } }
]Settings: tuning retrieval defaults
The project-level defaults every /search call uses unless overridden per-request.
- Top K / Min score — default result count and the relevance floor below which results are dropped.
- Vector weight — how hybrid fusion balances semantic vs. keyword signal.
- MMR — diversify results instead of returning near-duplicates.
- Rerank + reranker connection — the default cross-encoder pass.
- Access control — enforcement mode and signed-assertion settings (see above).
Every per-request field in POST /search overrides its Settings default for that call only.
6. Integrating the API
Authentication
API keys with scopes, or JWT for dashboard-equivalent access.
Two auth modes. API keys (trv_...) are what your backend uses — scoped, revocable, never expire on their own. JWT (email/password login → access + refresh token) is what the dashboard itself uses; you generally don’t need it for integrations.
Authorization: Bearer trv_... # or x-api-key: trv_...
Calling Search from your app
The one endpoint most integrations need — in whatever your backend is written in.
curl -X POST https://trovegen.com/api/v1/projects/$PROJECT_ID/search \
-H "Authorization: Bearer $TROVEGEN_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "When do refunds arrive?",
"mode": "hybrid",
"topK": 8,
"rerank": "tei",
"filter": { "region": "eu", "year": { "$gte": 2025 } }
}'The response contains results[] (content, score, documentId, chunkIndex, metadata) plus a pipeline block describing what actually ran (mode, candidate count, whether reranking applied, ACL mode). Feed results into your own LLM call, or render them directly.
Searching more than one project? Call POST https://trovegen.com/api/v1/search with projectIds (or omit it for every project) — same options, results merged by rank and tagged with their project. Details in Searching several projects.
The TypeScript SDK
@intellara/trovegen-sdk — typed, dependency-free, works in Node and browsers.
Developers, admins and owners can download the SDK and the MCP server for this deployment from SDK & MCP in the left menu. Install both files together: npm install ./intellara-trovegen-sdk-0.1.0.tgz ./intellara-trovegen-mcp-0.1.0.tgz.
npm install @intellara/trovegen-sdk
import { TroveGenClient } from '@intellara/trovegen-sdk';
const trovegen = new TroveGenClient({ apiKey: process.env.TROVEGEN_KEY, baseUrl: 'https://trovegen.com' });
const res = await trovegen.search(projectId, {
query: 'When do refunds arrive?',
mode: 'hybrid',
topK: 8,
});
// res.results[0] → { content, score, documentId, chunkIndex, metadata }
// several projects (ids or slugs), or omit projectIds for all of them
const merged = await trovegen.searchProjects({
query: 'When do refunds arrive?',
projectIds: ['support-kb', 'billing-kb'],
});
// merged.results[0] → { ...result, projectId, projectName }
// errors are typed: TroveGenError carries { code, requestId, ... }
// retries with Retry-After are handled for youMCP server for AI agents
Turn a project into a native search tool for Claude, Cursor, and any MCP client.
{
"mcpServers": {
"trovegen": {
"command": "npx",
"args": ["trovegen-mcp"],
"env": { "TROVEGEN_API_KEY": "trv_...", "TROVEGEN_PROJECT": "<project-id>" }
}
}
}
// tools exposed: trovegen_search · trovegen_list_projects · trovegen_list_documents
// (trovegen_ask / trovegen_compute_table also available if you opt into generation)
// write tools are hidden unless TROVEGEN_ALLOW_WRITE=true — read-only by defaultErrors & rate limits
Every error is machine-readable; every 429 tells you when to retry.
{ "success": false, "error": { "code": "FILTER_INVALID", "message": "...", "details": { "path": "year.$gte" } } }- Hitting a volume cap returns
402with the metric, your usage and the limit — never a silent drop. - One deliberate exception: asking for a reranker your plan doesn’t includedoes not fail the search. It degrades to no reranking and says so in
pipeline.rerankDowngraded— refusing a whole query over an optional quality stage would be worse for you than serving the un-reranked result. - Every authenticated request also counts against a per-workspace rate limit — one shared budget across all your API keys and dashboard sessions, on by default at a generous rate. Exceeding it returns
429with aRetry-Afterheader (the SDK honors it automatically) andX-RateLimit-Limit/X-RateLimit-Remainingon every response so you can back off before you hit it. A workspace owner or admin can raise, lower, or disable it from Billing → Rate limiting. Login/register are separately guarded per IP address against brute-force attempts, always on. - Every error carries a
requestId— the same ID that appears in your project’s pipeline timeline and server logs.
Optional: the generation API
Cited, scored answers — available if you want them, not required.
troveGEN also exposes POST /projects/:id/ask: it runs the same retrieval, then routes to exact table computation, LLM-generated citations, or agentic multi-step retrieval depending on the question. Citations are validated against real retrieved chunks; answers stream over SSE; a locally-served NLI model can score groundedness.
403 GENERATION_DISABLED until a workspace owner or admin turns it on. That one switch (Billing → Generation API) governs the endpoint, the console’s Chat and Ask tabs, SDK askStream, and MCP’s trovegen_ask tool all at once — there is no separate place to enable it per surface.The Chat tab builds threaded, multi-turn conversations on top of the same endpoint via conversationId: prior turns are folded into the prompt for continuity (pronouns like “it” resolve correctly), but retrieval always runs on the question exactly as typed — history changes how the model reads a question, never what evidence it’s shown. Each message can also pin a specific model via llmConnectionId (one of your llm-kind connections), overriding the project’s default for that request only.
curl -X POST https://trovegen.com/api/v1/projects/$PROJECT_ID/ask \
-H "Authorization: Bearer trv_..." -H "Content-Type: application/json" \
-d '{"query":"When do customers get their money back?"}'
# res.answer, res.citations[], res.groundedness — all optional to use
# 403 GENERATION_DISABLED if the tenant hasn't turned this on yet7. Complete API reference
Base URL for this deployment: /api/v1. Every route below requires either an Authorization: Bearer trv_... API key or a dashboard session JWT, except health checks. A scope column value means that write is gated and a key without it gets 403 FORBIDDEN; an unrecognized scope name is rejected at key-creation time rather than silently widened. Rows with no scope shown accept any valid, unrevoked key for this tenant — reads are not currently scope-gated, so a narrowly-scoped key (e.g. search:read only) can still list projects, connections, eval runs and document metadata. If your key needs to be read-restricted too, keep it out of any integration surface you don’t fully trust.
Auth
Account + session. Dashboard uses this; API-key integrations usually skip it.
Create a tenant + user, returns access/refresh tokens.
Email + password → access/refresh tokens.
Exchange a refresh token for a new access token.
Current user + tenant.
Update your display name (dashboard session only).
Change your password (verifies the current one).
Email a 6-digit reset code. Same response whether or not the account exists.
Consume the code and set a new password. Revokes sessions issued before the reset.
Public. What an emailed team invitation is for (workspace, role, email). 404 for an unknown, used, revoked or expired link.
Public. { token, name, password } → creates the account in the inviting workspace (email already verified by the link) and signs in. A link works once.
Team & roles
Owner/admin dashboard roles only. Four roles: owner, admin, developer (API keys, SDK/MCP, projects and search — no team or billing), user (chat on assigned projects only). A role or assignment change applies on the member’s very next request.
Everyone in the workspace with role and (for users) assigned project ids.
{ role?, projectIds? }. The owner cannot be changed; an admin manages developers and users only; nobody edits themself.
Remove a member. Their access ends immediately.
Pending invitations.
{ email, role: admin|developer|user, projectIds? } → emails a single-use 7-day link and also returns it (inviteUrl) for deployments with no mail relay. Only the owner can invite an admin. The address must not already have an account.
New link, new 7-day window; the old link stops working.
Revoke.
SDK & MCP downloads
Owner, admin or developer dashboard role. The packages are built into the platform image, so what you download matches this deployment.
The bundled packages: file, package name, version, size, sha256.
Stream one .tgz. Install both together: npm install ./sdk.tgz ./mcp.tgz.
API keys
List keys (prefix + last 4 shown, never the full key).
Create a key with scopes; full key returned once.
Revoke a key immediately.
Projects
GET routes here need only a valid key — no scope, of any kind, gates them today (see the security note below the table).
List projects.
Create a project — managed (name only) or BYO (connection ids).scope: projects:write
Project detail.
Document/chunk counts and quick health.
Generate/rotate the signed end-user-token secret (shown once).scope: projects:write
Sync users + group hierarchy (IdP-agnostic); computes each user’s closed group set so a signed token can carry just sub.scope: projects:write
A synced user’s resolved (closed) principal set.
Every metadata key/value seen — powers the filter builder.
Model routing status, policy, and the eval runs that approved it.
Switch routing on from two eval runs (routing off vs on). Refused with every failed check unless accuracy holds.scope: projects:write
Switch routing off. Needs no evidence.scope: projects:write
Update retrieval config, ACL mode, generation settings.scope: projects:write
Delete a project and its bookkeeping.scope: projects:write
Connections
List connections (credentials never returned).
Create a vector-store / embedding / reranker / LLM connection.scope: connections:write
Connection detail.
Round-trip a real health check before you rely on it.
Remove a connection.scope: connections:write
Documents & ingestion (RAG Pipeline)
The Documents tab, over the wire.
List documents with status.
Ingest raw text with title + metadata.scope: pipeline:write
Upload a file (PDF/DOCX/TXT/MD/…); OCR + table-aware chunking apply automatically. Send layout="book" (optional bookTitle; title or the file name is the book name) to split it chapter > section > paragraph: every chunk is headed by its place in the book and carries book, chapter, chapter_no, section and section_path metadata (filterable). A PDF own bookmarks (its table of contents) are used as its chapters and sections when it has them. Send folderPath to place it in the folder tree.scope: pipeline:write
Ingest a file and STREAM its live pipeline stages over SSE (the Ingestion Observatory live feed).scope: pipeline:write
Ingest text and stream live pipeline stages over SSE.scope: pipeline:write
Ingest many documents over one SSE connection (observatory Hero & Swarm).scope: pipeline:write
Ingest one URL, or start a background crawl with { crawl: { maxDepth, maxPages } }.scope: pipeline:write
Poll a crawl job's progress and final counts.
Per-document stage narrative (parse → OCR → chunk → embed → upsert) with timings.
The chunks a document produced.
Re-index a document. No body (or mode "embed"): re-embed the stored chunks. Body {mode:"rechunk", chunking:{strategy,chunkSize,chunkOverlap,parentSize,contextMode,selfContainment,layout:"document"|"book"}, domain:"auto"|"keep"|"general"|<domain id>, saveAsDefault?} rebuilds the document from its text with those settings and re-checks its domain (default "auto"). Returns the replacement document id (the folder, access list and source link carry over; the old version stays searchable until the new one is ready, then is removed).scope: pipeline:write
Bulk re-detect domains. Always a background job (202 + job). {apply:false} (default) previews which documents would change domain; {apply:true, documentIds:[…]} re-chunks exactly those with the domain re-detected. Documents whose domain a person set are never touched. Poll GET /projects/:id/domains/redetect/jobs/:jobId (or …/jobs/latest) for progress and the result.scope: pipeline:write
Read-only preview of what a delete would remove: chunks + vectors, extracted tables, figures, masked values, graph names/relations/communities, eval questions, chat citations, version count, and whether a connected source will re-import it. Show this before deleting.
Permanently delete a document AND everything derived from it in one transaction — chunks, vectors, tables, figures, vault entries, graph names only it mentioned (and connection counts), communities/relations that quoted it, eval questions written from it, chat-citation passages. Returns a receipt {removed, keeps, followUps}. With versioning on, purges ALL versions (true erasure).scope: pipeline:write
Ingest a new version that supersedes this document (gap 19); prior version retained for point-in-time. Needs versioning on.scope: pipeline:write
Version lineage (supersede chain) with each version's validity + which is current.
Smart-setup: analyse a sample & recommend chunking/domain/retrieval config with rationale.scope: pipeline:write
Dry-run: preview how text parses & chunks (boundaries + metadata) without persisting or embedding.scope: pipeline:write
Folder tree (paths + document counts) — arranged from local-upload relative paths AND connector item refs.
Top graph entities by mention count.
Entity resolution: merge alias entities (e.g. "Acme Corp"/"Acme Corporation") into one canonical node; re-points mentions + edges.scope: pipeline:write
Top entity relationships (co-occurrence edges + weights) — powers expand:graph retrieval.
LLM-extract typed, directed relations (subject —predicate→ object) over the corpus. Needs a chat provider.scope: pipeline:write
Typed entity relations, heaviest first.
Detect graph communities (clusters) + summarize them. ?llm=1 for LLM summaries, else extractive.scope: pipeline:write
Detected communities (label, members, summary) — GraphRAG global/thematic questions.
The latest auto-generated taxonomy (themes + keywords) for the corpus.
Cluster the corpus into themes and back-tag chunks (keyless).scope: pipeline:write
Data-health aggregates: tiny/oversized/orphan chunks, self-containment, open flags, failed docs.
Ingestion data-quality flags (e.g. contradictions found at ingest). ?resolved=false for open ones.
Mark a data-quality flag resolved/unresolved.scope: pipeline:write
Sources & sync
Continuous ingestion from S3-compatible buckets or HTTP manifests. No single-source GET — list and runs only.
List sync sources with last-run stats.
Register a source (kind: manifest | s3).scope: pipeline:write
Trigger a sync run now (also runs on schedule).scope: pipeline:write
Run history: +added ~updated −deleted =unchanged, per-item errors.
Remove a source (does not delete already-ingested documents).scope: pipeline:write
Search (RAG Search)
The core product — hybrid retrieval, reranking, filters, ACLs.
Hybrid/vector/keyword search; mode, topK, rerank, filter, onBehalfOf, trace.scope: search:read
Search the projects you pick: projectIds (ids or slugs, up to 25); omit to search every project. Same options as project search. Several projects are merged by rank; each result carries projectId/projectName, and a project that fails is reported in projects[].error while the rest still return. Metered as one search per project searched.scope: search:read
Image-as-query: a vision model describes the image, then searches the corpus. imageBase64 + optional search params. Needs a vision model.scope: search:read
Conversations
Multi-turn threads for /ask. Entirely opt-in: without a conversationId, /ask stays stateless and stores nothing. Threads record and replay turns — retrieval always runs on the question as asked, never a rewritten one. Each thread is private to the dashboard user who created it — every route here (including GET) only ever sees or touches the caller’s own threads, never a teammate’s, even for an owner/admin. An API key (no dashboard user) gets its own separate, key-shared bucket. See /tenant/chat-usage for aggregate, content-free usage by user.
List threads, most recently active first.
Start a thread. Auto-titled from the first question asked in it.scope: search:read
Full transcript: each message with its citation snapshot, engine, groundedness score and rating.
Rename a thread: {"title": string}. A manual rename sticks — the first-message auto-title only fires while the title is still the default.scope: search:read
Delete a thread; its messages cascade.scope: search:read
Rate an answer: {"rating": 1 | -1 | null}. null clears.scope: search:read
Knowledge graph
Entities, co-occurrence edges, communities and typed relations. Extraction runs at ingest when chunkingConfig.graphMode is on; heuristic extraction is keyless, typed relations need an LLM.
Build the entity graph from documents already in the project (extraction otherwise runs only at ingest). {"enable": true} also turns Entity graph on so new uploads extend it; mode "heuristic" (default, keyless) or "llm". Full rebuild — safe to repeat.scope: projects:write
Top entities by mention count.
Co-occurrence edges, heaviest first.
Merge alias entities ("Acme Corp" + "Acme Corporation"). Idempotent; mentions and edges re-point.
Detect communities by weighted label propagation. ?llm=1 for LLM summaries, else extractive.
Detected communities, largest first.
Extract typed subject-predicate-object triples. LLM-only; keyless yields none (noModel: true). Replaces the previous relations.
Graph actions (graph/build, entities/resolve, communities/build, relations/extract) accept ?async=1: they return 202 with a job at once, and this endpoint reports status (running | completed | failed), progress {done,total} and the result. Use it for large projects — a waiting request is cut off after ~100 s behind a proxy. One graph action per project at a time (409 GRAPH_JOB_RUNNING).
The running (or most recent) graph job for the project, or null. Jobs are kept for an hour after they finish.
Typed relations with the chunk that evidences each.
Evaluation
Prove retrieval quality; A/B config changes. Both writes here need search:read, not a projects scope — evals are a retrieval concern.
List golden question sets.
Generate a question set from the project's documents (needs a chat model): {count, documentIds?, mix?: {factual, multi_part, unanswerable}, critique?}. 202 + background job. Each question is checked against its verbatim source quote and a quality review; the result is a draft to review, then save with POST /eval-sets.scope: search:read
Generation progress {done,total} (questions written), then result {questions, stats}. /generate/latest returns the running or last job.
Save a set. Each question: expected.documentIds (found right doc / MRR / nDCG), referenceAnswer (answer correct, model-judged), contextContains (facts found), answerContains (exact phrases), shouldRefuse (documents do not answer it). Optional type and source.scope: search:read
Delete a set.
Start an async run, optionally with config overrides. Returns 202; poll the run.scope: search:read
List runs; ?compare=a,b diffs two runs and names regressed/improved questions.
Run detail: hit@k, MRR, nDCG, latency p50/p95, per-question results.
Usage & billing
Current usage (pages, hosted embedding tokens, hosted reranks, searches), plan entitlements and managed-storage total.
List available plans.
Current subscription.
Start a Razorpay checkout for a plan.
Verify a completed checkout (webhook-backed).
Cancel the active subscription.
Billing details plus the tax that would apply, and why.
Set billing name, address, country and tax ID (owner/admin).
Every charge: amount, tax, method, linked invoice.
Issued invoices, newest first.
Download an invoice as a PDF.
Health
For your uptime monitor, not your application code.
Liveness — always 200 once the process is up.
Same as /health.
503 when a hard dependency (Postgres, tenant schema, configured vector/embedding endpoints) is down.
Ask (optional generation API)
Not required to use troveGEN. 403 GENERATION_DISABLED until a workspace owner/admin enables it in Billing → Generation API — see "Optional: the generation API" above.
Routes: exact table compute → text-to-SQL → grounded generation → raw chunks. mode:'agentic' for multi-step. stream:true for SSE. llmConnectionId picks a specific llm-kind connection for this request only (else the project default, then the platform default) — 400 if it isn't an llm connection you own.scope: search:read
Tenant settings
Admin-configurable platform toggles, applied tenant-wide.
Change role and/or project access: {role?, projectAccess: all|assigned, projectIds?}. Developers and users can be limited to assigned projects; their API keys follow.
Company profile (name, website, industry, size, phone, country, address, about, hasLogo). Any member.
Edit the company profile. Owner/admin.
Upload the logo: {mime: png|jpeg|webp, dataBase64}, max 512 KB. Owner/admin.
The logo image. DELETE removes it (owner/admin).
name, generationEnabled, rateLimitEnabled, rateLimitPerMinute.
Update any subset of the above (incl. workspace name) — owner/admin dashboard role only (not available to API keys).
Per-user Chat conversation/message counts + last-active time, across every project — owner/admin dashboard role only. Aggregate counts only; message content stays private to the user who wrote it.
