Docs · SDKs
The same four operations, in two languages.
Both libraries are thin. They walk a folder, hash each file in place, build a Merkle tree, and send the root — nothing else. The two are bit-for-bit compatible: both are held in continuous integration to the same published conformance vectors, so a folder anchored from Python verifies from Node. The browser implements the same algorithm — orphograph-merkle-v1-rfc6962 — and a receipt issued through any of them verifies with this service gone.
Neither package is on a public registry yet, so both install from source. If you would rather not take a dependency at all, the HTTP API is plain JSON over HTTPS and the libraries add nothing you cannot do with a request client.
Python
Python 3.9 or newer. Standard library only — no third-party dependencies at runtime.
pip install "git+https://github.com/Orphograph/Orphograph#subdirectory=sdk-python"
from orphograph import anchor_folder, verify_folder
result = anchor_folder("/path/to/folder", label="Case file 2026-05-20")
receipt_id = result["receipt_id"]
root_hex = result["root_hex"]
# Later, from a clean machine, given only the folder and the id:
assert verify_folder("/path/to/folder", receipt_id) is True
The package also installs the orphograph command described in the command-line reference. Full source and README: sdk-python.
Node and TypeScript
Node 20 or later. Zero runtime dependencies — node:crypto, node:fs, node:http, node:https, and node:path only.
git clone https://github.com/Orphograph/Orphograph.git
cd Orphograph/sdk-node
npm install
npm install /path/to/Orphograph/sdk-node # from your project
Run npm install inside sdk-node before installing it into your project. The compiled dist/ is not committed and the package's entry point points into it, so that first install is what builds it — a path install against a directory where it has never been run fails with tsc: command not found.
import { anchorFolder, verifyFolder } from "orphograph";
const result = await anchorFolder("/path/to/folder", {
serverUrl: "https://orphograph.com",
apiKey: process.env.ORPHO_API_KEY, // optional
clientLabel: "Case file 2026-05-20",
});
const { receipt_id, root_hex } = result;
const ok = await verifyFolder("/path/to/folder", receipt_id);
Full source and README: sdk-node.
The four operations
Named differently by each language's convention, identical in behaviour.
anchor_folder · anchorFolder
Hash a folder and commit its Merkle root. Returns the receipt id and the root. Optional label and exclude-glob arguments; supplying any exclude replaces the default deny-list rather than extending it.
verify_folder · verifyFolder
Re-walk a folder and compare its recomputed root against a receipt. Returns a boolean.
inclusion_proof · inclusionProof
Fetch the Merkle path proving one named file was part of an anchored set — without disclosing the rest of the folder.
verify_inclusion · verifyInclusion
Check such a proof locally against a file and a root. No network call, which is the point: the recipient of a proof need not trust, or reach, this service.
What crosses the network
The manifest, and nothing else: relative paths, per-file SHA-256 digests, leaf hashes, and the thirty-two-byte root. File contents are streamed through SHA-256 locally in one-megabyte chunks and never transmitted. This is a property of the libraries, not a promise about our servers — you can confirm it by reading either implementation, both of which are short and MIT-licensed.
Paths are transmitted. If a filename is itself sensitive, why filenames are not stored covers what the service retains and what it discards.
Further reading
The HTTP API is the layer both libraries sit on. Webhooks replace polling for confirmation. Folder anchoring by Merkle root explains what a root commits to — and what it does not.