The TTTPS Provenance API seals any content hash (an AI agent output, a document, an arbitrary payload) into a tamper-evident receipt with an operator-independent timestamp. A receipt attests to WHEN a digest was seen, its ORDER, and TAMPER-EVIDENCE: it does not assert that the underlying content is correct. The raw payload is never sent or stored, only its sha256 digest.
1,000 free seals per key · no card, no approval gate · POST /v1/keysAggregate seal volume. Provenance attests when/order/tamper-evidence, not correctness.
The kernel is open and the contracts are public, so anyone can recompute what you got. Sealing takes that reproducible result and fixes it to a moment, tamper-evident afterwards. One establishes what is true; the other establishes when it existed. Everything below also works as plain HTTP in the reference.
Checked against the bound proved in Lean 4 for that metric. No key needed, nothing recorded.
Supply your own digest to bind the receipt to a full run record (cohort, model version, fold) without transmitting any of it.
Nothing but this digest is sent. Compute it however you like, for example
sha256sum myfile.txt or
hashlib.sha256(payload).hexdigest().
Creates a timestamped, tamper-evident receipt. This is the only step that writes a permanent record and spends one seal from your quota.
Runs with no key at all, which is the point: whoever you hand a receipt to can re-check it without an account here.
Values you enter are used to answer the request and discarded. Only a SHA-256 digest is stored, and a receipt attests when a result existed and that it has not changed since, not that it is scientifically correct.
Everything below is plain HTTP against the production API. No install, no account approval, no card. Paste the three commands in order and the last one prints a receipt anyone can re-check.
curl -X POST https://kpp.kenosian.com/v1/keys \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com","use_case":"trying tttps"}'
The response carries api_key. It is shown once and never stored on our side, only its
digest, so keep it. It comes with a thousand free seals.
sha256sum myfile.txt # or: shasum -a 256 myfile.txt
curl -X POST https://kpp.kenosian.com/v1/anchor \
-H 'Content-Type: application/json' \
-H 'X-API-Key: <your api_key>' \
-d '{"content_hash":"<the 64-hex digest>"}'
You compute the digest yourself on purpose. The file never leaves your machine: this API receives
the hash and nothing else, so there is no copy of your content here to leak, subpoena or lose. That
is also why we cannot hash it for you. The response carries receipt_id and an absolute
verify_url you can paste straight into a browser. If you would rather send the key in
the body than as a header, {"content_hash":"...","key":"..."} works identically.
curl 'https://kpp.kenosian.com/v1/verify?receipt_id=<your receipt_id>'
Verification is open, so whoever you hand a receipt to can check it without credentials and without
asking you for anything. A tampered or backdated receipt comes back as verified: false
with the reason, rather than as an error. For an artifact that has to survive offline review, exchange
the receipt for a signed certificate at POST /v1/export/certificate, which a third party
checks against the public key published in the issuer DID document.
Every integration seals its framework's output digest through the same endpoints documented below. This table is the only place integration status is published, so it cannot fall out of step with another page. Three packages are built and verified with their upload to PyPI still pending.
| Framework | Status | Install | What it does |
|---|---|---|---|
| smolagents | Native | ttt-mcppip install smolagents-openttt |
Connects over MCP with no adapter package at all. A published step callback is the MCP-free alternative. |
| LangChain | Published | pip install langchain-openttt |
Callback handler. Seals each LLM call's output hash. |
| LiteLLM | Published | pip install litellm-openttt |
CustomLogger with sync, async and fail-open paths. |
| LlamaIndex | Published | pip install llamaindex-openttt |
BaseCallbackHandler covering chat and completion. |
| vLLM | Published | pip install vllm-openttt |
ASGI middleware. Carries W3C traceparent into the receipt. |
| Ollama | Upload pending | ollama-openttt |
Reverse proxy. Seals the final NDJSON line of a stream. |
| DeepEval | Upload pending | deepeval-openttt |
BaseMetric. Cross-checks the receipt against the backend. |
| Ragas | Upload pending | ragas-openttt |
SingleTurnMetric. Carries receipt id through the sample. |
Interactive reference generated from this API's OpenAPI spec, so the list below is the live surface rather than a hand-kept copy of it: key issuance, anchoring, verification, the per-key receipt dashboard, the public counter and its badge, and offline certificate export with the issuer DID document that certificates are checked against. Verification is reachable two ways, as a POST with a JSON body or as a GET with a receipt_id query parameter, which is the clickable form returned in verify_url.
Two field-naming details worth stating plainly, since integration code has gotten this wrong before:
POST /v1/anchor returns the digest under a field literally called receipt
(alongside receipt_id, content_hash, time, time_source,
and verify_url), not chain_digest, that name doesn't exist in this API.
There is also no fail_open field anywhere in a server response: fail-open is client-side
behavior, a caller that catches a PoT-backend error and falls back locally rather than blocking, not
something the server reports about itself. The full request/response schemas below are generated
directly from this API's OpenAPI spec, so they reflect the real field names, not a paraphrase.
The aggregate counter shown at the top of this page is a read-only public endpoint, and it is
documented below alongside the rest, together with the Shields endpoint that renders it as a badge.
On keys: anchoring accepts yours either as an X-API-Key header or as a key
field in the JSON body, whichever your client makes easier. The receipt dashboard takes the header
only, and it is the one endpoint that refuses to answer without a key at all, because what it returns
is the receipt history belonging to that single key and there is no anonymous version of that.
Verification is open to everyone and needs no key, which is the point: a receipt is worth something
precisely because the person you hand it to can check it without your permission.