Clickwrap, evidenced
Prove what your users agreed to.
Horkos blocks your app until the user accepts the current agreement version, records the acceptance synchronously, and seals an immutable evidence record — content hash, timestamp, and the exact terms they were shown.
Author and publish
Write your terms and publish a version. Publishing canonicalises the content, computes a SHA-256 hash, and freezes it — the version your users accepted stays provable forever.
Gate your app
Drop in the SDK. It asks Horkos what this user still owes and blocks until they accept. If anything fails, it fails closed — nobody is ever waved past an unrecorded agreement.
Keep the evidence
Every acceptance is written synchronously, then sealed into an immutable record: the exact hashed content, the server timestamp, the request context, and what the subject was shown.
Integration
Two script tags and a token endpoint
Your backend mints a short-lived signed token for the user it has already authenticated. Horkos stores only your public key — your private key never leaves your infrastructure.
<script src="https://cdn.gethorkos.com/v1/horkos.js"></script>
<script>
Horkos.init({
tokenProvider: () => fetch("/api/horkos-token").then((r) => r.text()),
});
Horkos.getClient().gate({ onDecline: () => session.signOut() });
</script>The record
Evidence that says what it knows
Each acceptance produces a machine-readable record and a PDF. Both state which facts the server generated, which came from a verified token, which the infrastructure observed, and which the client merely claimed — so an auditor can weigh them correctly.
Bound to the exact bytes
The artifact carries the canonical content the hash covers and re-verifies it. Tampered content cannot produce a passing record.
Declines are recorded too
When an optional agreement is refused, that is a real, sealed event — proving consent was never given is as important as proving it was.
Subjects stay opaque
Horkos identifies users by an opaque id you control. No names, no emails — nothing you did not already hold.
Exportable on request
A data-access request produces a scoped, hash-verified export of everything recorded for one subject.
Start with test mode
Test-mode acceptances are unlimited and never billed, so you can wire the whole flow up before a single live user sees it.