Blockchain Anchoring — prove a document existed, without being trusted
Anyone can claim a file is unchanged. An anchor lets a third party check it — against Bitcoin, years later, without asking LedgerFlow anything.
A partner, merchant or internal system submits a file through the external API. LedgerFlow takes its
cryptographic fingerprint and anchors that fingerprint into the Bitcoin blockchain via
OpenTimestamps, then hands back a portable .ots proof.
The file never leaves the deployment — only 32 bytes of hash do. The proof outlives the relationship: it is verified with open-source tooling against the public blockchain, so it keeps working even if this platform, this company and these servers are gone.
That independence is the entire value. Evidence you have to ask the vendor to confirm is not evidence — it is a reference. This is proof a counterparty, an auditor or a court can check without our cooperation, our uptime, or our continued existence.
How an anchor is made — submit, check, stamp, prove
The submitter hashes and encodes the file (left), LedgerFlow validates and records it (middle), and OpenTimestamps commits the fingerprint into a Bitcoin block (right) — after which the proof comes back and stands on its own.
- Submit — one authenticated
POST: file name, MIME type, the base64 payload, and the submitter's own SHA-256 of it. - Check — the server re-hashes what it actually received and compares. Any disagreement aborts the submission entirely.
- Stamp — the 32-byte digest (never the file) is queued to the OpenTimestamps calendar, which aggregates thousands of digests into one Bitcoin transaction. Anchoring costs a fraction of a cent per proof because everyone shares the block space.
- Prove — when the block confirms, the proof is upgraded, the block height is recorded, and the
.otsfile becomes downloadable — and emailable to its owner.
The hash custody chain
Most systems hash whatever arrives and call it proof — which silently anchors corrupted bytes if anything went wrong in transit. Anchoring a damaged file is worse than not anchoring at all: you now hold durable, verifiable proof of the wrong thing. LedgerFlow makes the submitter commit first:
- You state the fingerprint of the file you are sending.
- The server computes the fingerprint of the bytes it actually received.
- They must match. If they do not, the submission is rejected outright — nothing is stored, nothing is anchored, no quota is consumed — and both values are returned so the caller can tell a transport problem from a client-side bug.
On an accepted anchor both values are kept, and the platform re-asserts that agreement at rest. The result is an unbroken evidential line from the submitter's own machine to a Bitcoin block.
What a proof proves — and what it does not
Being precise here is what makes the evidence credible in a dispute.
It proves that these exact bytes existed no later than a specific Bitcoin block. One byte changes and the fingerprint changes and the proof no longer matches. No one — not the submitter, not LedgerFlow, not a regulator — can backdate a block.
It does not prove who wrote the file, that its contents are true, or that it is original. It is existence and integrity at a point in time, not authorship or authenticity.
Typical uses: settlement and reconciliation files, statements, signed agreements, KYC evidence packs, model or configuration snapshots, audit exports — anything where "this is what it said on that day" is the question that matters.
Five calls — the whole integration
External parties reach anchoring on the dedicated tenant-facing API surface — plain HTTPS and JSON, no SDK, one bearer token. Internal operators see the same anchors through the admin pages.
| Call | What it does |
|---|---|
anchor_submit |
Anchor a payload — returns the anchor id and the server-computed hash |
anchor_list |
The caller's own anchors, newest first, filterable by status |
anchor_get |
Full detail: status, timestamps, Bitcoin block height, both hashes |
anchor_proof |
The .ots proof file, base64 — for offline verification |
anchor_verify |
Re-hash supplied bytes against the stored fingerprint |
An anchor moves pending → submitted → confirmed; a submission that the calendar rejects lands on
failed with a message. There is no webhook — poll anchor_get (hourly is ample; Bitcoin
confirmation takes hours, not seconds).
Every 64-bit id is returned as a JSON string, so integrations in JavaScript and other float64 languages cannot silently corrupt it.
Limits and safeguards
Anchoring is an authenticated, quota'd, rate-limited endpoint that accepts large bodies — so it is fenced on every axis:
- 10 MB per payload, enforced in the API; the edge caps the HTTP body independently.
- 20 anchors per account per UTC day, serialised per owner so concurrent submissions cannot overshoot the quota.
- Rate and connection limits per client IP at the proxy, on a dedicated zone rather than the general API zone.
- Notifications only ever go to the account's own address — a submitter cannot direct platform-signed mail anywhere else, so the endpoint can never be used as an authenticated relay.
- Rejections cost nothing — an invalid submission stores no row, consumes no quota, and creates no anchor.
Ownership and privacy
Every anchor belongs to the account that created it, enforced by record-level security and by an ownership check on each call. Asking for someone else's anchor and asking for one that does not exist return the same answer — so the API never even confirms that another party's anchor exists. Competitors sharing your platform cannot probe each other's activity.
Only the fingerprint travels. The payload is never sent to the calendar, to Bitcoin, or to any third party, and it is never attached to the confirmation email — that carries the proof and a small JSON descriptor only.
The payload is retained inside the deployment so a later anchor_verify can re-check it. A hash
protects integrity, not confidentiality: short, guessable content can be brute-forced from its
hash, so treat anchoring as tamper-evidence, not as a privacy control.
Verify it yourself — the part that makes it evidence
A proof that only LedgerFlow can check is not proof. Anyone holding the file and the .ots can
verify it with the open-source client, against the public blockchain:
pip install opentimestamps-client
shasum -a 256 report.csv # must equal the anchored fingerprint
ots verify report.csv.ots # → "Bitcoin block N attests existence as of <date>"
The client hashes the file, walks the proof up to the Bitcoin merkle root, and checks that root against the chain — through public Electrum servers by default, or against your own full node. Alter the file and the first step fails; forge the proof and the second does. Neither step involves LedgerFlow, which is precisely the point: the evidence does not depend on the platform that produced it.
Two anchors, one pipeline
LedgerFlow anchors two different things through the same proven machinery:
- The balance chain — on a schedule, the platform hashes every account's chained row hash into a single root and anchors that, making the ledger's own history tamper-evident. Nobody submits it; it is the platform proving itself.
- Payload anchoring (this page) — an authenticated party submits arbitrary content and anchors it on demand, owning the result.
Below the point where a fingerprint is produced, everything is shared: the same anchor log, the same
queue, the same calendar, the same proof upgrade and diagnostics, the same .ots export. One
hardened path, two sources of truth — which is why a new anchoring use case costs a digest source
rather than a new subsystem.