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
legacyImputedstand-ins described below. - Starting with API 3.0, add
includeRanges=trueto/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 astatus, 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
| Representation | Meaning | Fields |
|---|---|---|
| a plain number | The 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. |
| absent | Nothing was reported for this metric. | — |
Rendering rule
SchoolDigger.com renders these values as follows; we recommend consumers do the same.
| Value | Rendered |
|---|---|
82.3 | 82.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) orisinstance(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.
Low-income measures (API 3.1)
Free/reduced-price lunch counts no longer mean the same thing in every state: some states report only students directly certified for free meals, and schools in the Community Eligibility Provision serve every student free and stop collecting meal applications. API 3.1 adds lowIncome to each school record in /v3.1/schools/{id}, /v3.1/schools and /v3.1/rankings/schools/{st}, picking one measure per school:
type | Meaning |
|---|---|
FRL | Free/reduced lunch eligible: students eligible for free school meals (household income at or below 130% of the federal poverty guidelines) plus students eligible for reduced-price meals (above 130% up to 185%). |
DC | Directly certified for free meals: students approved automatically, without a meal application, because the household gets SNAP, TANF or FDPIR (and, in most states, Medicaid), or because they are homeless, migrant, runaway, in foster care or in Head Start. Used when the school has no usable free/reduced count (Massachusetts, the District of Columbia, Delaware, Tennessee and West Virginia report only this). Usually lower than free/reduced eligibility. |
CEP | All students receive free meals: the school's free/reduced count is 98% or more of its enrollment and there is no direct certification count, which usually means it serves free meals to every student under the Community Eligibility Provision. No percent. |
"lowIncome": {
"type": "DC", "year": 2025, "percent": 70.04, "count": 2520, "enrollment": 3598,
"communityEligibilityLikely": false, "statewideFreeMeals": true
}
- FRL and DC are not comparable. Do not rank or sort one against the other; SchoolDigger.com lists show one measure per list.
yearis the school year of the value (2025 = 2024-25). Values older than 3 years are not used, and a count larger than the school's enrollment is treated as missing.communityEligibilityLikelyis true when the newest usable free/reduced count is 98%+ of enrollment, even for aDCschool.statewideFreeMealsis true when the state serves free school meals to all students that year.lowIncomeis absent when the school has no usable value (private schools, for example).- On
/v3.1/schools/{id}, eachschoolYearlyDetailsentry also hasfreeReducedLunch(countandpercent, or astatus:communityEligibility,repeatedwhen the state repeated the prior year's counts,aboveEnrollment) anddirectCertification(countandpercent). Each is absent when not reported. percentFreeDiscLunchand every version up to 3.0 are unchanged.includeRangesworks on 3.1 as on 3.0.
See the API 3.0 reference, the API 3.1 reference and the Change Log. Questions: api@schooldigger.com.