---
title: "Coding Readiness Check"
method: GET
path: "/health/coding"
tags: ["health"]
---

# Coding Readiness Check

`GET /health/coding`

## Request

- Base URL: `https://api.accurecord.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.accurecord.io/health/coding`
- Auth: none declared

Can this revision actually CODE, or only pass a health check?

SEPARATE FROM /health/ready ON PURPOSE, and it is the whole point of the endpoint.
`/health/ready` is what the platform routes on: a 503 there pulls the replica out of
rotation, which is why Redis is fail-open there. Reference data being unbuilt is the
opposite shape — it must STOP A DEPLOY, and must never pull a serving replica. Folding
this into readiness would trade a silent accuracy loss for a self-inflicted outage.

So: always 200, nothing routes on it, and the deploy smoke test is the only consumer.
It fails the canary before traffic shifts; a live replica is never affected.

Body is `{"status": ...}` and nothing else TO AN ANONYMOUS CALLER, matching /health/ready's
stance — naming which subsystem is dark on an unauthenticated endpoint is the SOC2
info-disclosure control. The detail is logged.

⚠ A VALID `X-API-Key` ADDS A `channels` MAP (2026-08-30, DATA-H2/H3), and nothing else
changes. One status word tells an operator that the canary refused and not which of ten
channels refused it, which leaves them reading Container App console logs during a blocked
deploy. The breakdown is therefore returned — but only to an authenticated caller, exactly
the stance /health/migrations and /health/data-integrity already take for endpoints that
name internal table state. The anonymous body is byte-identical to before, so the deploy
smoke test (templates/steps-smoke-test.yml), which calls this without a key and greps
`"status"` out of the body with a GREEDY regex, is unaffected. Keep it that way: the
channel map is deliberately `{name: word}` with no nested `"status"` key, because a second
`"status"` anywhere in this body would make that regex read the LAST one and silently
invert the gate.

⚠ A VALID KEY ALSO ADDS A `client` BLOCK (2026-08-30, SEC-M6 live check ③) —
`{peer, forwarded, xff_depth}`, the three values that make `TRUSTED_PROXY_HOPS`
verifiable with a single curl. See `_forwarded_diagnostics`. Same authenticated-only
stance and the same no-nested-`"status"` rule as `channels`.

``?year=`` probes a specific fiscal year. Without it this only ever answered for
``DEFAULT_ICD10_YEAR``, while a request may carry any ``body.year`` (see
api/v1/code.py) — so a client coding FY2025 against a deployment whose reference data
exists only for FY2026 got a green health check and a silently degraded coding path.
That is the serving-time shape of KB trap T1. The parameter is additive: the no-argument
call the deploy smoke test makes behaves exactly as before.

TWO CHECKS, ONE STATUS WORD (cross-year integrity added 2026-08-11).
Reference data fails in two shapes and only one of them is about a year being ABSENT:

  * ``check_coding_readiness`` — is the data this year needs THERE (corpus built,
    vocabulary loaded)? Absent data.
  * ``check_cross_year``       — was each year actually LOADED, or copied from the year
    before it? Present data that is silently WRONG, which no readiness probe can see
    because every table it looks at is populated.

The second used to be Gate C: a snapshot file produced by hand on the jump VM, committed
to the repo, and read by the CI stage. That design had three defects — nothing refreshed
it (so it expired and froze every merge), it gated PRs on a deploy-time concern, and it
described the database at some past moment rather than the one this revision will serve.
It is now computed here, live, on the canary before traffic shifts. ~0.85s for 13 datasets
across a three-year window; this endpoint has exactly one consumer, so that is affordable.

⚠ ERRORS block, WARNINGS do not. An identical codeset across two years is often correct —
the IPPS sex edit was deactivated 2024-10-01, so an unchanged set there is the EXPECTED
state. `check_cross_year` already encodes that distinction; re-deciding it here would
duplicate the judgement in the place least able to make it.

## Query parameters

- `year` integer, nullable

## Headers

- `X-API-Key` string, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/accurecord/apis/icd-10-coding-api.md) · [All operations](https://skmtc.dev/accurecord/apis/icd-10-coding-api/llms.txt) · [OpenAPI document](https://skmtc.dev/accurecord/apis/icd-10-coding-api/revisions/b1e12ce06ba5?raw)
