Governed retrieval API — score sources, gate allow_answer, and audit every decision. Authenticate with X-API-Key on hosted calls.
Most integrations: you already retrieved and reranked chunks. POST them here — no new search.
POST /policy/evaluate — query + sources in → allow_answer, policy reasons, authority scores, audit_id.
curl -X POST https://queryfanout.dev/policy/evaluate \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-d '{
"query": "What is the statute of limitations for this claim?",
"policy": "legal",
"agent_id": "your-agent",
"run_id": "run-001",
"sources": [
{
"title": "Chunk title",
"snippet": "Text from your reranker...",
"url": "internal://doc-1"
}
],
"authority_overrides": {
"internal://filing": 0.92,
"internal://draft": 0.55
}
}'
Returns allow_answer: true to synthesize, false to escalate with policy.reasons.
POST /evidence — probe, fanout, policy, synthesis, and audit in one call. Use when Query Fanout should run search backends.
curl -X POST https://queryfanout.dev/evidence \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-d '{
"query": "How do refund policies work?",
"preset": "mock",
"policy": "legal",
"demo_mode": true
}'
Set demo_mode: true for prospect-safe output (no raw synthesis). Full records remain in audit export.
| METHOD | PATH | PURPOSE |
|---|---|---|
| POST | /policy/evaluate | Gate pre-retrieved sources (no search) |
| POST | /evidence | Governed retrieval + policy + synthesis |
| GET | /audit | List recent audit records (tenant-scoped) |
| GET | /audit/{{id}} | Full audit record by ID |
| GET | /policies | Named policy preset definitions |
| POST | /autopsy/upload | Upload JSONL logs for design-partner autopsy |
| GET | /health | Service health |
Hosted API requires header X-API-Key: <your-key>. Keys are tenant-scoped — audit data is isolated per design partner.
Set "audit": false on /policy/evaluate to skip audit persistence (payload still hits the API).
from query_fanout import RetrievalClient
client = RetrievalClient(policy="legal", agent_id="support-bot", audit=False)
# Pre-retrieved sources (no search)
report = client.evaluate_policy(
"How do refund policies work?",
[{"title": "...", "snippet": "...", "url": "..."}],
)
if report.allow_answer:
answer(report.synthesis)
else:
escalate(report.audit_id, report.policy.reasons)
{
"allow_answer": false,
"audit_id": "99c08409-28ec-4427-...",
"original_query": "...",
"overall_confidence": 0.76,
"policy": {
"profile": "legal",
"passed": false,
"action": "block",
"reasons": ["only 1 qualifying source(s); minimum is 3"]
},
"evidence": [
{"title": "...", "url": "...", "confidence": 0.72, "authority": 0.55, "consensus": 1.0}
],
"tenant_id": "your-tenant"
}
Need a key? Contact for design-partner access · Try endpoints interactively