Developer API

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.

No authCORS: *StatelessOffline-checkableRate-limited 40/min

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.

POST/api/v1/verify

Verify 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.json

Response

{
  "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.

CI / CDthrondar-verify@v1

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 key

Or 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).

POST/api/v1/evidence

Turn 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.json

Response (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.

GET/api/provenance/pubkey

The 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

  • GET/api/transparency/ledger
    The signed tree head of the append-only answer log (RFC 6962 / Certificate-Transparency structure); /inclusion, /consistency and /historyreturn the proofs to check a leaf is included and that history wasn't rewritten. Human view: /transparency/ledger.Verifying independently? Take the tree_size and root_hash you check a proof against from the signed tree head (the ML-DSA-87 signed_tree_head, verified under context throndar-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.
  • GET/api/cbom
    The Cryptographic Bill of Materials — every primitive in use mapped to its standard and role (CycloneDX). Human view: /pqc.

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.

What a verified answer means. A green verdict attests origin and integrity — this exact text came from Throndar and hasn't been altered — not the factual accuracy of the answer. Algorithm names denote the public standards the primitives are based on (ML-DSA-87 / FIPS 204, ML-KEM-1024 / FIPS 203; Falcon / FN-DSA, FIPS 206 forthcoming), not a FIPS-140 / CMVP validation.

Verify in your browser · AI Provenance Record · Public ledger