/collections/{id}/askScope ask:readGrounded answer with exact page and bbox citations, or an explicit abstention. Both retrieval paths return the same fields: `answer`, `reason`, `citations`, `receipt`, `activeWorld`, `freshness`, `answerMode` and `retrievalPath`. `answerMode` is `evidence_excerpts` on both -- the answer is the cited excerpts, concatenated in rank order, and no language model writes any part of it. `retrievalPath` names which runtime answered: `compiled-retrieval-v1` (lexical + dense + structure, RRF-fused, reranked and World Gate filtered; also returns `contextPacket` and `retrieval` diagnostics) or `excerpt-concatenation-fallback` when the active World has no queryable compiled index, which also returns `retrievalIndex` and a human-readable `retrievalNotice`. Per-citation scoring differs by path and is not normalized across them: the fallback carries `relevance` with its lexical/graph/temporal/authority breakdown, the compiled path carries per-source ranks and the reranker score. An abstention is a 200 with `code: ANSWER_ABSTAINED` — a result, not a failure.
curl -sS -X POST https://tavonel.com/api/v1/collections/{id}/ask \
-H "Authorization: Bearer $TAVONEL_API_KEY" \
-H "content-type: application/json" \
-d '{ "question": "<question>" }'import os
import requests
body = {
"question": "<question>"
}
response = requests.request(
"POST",
"https://tavonel.com/api/v1/collections/{id}/ask",
headers={"Authorization": "Bearer " + os.environ["TAVONEL_API_KEY"]},
json=body,
timeout=30,
)
response.raise_for_status()
print(response.json())const response = await fetch("https://tavonel.com/api/v1/collections/{id}/ask", {
method: "POST",
headers: { authorization: `Bearer ${process.env.TAVONEL_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({ "question": "<question>" }),
});
if (!response.ok) throw new Error(`${response.status} ${(await response.json()).code}`);
console.log(await response.json());{
"question": "<question>"
}| Status | Response |
|---|---|
200 | { code, answer, reason, citations, receipt, activeWorld, freshness, answerMode, retrievalPath }. answerMode is evidence_excerpts on both paths. retrievalPath is compiled-retrieval-v1 (which also returns contextPacket and retrieval) or excerpt-concatenation-fallback (which also returns retrievalIndex and retrievalNotice). An abstention is a 200 with code ANSWER_ABSTAINED and a reason — a result, not a failure. Read retrievalPath before comparing answers across Worlds: a difference between two answers can be a difference between two runtimes rather than between two corpora. |
400 | QUESTION_INVALID — The question was absent, or shorter than the minimum. RETRIEVAL_QUESTION_INVALID — The retrieval runtime refused the question text itself. COLLECTION_ID_INVALID — The collection id did not match collection-<32 hex>. INVALID_JSON — The body was not parseable JSON. |
401 | AUTH_REQUIRED — No credential was presented, or the bearer token is not a key TAVONEL issued. This is what an unauthenticated request to any scoped route returns. |
403 | API_SCOPE_REQUIRED — The key authenticated and does not carry the scope this operation requires. The request was refused rather than answered with less. PILOT_ACCESS_REQUIRED — The credential is valid and the workspace it names is not admitted to TAVONEL. |
409 | ACTIVE_WORLD_NOT_FOUND — Nothing has been activated for this collection, so there is no World to read, index or answer from. A candidate nobody accepted is not a smaller answer — it is a different one. ACTIVE_WORLD_CHANGED_RETRY — The active version changed while the request was in flight. |
413 | QUESTION_TOO_LARGE — The question exceeded 500 characters. |
429 | API_RATE_LIMITED — The key has used its per-minute allowance for this scope. The window is a fixed clock minute per key and scope; the allowances are on /docs/billing-and-limits. |
503 | ACTIVE_WORLD_STORE_UNAVAILABLE — The World store could not be reached. WORLD_STORE_READ_FAILED — The World store could not be read. |