ProofKit

Documentation

API et spécification du reçu

Un seul point d'accès, un document JSON en retour. La réponse est le reçu signé.

POST /api/v1/check

Corps : {"text": "…"} — UTF-8, de 5 à 20 000 caractères. Pas de clé nécessaire en offre gratuite.

curl -X POST https://proof.sapir861.com/api/v1/check \
  -H "content-type: application/json" \
  -d '{"text":"See Marbury v. Madison, 5 U.S. 137 (1803)."}'
StatutSignification
200Reçu : {body, sig, digest, log}
400Texte manquant, trop court ou de plus de 20 000 caractères
429rate_limited (pic) ou monthly_limit — l'offre gratuite est de 100 références par mois et par réseau

L'en-tête de réponse x-proofkit-remaining indique les références gratuites restantes ce mois-ci. Les offres Pro et Team reçoivent une clé d'API avec des limites plus élevées : envoyez-la sous la forme Authorization: Bearer pk_live_… ; la réponse contient alors x-proofkit-plan. Une clé non valide renvoie 401 invalid_api_key ; une offre expirée repasse en offre gratuite.

Champs du reçu

ChampDescription
body.specsapir-receipt/1
body.kindcitation-check
body.tsHeure UTC de la vérification, ISO-8601
body.input_sha256SHA-256 du texte exact soumis (prouve quel texte a été vérifié sans le conserver)
body.checkerMéthode et source utilisées
body.results[]jurisdiction (US|UK|EU|ECHR), cite, name, verdict, note, source, opinion, matched_case
verdictverified · mismatch (vraie référence, autre affaire) · not_found · ambiguous · exists_name_unchecked · unverifiable · unchecked
body.summarytotal, verified, flagged
body.keyClé publique de signature (Ed25519, JWK x)
sigSignature Ed25519 (base64url) du JSON canonique de body
digestSHA-256 en hexadécimal du JSON canonique de body
logPosition n et hash de chaîne dans le journal public de transparence

JSON canonique : clés des objets triées, sans espaces, échappement JSON standard des chaînes, champs undefined omis.

Vérification

  1. Sérialiser body de façon canonique.
  2. Le SHA-256 doit être égal à digest.
  3. Vérifier sig en Ed25519 sur les mêmes octets avec la clé de /.well-known/proofkit-pubkey ; elle doit être égale à body.key.x.
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");

Limites. À lire avant de vous fier au résultat

  • Couverture : États-Unis — CourtListener (en service ; certains recueils d'États et anciens sont incomplets). Royaume-Uni — Find Case Law (bêta ; fiable depuis 2022). UE — EUR-Lex, Cour de justice et Tribunal (bêta). CEDH — HUDOC (bêta). Chaque résultat comporte un champ jurisdiction.
  • Les références Westlaw (WL), Lexis et du domaine public ne peuvent pas être vérifiées dans une base ouverte : elles sont marquées unverifiable.
  • La correspondance des noms se fait mot à mot (≥ 0,5). Des noms d'affaire très courts ou inhabituels peuvent donner mismatch pour une affaire réelle. Ouvrez toujours le lien vers la source.
  • Nous vérifions l'existence et l'identité de l'affaire, pas si elle soutient l'argument.