Build on verifiable AI
Every Throndar answer carries a portable, post-quantum-signed proof. These endpoints let your systems — compliance pipelines, procurement tooling, an auditor's scripts — check that proof themselves. They are public, no-auth, CORS-enabled, and stateless: nothing is stored, and the verification math runs against the keys embedded in the bundle, so you never have to trust Throndar's servers at check time.
Base URL https://throndar.ai. All bodies are JSON. A proof bundle is the exact JSON produced by the Download proof action on any answer (or the machine endpoints below). Machine-readable spec: OpenAPI 3.1 — import it into Postman/Insomnia or generate a client.
/api/v1/verifyVerify any Throndar proof — a single answer, a whole-conversation transcript, an Autopilot run evidence pack, a signed data export, a transparency-log signed tree head, or a consistency proof — auto-detected from the JSON. Returns the structured verdict computed by the same verifier the browser uses. overallOk means the embedded signatures verify against the embedded keys (INTEGRITY); signerRecognized additionally confirms the signing key is one Throndar publishes (ORIGIN). Only signerRecognized: true means “produced by Throndar.”
curl -X POST https://throndar.ai/api/v1/verify \
-H "content-type: application/json" \
--data @proof.jsonResponse
{
"service": "Throndar",
"kind": "throndar-proof",
"created": 1782000000,
"verdict": {
"overallOk": true,
"checks": 1,
"receipt": {
"present": true, "answerHashOk": true, "sigOk": true,
"keyId": "0986d89fa3c74566", "councilGrounded": true,
"promptBound": true, "promptOk": true, "questionBinding": "entire-input"
},
"excerpt": { "present": true, "ok": true },
"signerRecognized": true
},
"signerRecognized": true,
"disclaimer": "verdict.overallOk means the bundle's embedded signatures verify ..."
}The question and a quote are separate claims. The signatures cover the answer. A bundle can also carry the question (prompt) and a pinned quote (excerpt), and neither is signed by itself. receipt.questionBinding says what a bound question covers — entire-input, or current-message of a larger input disclosed in receipt.framing. promptUnverified: true means no signature covers the question shown (an older receipt; reported, not failed) — treat only the answer as attested, even beside signerRecognized: true. A bound question that doesn't match, or a quote that isn't an exact slice of the answer (excerpt.ok: false), fails the bundle. You can also post an AI Provenance Record as-is: its embedded proof is verified, its summary is recomputed from that proof and must match, and the response adds record.
councilGrounded: false flags a single-model fallback (the multi-model council did not contribute) — it is bound into the signature, so it can't be stripped or forged. Transcript bundles (kind: "throndar-transcript") return a per-turn verdict; a transcript is authentic only if every turn verifies. Autopilot evidence packs (kind: "throndar-autopilot-run", the “Download evidence pack” JSON) verify the whole guardrailed run — goal, step-output hashes, per-step verification method, budget accounting — under a separate signing domain, so a run receipt can never be replayed as a chat answer or vice versa. The endpoint also accepts a signed data export (proof.kind: "throndar-export", which binds a hash of the whole conversations payload), a signed tree head (throndar-sth — a checkpoint of the transparency log), and a consistency bundle (throndar-consistency — two signed tree heads plus an RFC 6962-bis proof that the log only appended between them, never rewrote). Every kind is domain-separated, so a signature for one can never be replayed as another.
The same verifier ships as a self-contained, offline GitHub Action — fail the build if a Throndar proof doesn't verify. It runs the identical checks as this API and the browser tool (one implementation, so a CI verdict can never diverge), against Throndar's pinned published keys, with no network call at verify time.
# .github/workflows/verify.yml
- uses: brandonjsellam-Releone/throndar-verify@v1
with:
bundle: artifacts/answer.throndar-proof.json # a file, or a directory of *.json
require-origin: "true" # reject anything not signed by a pinned Throndar keyOr run the self-contained bundle directly — node throndar-verify.mjs --require-origin ./proofs/. Exit code 0 = all verified, any non-zero fails the step; --json emits a per-file report. Each line also says what the signature covers for a question shown beside the answer — or that it is UNSIGNED — per turn for a transcript, and the JSON report carries the same as promptUnverified / questionBinding. All six proof kinds are auto-detected, and an AI Provenance Record file is accepted as-is. Source, releases + the built binary: github.com/brandonjsellam-Releone/throndar-verify (MIT).
/api/v1/evidenceTurn a proof bundle — or an Autopilot run evidence pack — into an AI Provenance Record: the verified proof embedded as the trust root, plus a factual summary and the published EU-AI-Act obligation mapping. Run records carry record_type: "autopilot_run" and additionally attest the per-step verification methods bound into the run receipt (oversight evidence for autonomous multi-step runs). The machine counterpart of /ai-act. Optional ?org= stamps a subject organisation. Factual evidence — never a declaration of conformity.
curl -X POST "https://throndar.ai/api/v1/evidence?org=Acme%20Inc" \
-H "content-type: application/json" \
--data @proof.jsonResponse (abridged)
{
"schema": "throndar-ai-provenance-record",
"schema_version": 1,
"generated": 1782000042,
"subject": { "organisation": "Acme Inc" },
"attested": {
"signed": true,
"signer_recognized": true,
"answer_sha256": "…",
"algorithms": ["ML-DSA-87 (FIPS 204) answer receipt"],
"governance_flag": "PASS",
"council_grounded": true,
"signed_at": 1782000000,
"receipt_key_id": "0986d89fa3c74566",
"question_attested": true,
"question_binding": "entire-input",
"quote_attested": null
},
"ai_act_support": [ /* published obligation mapping */ ],
"proof": { /* the embedded, re-verifiable proof bundle */ },
"disclaimer": "Not a declaration of conformity, not a certification, not legal advice. …",
"notes": [ "This record is a CONTEXTUAL WRAPPER, not a new signature. …" ]
}The only cryptographic guarantee is the embedded proof; every summary field is recomputable from it. A bundle that doesn't verify still returns a record — it honestly reports signed: false. question_attested and quote_attested are true, false or null (none carried): signed: true beside question_attested: false means only the answer is evidence, and the record's notes say why. To re-verify a record, post the file itself to /api/v1/verify, load it at /verify/offline, or run the CLI on it.
/api/provenance/pubkeyThe published ML-DSA-87 answer-receipt public key(s). Returns an array so historical key_ids keep resolving across rotations. Cached one hour.
curl https://throndar.ai/api/provenance/pubkey{
"algo": "ML-DSA-87",
"context": "throndar-provenance-v1",
"configured": true,
"keys": [
{ "key_id": "0986d89fa3c74566", "public_key_hex": "…",
"context": "throndar-provenance-v1", "algo": "ML-DSA-87" }
]
}More public endpoints
- GETThe signed tree head of the append-only answer log (RFC 6962 / Certificate-Transparency structure);
/api/transparency/ledger/inclusion,/consistencyand/historyreturn the proofs to check a leaf is included and that history wasn't rewritten. Human view: /transparency/ledger.Verifying independently? Take thetree_sizeandroot_hashyou check a proof against from the signed tree head (the ML-DSA-87signed_tree_head, verified under contextthrondar-sth-v1) — never from an unsigned proof response, whose size/root a server could set freely. The size is only meaningful as part of the signed(tree_size, root)pair. - GETThe Cryptographic Bill of Materials — every primitive in use mapped to its standard and role (CycloneDX). Human view: /pqc.
/api/cbom
Errors & limits
400 — body isn't valid JSON.
413 — payload over 2 MB.
422 — not a recognised Throndar bundle (or too many transcript turns).
429 — rate limit (≈40 requests/min per IP; retry-after header).
All POST endpoints accept OPTIONS preflight and send access-control-allow-origin: *, so they work directly from a browser.
Verify in your browser · AI Provenance Record · Public ledger