Integrate in an afternoon.
One endpoint on your backend, one script tag in your app. Horkos decides what is owed; your code never has to.
Step one — your backend
Mint a short-lived token
Generate an RSA key pair and register the public half in your application's settings. Your backend signs a token for the user it has already authenticated; the token is valid for at most five minutes and is bound to your application.
import { HorkosServer } from "@horkos/server";
const horkos = new HorkosServer({
applicationId: process.env.HORKOS_APPLICATION_ID,
privateKey: process.env.HORKOS_PRIVATE_KEY, // never leaves your infrastructure
audience: "https://api.gethorkos.com",
});
// Your route, for a user YOU have already authenticated.
app.get("/api/horkos-token", requireLogin, (req, res) => {
res.send(horkos.createSubjectToken({ subject: req.user.id }));
});Step two — your app
Gate the page
The modal renders in your brand, blocks until the user acts, and records the acceptance before it releases. If it cannot record, it keeps the user gated and says so.
<script src="https://cdn.gethorkos.com/v1/horkos.js"></script>
<script>
Horkos.init({
tokenProvider: () => fetch("/api/horkos-token").then((r) => r.text()),
});
// Blocks until every required agreement is accepted. Resolves with what was
// recorded; rejects rather than resolving empty if anything fails.
Horkos.getClient().gate({ onDecline: () => session.signOut() });
</script>API
The surface you'll use
What must this subject accept? Returns only unmet requirements.
Record an acceptance or an optional decline. Idempotent per subject and version.
Tenant-wide audit list, newest first.
Short-lived signed links to the sealed artifacts.
Start a subject data-access export.
Every route is documented in the OpenAPI contract, and the SDK versions are published to immutable URLs — /sdk/1.0.0/horkos.js never changes once released, while /v1/horkos.js tracks the current version so you can roll forward or back without redeploying.
Try it in test mode
Create an application in TEST and wire the whole flow up without touching your quota.