ProofKit

תיעוד

API ומפרט הקבלה

כתובת אחת, מסמך JSON אחד בתשובה. התשובה היא הקבלה החתומה.

POST /api/v1/check

גוף: {"text": "…"} — UTF-8, בין 5 ל־20,000 תווים. במסלול החינמי לא צריך מפתח.

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)."}'
קודמשמעות
200קבלה: {body, sig, digest, log}
400אין טקסט, הוא קצר מדי או ארוך מ־20,000 תווים
429rate_limited (פרץ) או monthly_limit — במסלול החינמי 100 הפניות בחודש לכל רשת

כותרת התשובה x-proofkit-remaining מראה כמה הפניות חינמיות נשארו החודש. תוכניות Pro ו־Team מקבלות מפתח API עם מגבלות גבוהות יותר: שלחו אותו כ־Authorization: Bearer pk_live_…, והתשובה תכלול x-proofkit-plan. מפתח לא תקין מחזיר 401 invalid_api_key; תוכנית שפג תוקפה חוזרת למסלול החינמי.

שדות הקבלה

שדהתיאור
body.specsapir-receipt/1
body.kindcitation-check
body.tsשעת הבדיקה, ISO-8601 UTC
body.input_sha256SHA-256 של טקסט הקלט המדויק (מוכיח איזה טקסט נבדק בלי לשמור אותו)
body.checkerהשיטה והמקור
body.results[]jurisdiction (US|UK|EU|ECHR), cite, name, verdict, note, source, opinion, matched_case
verdictverified · mismatch (הפניה אמיתית, תיק אחר) · not_found · ambiguous · exists_name_unchecked · unverifiable · unchecked
body.summarytotal, verified, flagged
body.keyמפתח החתימה הציבורי (Ed25519, JWK x)
sigחתימת Ed25519 (base64url) על ה־JSON הקנוני של body
digestSHA-256 (hex) של ה־JSON הקנוני של body
logהמיקום n וגיבוב השרשרת hash ביומן השקיפות הציבורי

JSON קנוני: מפתחות האובייקטים ממוינים, בלי רווחים, escaping סטנדרטי של מחרוזות, שדות undefined מושמטים.

אימות

  1. לסדר את body בצורה קנונית.
  2. ה־SHA-256 חייב להיות שווה ל־digest.
  3. לאמת את sig ב־Ed25519 על אותם בתים עם המפתח מ־/.well-known/proofkit-pubkey; הוא חייב להיות שווה ל־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");

מגבלות. קראו לפני שאתם מסתמכים

  • כיסוי: ארה״ב — CourtListener (פעיל; חלק מהקבצים המדינתיים והישנים חלקיים). בריטניה — Find Case Law (בטא; אמין מ־2022). האיחוד האירופי — EUR-Lex, בית הדין והבית הדין הכללי (בטא). ביה״ד לזכויות אדם — HUDOC (בטא). לכל תוצאה יש שדה jurisdiction.
  • הפניות Westlaw (WL), Lexis והפניות public-domain לא ניתנות לבדיקה מול מאגר פתוח, ולכן מסומנות unverifiable.
  • התאמת השם מבוססת על מילים (≥ 0.5). שמות תיקים קצרים מאוד או חריגים עלולים לקבל mismatch גם בתיק אמיתי. תמיד פתחו את קישור המקור.
  • אנחנו מאמתים את קיום התיק וזהותו, לא אם הוא תומך בטיעון.