API

Three endpoints, one JSON shape, no SDK, no key and nothing to sign up for. Ten checks a day per address, counted the same whether they come from this page or from your terminal.

One call

curl 'https://check.scador.com/api/check?q=Gazprombank&country=RU'

q is a company name or a 20-character LEI. country is an optional ISO-3166 alpha-2 code; a wrong one is a 400 rather than a filter dropped in silence.

What comes back

{
  "version": 1,
  "query": { "q": "Siemens Aktiengesellschaft", "country": "DE" },
  "verdict": "no-match",
  "subject": {
    "lei": "W38RGI023J3WT1HWRP32",
    "name": "Siemens Aktiengesellschaft",
    "country": "DE",
    "status": "ACTIVE",
    "registrationStatus": "ISSUED"
  },
  "matches": [],
  "ownership": [
    {
      "lei": "W38RGI023J3WT1HWRP32",
      "name": "Siemens Aktiengesellschaft",
      "country": "DE",
      "relation": "self",
      "hops": 0,
      "matches": []
    }
  ],
  "ownershipTruncated": false,
  "checkedAt": "2026-09-19T21:01:06.980Z",
  "sourcesAsOf": {
    "OFAC": "2026-09-19T15:01:03.941Z",
    "EU": "2026-09-19T15:01:03.943Z",
    "UK": "2026-09-19T15:01:03.945Z"
  },
  "id": "z2wuPRQ739vo",
  "permalink": "/c/z2wuPRQ739vo",
  "ogImage": "/c/z2wuPRQ739vo/og.png"
}

Every entry in matches — on the subject, and on each node of ownership — carries the reason it is there:

{
  "source": "OFAC",
  "program": "RUSSIA-EO14024",
  "entryId": "TEST-DOC1",
  "listedAt": "2022-02-24",
  "countries": ["RU"],
  "matchedName": "Gazprombank (Joint-stock Company)",
  "score": 1,
  "basis": "name",
  "why": "name similarity 1.00 (\"gazprombank joint stock company\" ≈ \"gazprombank joint-stock company\") + same country"
}

score is 0…1; anything reported is ≥ 0.85, or an exact LEI equality (1). permalink and ogImage are paths on this host — the shareable page and its card.

basis is lei (an identifier, which cannot be a coincidence) or name (a resemblance, however strong). Only OFAC entries can ever produce basis: "lei": the EU consolidated list and the UK OFSI list publish no LEI at all, so a company that is listed only in Brussels or London is reached by name resemblance and nothing else. Read a name basis on those two accordingly — and read the absence of a match on them as weaker evidence than the absence of one on OFAC.

The five verdicts

  • LISTED listed

    This company itself appears on one of the sanctions lists we hold.

  • PROXIMITY proximity

    This company is not listed, but a parent, owner or subsidiary within two ownership hops is.

  • NO MATCH no-match

    Nothing in this company or its GLEIF ownership matched the lists we hold. That is not the same as being clean.

  • UNRESOLVED unresolved

    The name fits several companies in GLEIF, so nothing was screened yet. Pick the one you meant.

  • NO LEI no-lei

    GLEIF knows no company by this name, so only the name itself was screened — with no ownership at all. The weakest answer this tool gives.

There is deliberately no clear. This service screens three lists and GLEIF ownership; that is never proof that a company is clean.

The other endpoints

EndpointWhat it does
GET /api/check?q=&country=The check. Costs one against your daily quota.
GET /api/lei/{lei}The same check addressed by identifier. Never answers unresolved — a LEI cannot be ambiguous.
GET /healthWhich lists this instance holds, when each last changed, whether GLEIF answered last time, and the running build. No quota. See it now.

The check endpoints answer GET only. HEAD, POST, PUT, PATCH and DELETE are all refused with a JSON 405 and Allow: GET — HEAD in particular, because SvelteKit would otherwise serve it by running the GET and dropping the body, which spends a check to produce no answer.

Limits

CallerChecksKeyed onResets
Anyone10 a dayIP address (IPv6: the /64)00:00 UTC

Every metered answer carries what you have left — a 429 included:

X-RateLimit-Scope: anonymous
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9
X-RateLimit-Reset: 2026-09-20T00:00:00.000Z
Retry-After: 10734          (only on a 429 or a 503)

And every 429 names the budget that ran out:

anonymous-day   the day's ten for this address are spent

An over-limit request still counts and is not refunded; a request that fails validation costs nothing. There is no account and no key: the address you call from is the whole identity, so a shared office address shares one day's ten.

POST /api/v is the page-view beacon used by this site — it is not part of the API, it spends none of your checks, and it stores nothing you can read back.

When it refuses

400  { "error": "bad_request",       "hint": "q: Too small: expected string to have >=1 characters" }
404  { "error": "not_found",         "hint": "GET /api/check?q=…, GET /api/lei/<LEI>, GET /health — see /docs" }
405  { "error": "method_not_allowed", "hint": "GET /api/check — HEAD would spend a check for no answer" }
429  { "error": "rate_limited",      "scope": "anonymous-day",
      "limit": 10, "remaining": 0, "resetAt": "2026-09-20T00:00:00.000Z",
      "hint": "You have used your 10 free checks for today. The counter starts again at 2026-09-20T00:00:00.000Z." }
503  { "error": "gleif_unavailable", "hint": "GLEIF API unavailable, retry later" }

Every failure has the same shape — error is what code branches on, hint is for a human reading a terminal. One answer on this host is deliberately not JSON: the CSRF refusal below, which SvelteKit emits before this app runs.

CSRF

A JSON POST needs no Origin header — send Content-Type: application/json and it is accepted from anywhere, which is what an integration does. A form-encoded POST must come from this origin: browsers send the header by themselves, and a scripted form post that omits it is refused with 403.

That refusal is the framework's, not this app's: it happens before any route runs, so it does not carry the {error, hint} shape. It is text/plain — the body is literally Cross-site POST form submissions are forbidden — unless the request sent Accept: application/json exactly, in which case it is {"message": "…"}. Either way the fix is the same: send the form from this origin, or send JSON.