HLA-Verify

API reference v0 · private preview

Three endpoints, one deterministic engine

Every response is computed from a pinned IPD-IMGT/HLA release and carries that release in the payload. Every example on this page is real output from the engine at release 3.65.0 — not illustrative JSON.

Base URL, auth and versioning

Base URLhttps://api.hlaverify.com
AuthX-API-Key: <your key> on every request
Content typeapplication/json for POST bodies
Release pinningPer key. The active release is returned as release in every response.
Interactive docsOpenAPI at /docs on your deployment
Preview status. The engine, endpoints and response shapes below are implemented and tested. The hosted endpoint at api.hlaverify.com is provisioned per pilot rather than open to self-serve signup — request access and we will issue a key, or run the container yourself.

POST /v1/verify

Takes arbitrary free text — a typing report, an EHR fragment, a note, a model's answer — and returns a verdict for every allele-shaped token it contains.

Body: {"text": string}, up to 200,000 characters.

$ curl -s https://api.hlaverify.com/v1/verify \
    -H 'content-type: application/json' -H "x-api-key: $KEY" \
    -d '{"text": "Donor typing: A*0101, B*15:504:01, DRB1*14:06, DQB1*05:03:01G.
                Assistant suggested DQB1*05:03:26:99."}'
{
  "release": "3.65.0",
  "clean": false,
  "counts": { "valid": 2, "deleted": 1, "group": 1,
              "fabricated_group": 0, "hallucinated": 1 },
  "tokens": [
    { "token": "A*0101",
      "status": "deleted",
      "note": "was assigned once, no longer current — see successor",
      "successor": "A*01:01:01:01",
      "current_2field": "A*01:01",
      "g_group": "AMBIGUOUS",
      "flags": ["deprecated_name"] },
    { "token": "B*15:504:01",
      "status": "valid",
      "current_2field": "B*15:504",
      "g_group": "NONE" },
    { "token": "DQB1*05:03:01G",
      "status": "group",
      "note": "a G/P group name in this release" },
    { "token": "DQB1*05:03:26:99",
      "status": "hallucinated",
      "note": "no such name in any release back to 1.05.0 — fabricated" },
    { "token": "DRB1*14:06",
      "status": "valid",
      "current_2field": "DRB1*14:06",
      "g_group": "AMBIGUOUS" }
  ],
  "attribution": "Computed from IPD-IMGT/HLA …"
}

Guardrail pattern: gate on clean. It is true only when hallucinated, fabricated_group and deleted are all zero. Tokens are returned sorted by name.

POST /v1/normalize

Takes a list of reported typing strings from any era and returns each one resolved to its current name, its 2-field reduction, its G group and its flags. This is the batch workhorse: a LIMS column in, a clean column out.

Body: {"typings": string[]}, up to 5,000 entries per call.

$ curl -s https://api.hlaverify.com/v1/normalize \
    -H 'content-type: application/json' -H "x-api-key: $KEY" \
    -d '{"typings": ["A*0101", "B*15:504:01", "DRB1*1406", "C*07:01:01:01"]}'
{
  "release": "3.65.0",
  "rows": [
    { "reported": "A*0101",        "current_name": "A*01:01",
      "allele_2field": "A*01:01",  "g_group": "AMBIGUOUS",
      "flags": ["deprecated_name"] },
    { "reported": "B*15:504:01",   "current_name": "B*15:504:01",
      "allele_2field": "B*15:504", "g_group": "NONE",      "flags": [] },
    { "reported": "DRB1*1406",     "current_name": "DRB1*14:06",
      "allele_2field": "DRB1*14:06", "g_group": "AMBIGUOUS",
      "flags": ["deprecated_name"] },
    { "reported": "C*07:01:01:01", "current_name": "C*07:01:01:01",
      "allele_2field": "C*07:01",  "g_group": "C*07:01:01G", "flags": [] }
  ]
}

g_group is AMBIGUOUS when a lower-resolution name spans more than one G group, and NONE when the allele belongs to no G group. Unresolvable input returns current_name: "UNRESOLVABLE" rather than a guess.

GET /v1/allele/{name}

The facts for one name: G group, P group, serology, first release, confirmation status, null-allele marking. Lower-resolution names return the size of the set they cover and a sample of members.

$ curl -s "https://api.hlaverify.com/v1/allele/A*01:01:01:01" -H "x-api-key: $KEY"

{
  "release": "3.65.0",       "name": "A*01:01:01:01",
  "status": "assigned",     "confirmed": true,
  "g_group": "A*01:01:01G", "p_group": "A*01:01P",
  "first_release": "3.00.0",
  "serology": { "unambiguous": ["1"] }
}
$ curl -s "https://api.hlaverify.com/v1/allele/A*01:01" -H "x-api-key: $KEY"

{
  "release": "3.65.0", "name": "A*01:01", "status": "valid_prefix",
  "members_count": 303,
  "members_sample": ["A*01:01:01:01", "A*01:01:01:02N", "A*01:01:01:03", "…"]
}

Deleted names return status: "deleted" with a successor. Unassigned but parseable names return 404; unparseable names return 404 with a parse message. Names are URL-path segments, so * and : may need encoding depending on your client.

GET /healthz

Liveness plus the release the process is currently pinned to. Unauthenticated. Use it to assert in your own CI that the release under you has not moved.

{ "ok": true, "release": "3.65.0", "uptime_s": 4192 }

Errors

StatusWhen
401Missing or unrecognized X-API-Key
404The name is not assigned in the pinned release, or is not a parseable HLA allele name
422Body failed validation — text over 200,000 characters, over 5,000 typings, wrong shape
429Rate limit for the key exceeded

Note the deliberate asymmetry: /v1/verify never fails on bad allele names — a fabricated name is a result, not an error. Only /v1/allele/{name} 404s, because there is nothing to report.

Self-hosting

The service ships as a container. For pilots that cannot send anything outside their own network, run it yourself; the reference files are fetched from the official source at startup and MD5-verified, and no request content leaves the process.

# build and run the verification service locally
$ docker build -t hla-verify -f sci_envs/service/Dockerfile .
$ docker run -p 8000:8000 \
    -e HLA_VERIFY_TAG=v3.65.0-alpha \
    -e HLA_VERIFY_API_KEYS="key-one,key-two" \
    hla-verify

# /docs is the OpenAPI UI; / is the interactive demo page
Environment variableEffect
HLA_VERIFY_TAGThe IPD-IMGT/HLA release tag to pin. Default v3.65.0-alpha.
HLA_VERIFY_API_KEYSComma-separated keys. Unset means open — demo mode only, never for a deployment reachable from outside.
Licence. The service code is under PolyForm Noncommercial 1.0.0 — free to read, evaluate and use noncommercially; commercial use needs a licence. The benchmark, harness and adapters around it are Apache-2.0. See Trust.