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: truemeans “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
},
"signerRecognized": true
},
"signerRecognized": true,
"disclaimer": "verdict.overallOk means the bundle's embedded signatures verify ..."
}councilGrounded: falseflags 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. All six proof kinds are auto-detected. 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"
},
"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.
/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