Skip to content
Liorith/Registry

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.

Requestsh
curl 'https://api.registry.liorith.net/check?domain=demo.liorith.net'
Responsejson
{
  "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.

  1. 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.

    sh
    npx liorith-verify keygen
  2. Store the private key

    A PEM has line breaks, which a Compose .env cannot carry. Either keep the PEM as-is in a real secret store, or pass it base64-encoded and decode it in your code.

    .env.localini
    LIORITH_REGISTRY_SITE_ID=your-site-id
    LIORITH_REGISTRY_PRIVATE_KEY_B64=LS0tLS1CRUdJTi...
  3. 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.tsts
    import { 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));
    }
  4. 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>
Never sign in the browser. Signing needs the private key, and anything shipped to a client is public. If the key leaks, anyone can produce proofs for your site until you rotate it in the admin panel.

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.

sh
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.