← PRODUCT
PRODUCT · PROVE

GateAttest: published Merkle anchors

A daily Merkle root over all Decision Receipts, published for good and committed to Bitcoin. Once confirmed, no receipt can be backdated.

DECISION RECEIPTinput hasha1b2…9flist snapshotsha256:2b44…coverage9 dimensionspolicybroker-v1.1decisionREVIEWed25519signatureanyoneverifiesanyone with the public key can check it

Start free sandboxTalk to us50 screenings a month free, no card.

On this page

GateAttest in simple terms

Once a day, one short fingerprint of every receipt so far is published and also written into the Bitcoin blockchain.

After that, nobody, including us, can produce an older-looking receipt and slip it in, because it would not match the fingerprint published that day.

IN EVERYDAY TERMSThink of posting yourself a sealed letter. The postmark proves the date, and there is no way to get an earlier postmark later.

What it does

Once a day, every Decision Receipt written so far is hashed into an RFC 6962 Merkle tree and the root, a single 32-byte number, is published at /attestations, where it is never rewritten. Each receipt becomes one leaf of that tree.

Anyone holding a receipt can ask /api/public/attestations/{receiptId} for its inclusion proof: the sibling hashes that fold the receipt up to the published root. The endpoint needs no API key, because the party being audited should not control whether the check can run. It returns no tenant data: a leaf is the SHA-256 of a receipt, and a sibling is the SHA-256 of somebody else's.

The receipt verifier runs the whole thing in the browser: it recomputes the leaf from the pasted receipt, folds the proof, and shows the root it reaches so it can be compared with the published list.

Why a broker needs it

A signature shows that a record has not changed since it was signed. It cannot prove the date, because the party holding the signing key can sign anything at any time and put an earlier timestamp inside it. A competent examiner raises this first about any vendor's "tamper-proof" evidence. A published root answers it with arithmetic. The number was published before the deposit in question was made, and no key can make a receipt written afterwards fold up to it.

How it works

The leaf is SHA-256(0x00 || "kytgate.receipt.v1\n" || the canonical receipt JSON without its signature || "\n" || the signature); inner nodes are SHA-256(0x01 || left || right). That is RFC 6962, the Certificate Transparency construction, chosen over the Bitcoin-style tree because the latter duplicates the last node on odd levels and therefore has a known root collision. Batches span all tenants, so one shared public number reveals nothing about any tenant's volumes and can be pinned externally.

A receipt missed by one run is picked up by the next: membership is determined by whether a leaf already exists for it, not by a time window, so nothing falls through a gap.

Try it without an account: Published anchors (live) · Decision Receipt verifier (in-browser, no account) · kytgate-verify: open-source CLI and library, no dependencies.

What it does not do

An anchor proves a receipt existed by the time its root was published and has not changed since. It does not prove the decision was right, and it says nothing about receipts that are NOT in a batch: a root proves what is in it, never what is missing. A root published only by KYTGate is a tamper-evident log, not third-party proof: the useful thing an auditor does with it is record today's root somewhere KYTGate does not control. External pinning (a chain transaction, a timestamping authority) is reported per batch when present and is not claimed when absent.

API

GET /api/public/attestations
{ "algorithm": "rfc6962-sha256", "batches": [
  { "period": "2026-09-11", "seq": 0, "root": "5dc9da79…", "leafCount": 1284, "coversTo": "…" } ] }

GET /api/public/attestations/{receiptId}
{ "anchored": true, "leafIndex": 417, "leafHash": "…",
  "proof": [ "…", "…" ], "batch": { "root": "5dc9da79…", "leafCount": 1284, … } }

Full reference: /docs#attest · OpenAPI 3.1

Start free sandboxRead the API docs Talk to us