Every AI answer —
with a receipt.
Proof Kit checks what an AI wrote against the source and returns a cryptographically signed receipt that anyone can verify offline. Start with legal citations: see which cases are real — in seconds.
- Open receipt spec
- Ed25519 + public hash chain
- Source: CourtListener
- Research record DOI 10.5281/zenodo.22848827
sig gN-7XztHZP4GRO5MZ0zZ…pEDA
digest 64997144dd1234f4…7fdc24
log #33 → d23cc14c…e55e
Live demo
Paste an AI-written paragraph.
Every US case citation is resolved against CourtListener. You get a verdict per citation and a signed receipt.json.
Why Proof Kit
Deterministic proof, not another model's opinion.
Probability scores — an AI judging an AI — don't hold up in front of a judge or an auditor. A receipt a third party can verify does.
Catch fabricated cases
A citation that doesn't exist — or a real citation pointing to a different case — is flagged with a link to the source.
Signed, tamper-evident
Every check returns receipt.json signed with Ed25519. Change one character and verification fails.
Public hash chain
Each receipt digest is appended to a transparency log. Removing or rewriting history breaks the chain.
Verify without us
Ten lines of Node or Python, or your browser. No account, no API call to us, no trust required.
Audit-ready evidence
Keep receipts as a record of what was checked, when and against which source — useful for record-keeping duties such as EU AI Act Art. 12.
Seconds, not hours
Paste a brief, get every citation resolved before it reaches a court, a client or a regulator.
How it works
Three steps from AI text to signed proof.
Paste or call the API
Send AI-written text to the web checker or POST /api/v1/check. We extract US reporter citations (U.S., S. Ct., F.3d, F. Supp., state reporters).
Each citation is resolved
Looked up in CourtListener; the case name is compared token by token. Verdicts: verified, wrong case, not found, ambiguous, unverifiable.
You get a signed receipt
The result is signed and its digest appended to a public hash chain. A partner, client or court can verify it without trusting us.
{
"body": {
"spec": "sapir-receipt/1",
"kind": "citation-check",
"ts": "2026-10-28T20:51:04.775Z",
"input_sha256": "e8115555b9505b63…d061b211c69",
"checker": "CourtListener citation resolver (courtlistener.com/c/), name-token match >= 0.5",
"results": [
{ "cite": "410 U.S. 113", "name": "Roe v. Wade", "verdict": "verified",
"source": "https://www.courtlistener.com/opinion/108713/roe-v-wade/" },
{ "cite": "925 F.3d 1339", "name": "Varghese v. China Southern Airlines Co.", "verdict": "not_found",
"note": "No case at this citation in CourtListener. Likely fabricated." }
],
"summary": { "total": 2, "verified": 1, "flagged": 1 },
"key": { "alg": "Ed25519", "x": "RMJOfCYzDOsYHFAMA5W5VPmnYN51jh7_sgDPzijAzu0" }
},
"sig": "gN-7XztHZP4GRO5MZ0zZTKAuat8V…JAegI0In4lE3gGpEDA",
"digest": "64997144dd1234f4…2e987fdc24",
"log": { "n": 33, "hash": "d23cc14ceead753a…52e95f85e55e" }
}Shortened for display. Real receipts include full hashes and every note.
curl -X POST https://proof.sapir861.com/api/v1/check \
-H "content-type: application/json" \
-d '{"text":"See Roe v. Wade, 410 U.S. 113 (1973)."}'import { readFileSync } from "node:fs"; // node verify.mjs receipt.json (Node 20+)
const r = JSON.parse(readFileSync(process.argv[2] || "receipt.json", "utf8"));
const canon = o => o === null || typeof o !== "object" ? JSON.stringify(o) : Array.isArray(o) ? "[" + o.map(canon).join(",") + "]"
: "{" + Object.keys(o).sort().filter(k => o[k] !== undefined).map(k => JSON.stringify(k) + ":" + canon(o[k])).join(",") + "}";
const msg = new TextEncoder().encode(canon(r.body));
const hex = Buffer.from(await crypto.subtle.digest("SHA-256", msg)).toString("hex");
const pub = (await (await fetch("https://proof.sapir861.com/.well-known/proofkit-pubkey")).json()).jwk;
const key = await crypto.subtle.importKey("jwk", pub, { name: "Ed25519" }, false, ["verify"]);
const ok = await crypto.subtle.verify({ name: "Ed25519" }, key, Buffer.from(r.sig, "base64url"), msg);
console.log(ok && hex === r.digest && pub.x === r.body.key.x ? "VALID" : "INVALID");# pip install cryptography ; python verify.py receipt.json
import json, sys, base64, hashlib, urllib.request
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
r = json.load(open(sys.argv[1] if len(sys.argv) > 1 else "receipt.json", encoding="utf-8"))
b64 = lambda s: base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
msg = json.dumps(r["body"], sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
pub = json.load(urllib.request.urlopen("https://proof.sapir861.com/.well-known/proofkit-pubkey"))["jwk"]
try:
Ed25519PublicKey.from_public_bytes(b64(pub["x"])).verify(b64(r["sig"]), msg)
ok = hashlib.sha256(msg).hexdigest() == r["digest"] and pub["x"] == r["body"]["key"]["x"]
except Exception: ok = False
print("VALID" if ok else "INVALID")No install: open https://proof.sapir861.com/verify and paste receipt.json.
Verification runs locally in your browser (WebCrypto Ed25519). Nothing is uploaded.Public key: /.well-known/proofkit-pubkey
Use cases
Starting with law. Built for any claim with a source.
Legal citations
Law firms, legal-tech and in-house teams: check every case an AI drafted before it reaches a court. Courts worldwide keep sanctioning filings with AI-invented cases.
Try free →Prices vs. source document
Did the AI quote the right price, date or figure from your PDF or CSV? Each claim will be matched to the cell it came from.
Join the waitlist →Arithmetic in AI answers
Totals, percentages and unit conversions recomputed deterministically — not judged by another model.
Request beta access →Pricing
Simple plans in USD.
Subscriptions are in early access: we invoice monthly and lock today's price for early customers.
Team
- Shared workspace
- 30,000 checks / month
- Audit export (CSV + receipts)
- Priority support
Pilot
- 30 days on your documents
- Report of every flagged citation
- No errors found in your AI output → the pilot is free
We reply within 24 hours on business days.
FAQ
Straight answers.
What exactly is checked?
Whether each US case citation exists in CourtListener and whether the case name matches. We do not judge whether a case supports your argument.
Do you store my text?
No. Text is processed in memory. Only its SHA-256 hash goes into the receipt, and only the receipt digest goes into the public log.
How can a third party verify a receipt?
Canonicalize body, hash it, and check the Ed25519 signature with our published public key — 10 lines of Node or Python, or paste it at /verify. Nothing is sent to us.
What about Westlaw / Lexis citations?
They can't be checked against an open database, so they're marked unverifiable — never silently passed.
Is this proven?
The method works on real and fabricated cases in our public tests. Independent evaluation on larger datasets is in progress; methodology is public in our research record.
What is proven — honestly. The checker tells you whether a citation exists in CourtListener and whether the case name matches. It does not judge whether the case supports your argument. Coverage is US case law available in CourtListener; Westlaw/Lexis-only cites are marked unverifiable. Independent evaluation across more models and larger datasets is in progress.
Put a receipt on your next AI draft.
Free for 100 citations a month. No account needed.