API Reference
Version: 6.1.2 ·
Base URL: https://tensalis-engine-23557189636.us-central1.run.app
Overview
Tensalis provides multi-layer hallucination detection and surgical correction for LLM outputs via a REST API. The system uses deterministic fact extractors and Natural Language Inference (NLI) to verify individual claims against source context — catching contradictions that embedding similarity misses.
The API is stateless and model-agnostic. It verifies the output of any LLM provider (OpenAI, Anthropic, Google, Cohere, etc.) without making external LLM calls itself.
The API is currently in early access. No authentication is required. API key management is planned for a future release. Contact us for production integration support.
Endpoints
POST /v1/rag
The primary verification endpoint. Send an LLM-generated response with its source context. Tensalis decomposes the response into atomic facts, verifies each against context, and optionally corrects contradictions.
Request
POST /v1/rag
Content-Type: application/json
{
"query": "What is the return policy?",
"context_docs": [
"Returns accepted within 30 days of purchase.",
"Items must have original tags attached.",
"Refunds are processed within 5 business days."
],
"response": "You can return items within 60 days. Refunds take 5 business days.",
"auto_correct": true
}
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | The original user question |
context_docs | array[string] | Yes | Source context documents (retrieved chunks, knowledge base excerpts) |
response | string | Yes | The LLM-generated response to verify |
auto_correct | boolean | No | Enable surgical correction of contradicted facts. Default: false |
Response
{
"is_trustworthy": false,
"confidence": 0.42,
"severity": "high",
"response": "You can return items within 30 days. Refunds take 5 business days.",
"original_response": "You can return items within 60 days. Refunds take 5 business days.",
"was_corrected": true,
"audit_id": "TEN-2026-A3F7B1C2",
"facts": [
{
"claim": "return items within 60 days",
"type": "DURATION",
"status": "contradicted",
"confidence": 0.95,
"evidence": "Returns accepted within 30 days of purchase.",
"correction": "return items within 30 days"
},
{
"claim": "Refunds take 5 business days",
"type": "DURATION",
"status": "supported",
"confidence": 0.92,
"evidence": "Refunds are processed within 5 business days."
}
],
"detection_layers": {
"crf_drift_detected": false,
"cbf_fabrication_detected": false,
"nsc_facts_total": 2,
"nsc_facts_supported": 1,
"nsc_facts_contradicted": 1
},
"timing": {
"total_ms": 147,
"crf_ms": 0.3,
"cbf_ms": 0.1,
"nsc_ms": 142,
"correction_ms": 4.6
},
"version": "6.1.2"
}
Response Fields
| Field | Type | Description |
|---|---|---|
is_trustworthy | boolean | Overall trust verdict |
confidence | float | Confidence score (0.0–1.0). Based on supported vs contradicted facts, penalized by drift/fabrication severity |
severity | string | none, low, medium, high, critical |
response | string | Corrected response (if auto_correct enabled), otherwise original |
original_response | string | The original LLM response, preserved for audit comparison |
was_corrected | boolean | Whether any facts were surgically corrected |
audit_id | string | Deterministic audit ID (TEN-YYYY-XXXXXXXX) for compliance trail |
facts | array | Per-fact verification results (see below) |
detection_layers | object | Which detection layers triggered |
timing | object | Per-layer latency breakdown in milliseconds |
version | string | Engine version |
Fact Object
| Field | Type | Description |
|---|---|---|
claim | string | The atomic claim extracted from the response |
type | string | NUMERIC, CURRENCY, DATE, DURATION, ENTITY, NEGATION, RELATION, GENERAL |
status | string | supported, contradicted, unsupported, uncertain |
confidence | float | Verification confidence for this specific fact |
evidence | string | The context passage that supports or contradicts this claim |
correction | string | Corrected value (only present if status is contradicted and auto_correct is true) |
Audit Ledger Endpoints
Every verification is recorded in a hash-chained audit ledger. These endpoints let you query, analyze, and verify the integrity of the audit trail.
GET /v1/ledger/records
Retrieve verification records with optional filters.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | int | 50 | Max records to return (1–500) |
offset | int | 0 | Pagination offset |
severity | string | — | Filter by severity: low, medium, high, critical |
is_trustworthy | boolean | — | Filter by trust verdict |
after | ISO datetime | — | Records after this timestamp |
before | ISO datetime | — | Records before this timestamp |
audit_id | string | — | Retrieve a specific record by audit ID |
source | string | — | Filter by source: api, bench, demo |
# Example: Get recent high-severity failures
GET /v1/ledger/records?severity=high&is_trustworthy=false&limit=20
GET /v1/ledger/stats
Returns aggregate analytics over all ledger records.
{
"total_requests": 1247,
"trust_rate": 0.84,
"avg_latency_ms": 153.2,
"avg_confidence": 0.78,
"total_facts_verified": 4891,
"contradiction_rate": 0.12,
"correction_rate": 0.09,
"severity_distribution": {
"none": 1048,
"low": 87,
"medium": 62,
"high": 38,
"critical": 12
},
"first_record": "2026-02-20T10:15:30Z",
"last_record": "2026-02-26T14:22:01Z"
}
GET /v1/ledger/verify
Walks the entire audit ledger and re-computes every hash to detect tampering. Returns chain validity status.
{
"valid": true,
"records_checked": 1247,
"first_hash": "a3f7b1c2...",
"last_hash": "d8e2f4a1..."
}
Code Examples
Python
import requests
BASE_URL = "https://tensalis-engine-23557189636.us-central1.run.app"
def verify_response(query: str, context: list[str], response: str, auto_correct: bool = True) -> dict:
"""Verify an LLM response against source context."""
result = requests.post(
f"{BASE_URL}/v1/rag",
json={
"query": query,
"context_docs": context,
"response": response,
"auto_correct": auto_correct
},
timeout=10
)
result.raise_for_status()
return result.json()
# Example usage
result = verify_response(
query="What are the account limits?",
context=[
"Free accounts are limited to 100 API calls per day.",
"Pro accounts have a limit of 10,000 calls per day."
],
response="Free accounts can make up to 1,000 API calls per day."
)
if not result["is_trustworthy"]:
print(f"Hallucination detected (severity: {result['severity']})")
if result["was_corrected"]:
print(f"Corrected: {result['response']}")
for fact in result["facts"]:
if fact["status"] == "contradicted":
print(f" ✗ {fact['claim']}")
print(f" Evidence: {fact['evidence']}")
JavaScript / Node.js
const BASE_URL = "https://tensalis-engine-23557189636.us-central1.run.app";
async function verifyResponse(query, contextDocs, response, autoCorrect = true) {
const res = await fetch(`${BASE_URL}/v1/rag`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query,
context_docs: contextDocs,
response,
auto_correct: autoCorrect
})
});
if (!res.ok) throw new Error(`Verification failed: ${res.statusText}`);
return res.json();
}
// Example usage
const result = await verifyResponse(
"What is the refund policy?",
["Refunds processed within 5-7 business days after approval."],
"Refunds are instant and processed immediately."
);
console.log(`Trustworthy: ${result.is_trustworthy}`);
console.log(`Audit ID: ${result.audit_id}`);
if (result.was_corrected) {
console.log(`Corrected response: ${result.response}`);
}
cURL
curl -X POST https://tensalis-engine-23557189636.us-central1.run.app/v1/rag \
-H "Content-Type: application/json" \
-d '{
"query": "What is the return window?",
"context_docs": ["Returns accepted within 30 days of purchase."],
"response": "You can return items within 90 days.",
"auto_correct": true
}'
# Check ledger stats
curl https://tensalis-engine-23557189636.us-central1.run.app/v1/ledger/stats
# Verify chain integrity
curl https://tensalis-engine-23557189636.us-central1.run.app/v1/ledger/verify
# Get recent high-severity records
curl "https://tensalis-engine-23557189636.us-central1.run.app/v1/ledger/records?severity=high&limit=10"
Error Handling
400 Bad Request
{
"detail": "Missing required field: context_docs"
}
Caused by missing required fields or malformed JSON.
422 Unprocessable Entity
{
"detail": "context_docs must contain at least one document"
}
Caused by empty arrays or invalid field values.
500 Internal Server Error
Transient model loading or inference failure. Retry after 2–5 seconds. If the service has been idle, the first request may experience a cold start (10–30 seconds) while models load into memory.
The first request after an idle period loads ~3 ML models (embeddings, NLI, NER) into memory. This cold start takes 10–30 seconds. Subsequent requests run in under 200ms. For production use, consider sending a periodic health check to keep the service warm.
Integration Patterns
RAG Pipeline (Post-Generation)
The most common pattern: verify the LLM response before returning it to the user.
# Your existing RAG pipeline
context = retrieve_documents(user_query)
llm_response = generate_response(user_query, context)
# Add Tensalis verification
result = verify_response(
query=user_query,
context=context,
response=llm_response,
auto_correct=True
)
if result["is_trustworthy"]:
return result["response"] # Verified (possibly corrected)
else:
return "I'm not confident in my answer. Let me connect you with a human agent."
LangChain Integration
from langchain.callbacks import BaseCallbackHandler
class TensalisVerifier(BaseCallbackHandler):
def on_llm_end(self, response, **kwargs):
result = verify_response(
query=kwargs.get("query", ""),
context=kwargs.get("context_docs", []),
response=response.generations[0][0].text,
auto_correct=True
)
if not result["is_trustworthy"]:
raise ValueError(f"Hallucination detected: {result['severity']}")
Performance Characteristics
| Metric | Value | Notes |
|---|---|---|
| Median latency | <200ms | Warm instance, typical request |
| Cold start | 10–30s | First request after idle (model loading) |
| External LLM calls | 0 | All models run locally |
| Max context size | ~10K tokens | Combined context_docs |
| Max response size | ~5K tokens | Single response text |
| Concurrency | 80 | Cloud Run concurrency limit |
Changelog
v6.1.2 (Current — February 2026)
- Hash-chained JSONL audit ledger with tamper detection
- Ledger query, stats, and verification endpoints
- Deterministic audit IDs (TEN-YYYY-XXXXXXXX format)
- Multi-tenant ledger isolation
v6.1.1 (February 2026)
- Quote normalization in atomic fact extraction
- Rewritten entity contradiction detection with preposition-aware matching
- Hardened negation detection (4-strategy approach)
- 40/40 engine unit tests passing
v6.0.3 (January 2026)
- Five-layer defense-in-depth pipeline (CRF, CBF, NSC, correction, interpretability)
- Atomic fact decomposition with typed extractors
- Surgical auto-correction of contradicted facts
- Cascading NLI verification via DeBERTa
- 63/65 production benchmark accuracy (96.9%)
v5.7.x (Legacy)
- Single-layer NLI verification
- Binary VALIDATED/BLOCKED classification
- Deprecated — use
/v1/raginstead of/v1/verify
Planned
- API key authentication and rate limiting
- Webhook notifications (verification.completed, verification.failed)
- Batch processing endpoint
- Persistent ledger storage (Cloud SQL)
- Real-time alerting for severity thresholds
Support
- Documentation: docs.tensalis.com
- Email: support@tensalis.com
- Interactive API docs: /docs (Swagger UI)
Last updated: February 2026 · v6.1.2 · tensalis.com