API documentation v1

Day-level school calendar data for every US public school district — one row per district per day, every break named and typed, every row scored for confidence.

12,000+ districts, 46M+ students, a rolling three-year window. Flat $99/monthget a key, then read on.

Overview

Responses are read-only JSON (the CSV export returns text/csv), versioned under /v1. Every calendar row carries a source_method and a confidence so you always know whether a date was read from a real calendar or estimated. It's the same archive that powers this site.

Authentication

All data endpoints require a valid API key, passed as a Bearer token in the Authorization header. Keys start with ssd_live_ and are shown once, after purchase and in your account — we store only a SHA-256 hash and can't recover it for you.

# include your key in every request curl https://api.hazeydata.ai/ssd/v1/districts \ -H "Authorization: Bearer ssd_live_your_key_here"

Base URL

https://api.hazeydata.ai/ssd/v1/

All endpoints return application/json unless noted (the CSV export returns text/csv).

Rate limits

Each subscription includes 10,000 API calls per month, resetting on the 1st. Exceed it and requests return 429 Too Many Requests until reset. Track usage live in your account dashboard — we alert you at 80%. Need higher volume? Contact us for enterprise pricing.

GET /districts auth

Search and list districts, ordered by enrollment (largest first).

GET /districts?state=FL&min_enrollment=10000
ParamTypeDescription
statestringTwo-letter code (case-insensitive)
searchstringPartial name match, e.g. Houston
min_enrollmentintEnrollment floor
limit / offsetintPagination (limit default 100, max 1000)
{ "total": 32, "limit": 100, "offset": 0, "districts": [ { "district_id": "FL_1200390", "district_name": "Miami-Dade County Public Schools", "state": "FL", "enrollment": 334235 } ] }

GET /days auth

The core endpoint — day-level rows showing whether each district is in session on each date, with break names and confidence.

GET /days?district_id=FL_1200390&school_year=2026-2027
GET /days?state=FL&date=2026-12-25
ParamTypeDescription
district_idstringA specific district
statestringTwo-letter code
datestringYYYY-MM-DD — all districts for that date
date_from / date_tostringDate range
school_yearstringe.g. 2026-2027
limitintDefault 365, max 5000
# what does spring break look like in Texas? curl "…/v1/days?state=TX&date_from=2027-03-08&date_to=2027-03-19" \ -H "Authorization: Bearer ssd_live_your_key" { "total": 2, "days": [ { "district_id": "TX_4823640", "district_name": "Houston Independent School District", "state": "TX", "date": "2027-03-08", "school_year": "2026-2027", "is_in_session": 0.0, "day_type": "BREAK", "break_name": "Spring Break", "confidence": 0.92, "source_method": "markitdown_extraction" } ] }

GET /breaks auth

Just the breaks, holidays, and non-school days (weekends excluded) — for "when is spring break across these districts?"

GET /breaks?state=CA&break_name=Spring
ParamTypeDescription
statestringTwo-letter code
break_namestringPartial match, e.g. Spring, Thanksgiving
date_from / date_tostringDate range
limitintDefault 100, max 1000

GET /export auth

Bulk CSV, same fields as /days, flattened for a warehouse or spreadsheet.

GET /export?format=csv&state=FL&school_year=2026-2027
ParamTypeDescription
school_yearstringDefault current year
statestringOmit for all states
limitintDefault 50000, max 100000

Returns text/csv with a suggested filename — pipe with -o or load with pd.read_csv().

GET /sample no auth

Free — no key required. The top 100 districts by enrollment, to preview the data model before subscribing.

GET /sample/districts

Data model

School day object

FieldTypeDescription
is_in_sessionfloat1.0 full day · 0.5 half day · 0.0 no school. A real number, not a boolean.
day_typestringSCHOOL_DAY, WEEKEND, BREAK, HOLIDAY, TEACHER_WORKDAY, HALF_DAY, SUMMER
break_namestring | nulle.g. Spring Break, Thanksgiving
confidencefloat0.0–1.0 — see below
source_methodstringHow we know: markitdown_extraction, pdf_extraction (both observed), imputation (estimated), deterministic (weekends, certain)
Observed vs estimated, in the payload: extraction methods are observed; imputation is an estimate (honest low confidence). Filter with min_confidence to keep whole calendars in or out. Unresolved days are not served — empty beats mislabeled.

School years

YearPeriodStatus
2024-2025Aug 2024 – Jun 2025Previous (historical)
2025-2026Aug 2025 – Jun 2026Most complete
2026-2027Aug 2026 – Jun 2027As published / estimated

The oldest year drops off each September. Requests outside the window return 403.

Confidence scores

RangeMeaning
0.90–1.00High — extracted directly from an official district calendar
0.70–0.89Good — from a PDF or secondary source
0.50–0.69Moderate — inferred from surrounding data or state patterns
1.00Deterministic — weekends and summer, classified by rule

Errors

StatusMeaning
200Success
400Bad request — check your parameters
401Missing or invalid API key
403Subscription inactive, or year outside the window
429Monthly rate limit exceeded
500Server error — let us know
{ "error": "Monthly rate limit exceeded (10000 calls). Resets on the 1st." }

Support

Something not working? Email us — you'll get a real human, usually within a few hours. Include your API key prefix (first 16 characters) so we can find your account. Most first-request issues are a missing Bearer prefix in the header.

Email support →