Docs · Getting started
Quickstart
A lookup needs nothing but a URL. A proof needs a key pair and one endpoint on your server.
Look up a domain
No key, no account, no headers. Registry outcomes come back with 200 and the result is in status, never in the HTTP code. A 4xx or 5xx means the request failed on the way — rate limit, missing parameter, infrastructure — and carries no result.
curl 'https://api.registry.liorith.net/check?domain=demo.liorith.net'{
"status": "registered",
"result": "verified_registry",
"domain": "demo.liorith.net",
"check_url": "https://registry.liorith.net/check/demo.liorith.net",
"checked_at": 1756800000000,
"registered": true,
"blocked": false,
"proof_checked": false,
"summary": "demo.liorith.net ist in der Liorith Registry eingetragen ...",
"does_not_imply": ["..."],
"site": {
"id": "demo",
"name": "Liorith Demo",
"canonical_domain": "demo.liorith.net",
"match_type": "exact",
"status": "active",
"category": "SysTest",
"legal": true
},
"last_verified_at": 1756799400000,
"last_status": "verified_signed"
}Branch on status or on the two booleans. Do not parse the summary text and do not branch on result — that field is the old vocabulary and is kept only so existing clients keep working.
Prove that a request is yours
A proof binds three things together: which site, which host, and when. Your server signs them; the registry checks the signature against the public key stored for your site.
- Generate a key pair
Ed25519. The private key stays on your server and never reaches a browser. The public key goes into the admin panel under your site.
shnpx liorith-verify keygen - Store the private key
A PEM has line breaks, which a Compose
.envcannot carry. Either keep the PEM as-is in a real secret store, or pass it base64-encoded and decode it in your code..env.localiniLIORITH_REGISTRY_SITE_ID=your-site-id LIORITH_REGISTRY_PRIVATE_KEY_B64=LS0tLS1CRUdJTi... - Add a signing endpoint
It signs for the host the request actually arrived on and redirects to the registry. Nothing secret leaves the server — only site, host, timestamp, nonce and signature travel in the URL.
app/api/verify-me/route.tstsimport { signProofV2, proofToUrl } from 'liorith-registry-sdk'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; function privateKey(): string | undefined { const b64 = process.env.LIORITH_REGISTRY_PRIVATE_KEY_B64; if (b64) return Buffer.from(b64, 'base64').toString('utf-8'); return process.env.LIORITH_REGISTRY_PRIVATE_KEY; } export async function GET(req: Request) { const siteId = process.env.LIORITH_REGISTRY_SITE_ID!; const key = privateKey()!; // Hinter einem Proxy steht der echte Host in X-Forwarded-Host. const host = req.headers.get('x-forwarded-host') ?? req.headers.get('host')!; const params = signProofV2(siteId, host, key); return Response.redirect(proofToUrl(params)); } - Link to it
Every visit signs a fresh proof. A signed URL is valid for two minutes and for exactly one verification, so it cannot be saved and reused.
html<a href="/api/verify-me">Verify this site</a>
Check it from the terminal
The CLI signs and verifies in one step, which tells you whether the key pair and the registry entry actually match before you wire up a page.
npx liorith-verify verify \
--site your-site-id \
--host your-domain.example \
--key "$(cat private.pem)"verified_signed means everything lines up. Any other value is explained on the status codes page — host_mismatch and no_secret are the two you are most likely to hit first.