Skip to content
Liorith/Registry

Docs · Guides

Legal scope integration

Rendering the list of domains the Liorith Legal Center is responsible for, on a page of your own.

The endpoint

GET/legal?category=…

Public, no key. CORS is open, so a browser can call it directly, and the rate limit is 30 requests per minute per IP. The full field reference lives under Lists & tools; this page is about putting it on a page without getting it wrong.

Responsejson
{
  "entries": [
    {
      "domain": "*.liorith.net",
      "category": "Core",
      "check_url": "https://registry.liorith.net/check/liorith.net"
    }
  ],
  "categories": ["Core", "Legal", "SysTest"],
  "count": 5,
  "generated_at": 1788647582078,
  "notice": "This list names the domains the Liorith Legal Center is responsible for. …"
}

Fetching it

The endpoint answers with Cache-Control: no-store, like every list endpoint, so that a caller always sees the current state. The legal scope changes rarely, though. Cache it on your side for a few minutes: that is well inside the rate limit and survives a short outage on our end.

app/legal/page.tsxts
const ENDPOINT = 'https://api.registry.liorith.net/legal';

export async function fetchLegalScope(category?: string) {
  const qs = category ? `?category=${encodeURIComponent(category)}` : '';
  const res = await fetch(`${ENDPOINT}${qs}`, {
    signal: AbortSignal.timeout(3000),
    next:   { revalidate: 300 },
  });
  if (!res.ok) throw new Error(`legal: HTTP ${res.status}`);
  return res.json();
}

Four things that matter

  1. On failure, claim nothing

    The tempting shortcut is to fall back to an empty list. Your page then states that the Legal Center is responsible for no domain at all, which is a false statement, on a legal page of all places. Show the last known list with its date, or say plainly that the list cannot be reached right now.

  2. Wildcards are display values, not matchers

    A domain may read *.liorith.net or **.liorith.net. A leading *. covers subdomains only, **. covers the root and its subdomains, and a bare domain covers both as well. Do not reimplement that matching to answer whether some host falls under the scope. Ask /check?domain=… and read registered. The check_url in each entry already points at the human-readable form of exactly that, with the wildcard prefix stripped.

  3. Scope is not operating state

    There is deliberately no status in entries. A domain can be inside the legal scope and suspended at the same time; those are different questions, and showing them in one table invites reading one as the other. If you need both, use /domains?legal=true, which carries the state.

  4. An entry may have no category

    Not every site is categorised. Such entries appear in entries with an empty category, are absent from categories, and cannot be selected through ?category=. Group them under a heading of your own, the way our page does with uncategorised.

Building the filter

categories holds every category present in the scope and does not shrink when ?category= narrows the entries. That is what makes it usable as a filter: the options stay put, so a visitor can leave a selection again. Categories used only by sites outside the legal scope are absent, so every option you render returns at least one entry.

count, by contrast, refers to the filtered set. If you want to show both, label them apart.

There is no SDK helper for this endpoint. liorith-registry-sdk covers proofs, lookups and badges; a wrapper around a single fetch would be a dependency to maintain for no gain.