SchoolDigger API
  • Plans
  • Documentation
  • Change Log
  • Data Privacy
  • Sign in

Data Quality and Suppression

How test-score values that are not a single exact number are represented in API 3.0

In short

  • States withhold or round some test results to protect student privacy (small student counts). SchoolDigger now stores exactly what the state published.
  • Available for 2026 and later test-score data (the 2025-26 school year onward), state by state as each state's results are loaded. Earlier years keep their existing exact values, plus the legacyImputed stand-ins described below.
  • Starting with API 3.0, add includeRanges=true to /v3.0/schools/{id} or /v3.0/districts/{id} and each percent metric in a test score (percentMetStandard, percentTier1 … percentTier5) is either a plain number or an object with a status, and is absent when nothing was reported.
  • Without includeRanges (the default) a 3.0 record is identical to 2.4: exact values only, and rows the state reported as a range or suppressed are left out.
  • API versions 2.4 and below are unchanged: they return only exact values and omit rows the state reported as a range or suppressed.
  • The API carries no display strings. The rendering rule below is the consumer's job.

The 3.0 shape

A school, district or state test score object in /v3.0/schools/{id}?includeRanges=true and /v3.0/districts/{id}?includeRanges=true:

"schoolTestScore": {
  "studentsTested": 48,
  "meanScaledScore": 645,
  "percentMetStandard": 82.3,
  "percentTier1": { "status": "range", "low": 0, "high": 10 },
  "percentTier2": 27,
  "percentTier3": { "status": "derived", "value": 8 },
  "percentTier4": { "status": "suppressed" }
}

A score object that contains only status objects is a real record: students were tested and the results were withheld. studentsTested, studentsEligible, meanScaledScore and the numTier counts are unchanged. Tier metrics remain Enterprise-only; percentMetStandard objects are returned on every plan that includes test scores.

Status vocabulary

RepresentationMeaningFields
a plain numberThe state reported an exact value. Identical to API 2.4.—
{ "status": "range" }The state published only a range, for example "less than 10%" or "at least 95%".low, high: the state's bounds in percent. low of 0 means "less than high"; high of 100 means "at least low".
{ "status": "suppressed" }The state withheld the value to protect student privacy.none
{ "status": "legacyImputed" }A pre-2018 SchoolDigger stand-in for a value the state published as a range at the time. Older API versions return the stand-in (4 for "less than 5%", 96 for "at least 95%") as a plain number.value: the stand-in; low, high: the state's bounds.
{ "status": "derived" }Computed by SchoolDigger from the other levels the state did report (for example the remaining tier when the others are exact).value when the result is exact, otherwise low, high.
absentNothing was reported for this metric.—

Rendering rule

SchoolDigger.com renders these values as follows; we recommend consumers do the same.

ValueRendered
82.382.3%
{ "status": "range", "low": 0, "high": 10 }< 10%
{ "status": "range", "low": 95, "high": 100 }≥ 95%
{ "status": "range", "low": 10, "high": 15 }10–15%
{ "status": "suppressed" }— (with a footnote: some values were suppressed by the state to protect student privacy)
{ "status": "legacyImputed", "value": 4, "low": 0, "high": 5 }< 5% (render from the bounds, not the stand-in)
{ "status": "derived", "value": 8 }8% (a derived exact value is shown as a normal value)

Rankings

SchoolDigger rankings use exact values where the state reported them and the midpoint of a range where it did not; a school whose results were entirely suppressed for a test is not ranked on that test. Ranking output in the API (rankHistory, /rankings) is unchanged.

Migrating from 2.4

  • Opt in per call with includeRanges=true; a 3.0 call without it returns the 2.4 record, so existing code keeps working when you switch the version.
  • With includeRanges=true, check the JSON type of each percent metric before using it as a number: typeof v === 'number' (JavaScript) or isinstance(v, (int, float)) (Python).
  • With includeRanges=true, expect test-score entries and score objects that 2.4 omitted: rows the state reported only as ranges or suppressed values.
  • Tier labels (tier1 … tier5) are now present whenever the tier percent is present as a number or an object.
  • All other 3.0 endpoints (/schools, /districts, /rankings, /autocomplete) return the same data as 2.4.
  • The official Python and JavaScript/TypeScript SDKs model the union as APIReportedPercent.

See the API 3.0 reference and the Change Log. Questions: api@schooldigger.com.

  • © 2026 SchoolDigger.com,
  • Powered by 3scale