# Wicked Sanity > Pay-per-call hallucination / eval-check API for agents mid-loop: verify a claim against supplied context (grounded mode) or against live web evidence found at request time (open mode) before acting on it or handing it downstream. ## What a check means Grounded mode runs real HHEM-2.1-Open (Apache-2.0, `vectara/hallucination_evaluation_model`) entailment inference over (your context, the claim) -- a solved, scoreable problem. Open mode runs a real Tavily search first, then the same entailment model over the retrieved evidence -- this checks consistency with live web content found right now, not objective truth; a claim can be well-supported by current web content and still be wrong. If no relevant evidence is found, the verdict is an honest `insufficient_evidence`, never a guess. Every verdict comes from a real model inference (and, in open mode, a real live search call) run at request time -- never a cached, hardcoded, or "typical" result presented as fresh. ## Quick start POST https://sanity.wickedapi.com/check Content-Type: application/json {"claim": "The Eiffel Tower is in Paris.", "context": "The Eiffel Tower is a wrought-iron lattice tower on the Champ de Mars in Paris, France.", "mode": "grounded"} Response (HTTP 200): {"data": {"id": "...", "verdict": "supported", "confidence_score": 0.94, "evidence": [{"source": "supplied_context", "snippet": "...", "hhem_consistency_score": 0.94}], "model_used": "vectara/hallucination_evaluation_model@", "latency_ms": 900, "checked_at": "..."}, "meta": {"timestamp": "..."}} Open mode needs no context: `{"claim": "...", "mode": "open"}`. Multiple claims against one context: `POST /check/batch` with `{"claims": [...up to 50], "context": "...", "mode": "grounded"}` -> `data` is a list in input order (one payment / one rate-limit hit for the whole batch; much faster than N separate calls). ## How to read the result - `verdict` = `supported` (consistent with the source) | `contradicted` (clearly inconsistent) | `unsupported` (not supported, not clearly contradicted -- treat as unverified) | `insufficient_evidence` (open mode found nothing usable; says nothing about whether the claim is true). - `confidence_score` is the raw HHEM consistency score in [0, 1]: near 1.0 = the claim is consistent with the source, near 0.0 = inconsistent. It is NOT confidence-in-the-verdict -- a `contradicted` verdict has a score near 0. It is 0.0 for `insufficient_evidence` (nothing was scored). - `evidence` is the audit trail: the context snippet (grounded) or the Tavily citations plus the scored text (open). - Suggested policy: act on `supported`; treat `unsupported` and `insufficient_evidence` as "unverified, don't rely on it"; treat `contradicted` as "reject or re-generate". ## Auth and payment POST /check and POST /check/batch are free and rate-limited for holders of a valid `x-api-key` header (responses carry `X-RateLimit-Limit/Remaining/Reset`; on HTTP 429 honour `Retry-After`). With no key you get an x402 challenge: HTTP 402 with the base64 JSON payment requirements in the `payment-required` response header (scheme `exact`, USDC; the body also advertises this route's input/output schema via the x402 Bazaar discovery extension). Sign the EIP-3009 authorization and retry the identical request with an `X-PAYMENT` header -- any x402 client SDK does this automatically. You are only charged when a verdict is returned. Pricing is a small per-request base fee plus a price per claim checked: a batch of N claims pays the base fee once and the per-claim price N times, and open mode (a live web search per claim) has its own per-claim price. The price is computed from the request body, so retry with the SAME body you were quoted for. The current network (mainnet or testnet), unit prices and asset are always in GET /v1/status under `data.access.x402` -- read them there rather than assuming. A free-to-try testnet twin of this API, always on Base Sepolia (test USDC from https://faucet.circle.com, no real value), runs at https://sanity-test.wickedapi.com -- same endpoints and same pricing; use it to build and validate your x402 client before paying on mainnet. ## Errors All errors are `{"error": "...", "source": "..."}`: 401 (no valid key and x402 not configured), 402 (payment required), 422 (invalid body, e.g. missing `context` for grounded mode, blank claim, or over the size limits below), 429 (rate limited), 404 (unknown check id for this caller), 5xx (server). ## Limits Up to 50 claims per batch, 5,000 characters per claim, 100,000 characters (and 100 items) of context. Model inference is CPU-based: expect well under a second for a warm grounded check; open mode adds one live web search (a few seconds). ## Retrieving a check later GET /checks/{id} returns a stored check for audit/dispute, but only for the same `x-api-key` that created it (404 otherwise). Keyless x402 payers already receive the full result inline in the POST response and cannot re-fetch it by id. ## Relationship to the rest of the Wicked trust suite Fifth piece alongside Wicked Reputation (agent staking/reputation) and Wicked Identity (proof-of-agent). Independent service, independent data -- never a shared database with any sibling. ## Endpoints - Landing page: https://sanity.wickedapi.com/ - API docs (OpenAPI/Swagger UI): https://sanity.wickedapi.com/docs - OpenAPI spec: https://sanity.wickedapi.com/openapi.json - Check one claim: POST /check - Check multiple claims against shared context: POST /check/batch - Retrieve a prior check (audit/dispute, scoped to caller): GET /checks/{id} - Service catalog, pricing, limits (machine-readable): GET /v1/status - Health: GET /health