{
  "openapi": "3.1.0",
  "info": {
    "title": "School Schedules Database API",
    "version": "1.0.0",
    "description": "Day-level US K-12 school calendars, resolved to the school district. One row per district per day (in session / half day / off) with break name, a 0-1 confidence score, and the source_method the date came from. IMPORTANT: there is no `estimated` boolean — derive it from source_method (observed/deterministic/legacy = confirmed; inferred/state_median_imputation = estimated). For 2026-2027 most dates are still estimated. Independent commercial dataset; not affiliated with any school, district, or the Department of Education.",
    "contact": { "name": "School Schedules Database", "url": "https://schoolschedulesdatabase.com" },
    "x-pricing": { "plan": "Full access", "price": "99", "priceCurrency": "USD", "unit": "MONTH", "url": "https://schoolschedulesdatabase.com/pricing", "note": "The keyless sample returns the district index only; calendar days require a key. Tiers never differ by data quality, but they do differ by SCOPE: a trial key is restricted to one state and one school year, and an out-of-scope request returns 403 naming the restriction rather than silently narrowing the result." }
  },
  "servers": [ { "url": "https://api.hazeydata.ai/ssd/v1" } ],
  "paths": {
    "/sample/districts": {
      "get": {
        "operationId": "getSampleDistricts",
        "summary": "Free, keyless: the 100 largest districts by enrollment.",
        "description": "The district index, so you can find district_id values. This endpoint returns NO calendar data.",
        "security": [ {} ],
        "responses": {
          "200": {
            "description": "District index.",
            "content": { "application/json": { "schema": {
              "type": "object",
              "properties": {
                "note": { "type": "string" },
                "total": { "type": "integer" },
                "districts": { "type": "array", "items": { "$ref": "#/components/schemas/District" } }
              }
            } } }
          }
        }
      }
    },
    "/districts": {
      "get": {
        "operationId": "listDistricts",
        "summary": "Search and page the full district list.",
        "security": [ { "bearerAuth": [] } ],
        "parameters": [
          { "name": "state", "in": "query", "schema": { "type": "string" }, "example": "FL" },
          { "name": "search", "in": "query", "schema": { "type": "string" } },
          { "name": "min_enrollment", "in": "query", "schema": { "type": "integer" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100, "maximum": 1000 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 } }
        ],
        "responses": { "200": { "description": "Districts.", "content": { "application/json": { "schema": { "type": "object", "properties": { "total": { "type": "integer" }, "districts": { "type": "array", "items": { "$ref": "#/components/schemas/District" } } } } } } } }
      }
    },
    "/days": {
      "get": {
        "operationId": "getDays",
        "summary": "Day-level calendar rows — the core dataset.",
        "description": "One row per district per day. Filter by district, state, date range and school year.",
        "security": [ { "bearerAuth": [] } ],
        "parameters": [
          { "name": "district_id", "in": "query", "schema": { "type": "string" }, "example": "FL_1200180", "description": "{STATE}_{NCES_ID}." },
          { "name": "state", "in": "query", "schema": { "type": "string" }, "example": "FL" },
          { "name": "date", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "school_year", "in": "query", "schema": { "type": "string", "enum": ["2024-2025", "2025-2026", "2026-2027"] } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 365, "maximum": 5000 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 }, "description": "Row offset for paging. `total` is the match count and `returned` is this page size (Issue #211)." }
        ],
        "responses": { "200": { "description": "Calendar days.", "content": { "application/json": { "schema": { "type": "object", "properties": { "total": { "type": "integer" }, "days": { "type": "array", "items": { "$ref": "#/components/schemas/Day" } } } } } } } }
      }
    },
    "/breaks": {
      "get": {
        "operationId": "getBreaks",
        "summary": "Named breaks and holidays.",
        "security": [ { "bearerAuth": [] } ],
        "parameters": [
          { "name": "state", "in": "query", "schema": { "type": "string" } },
          { "name": "break_name", "in": "query", "schema": { "type": "string" }, "example": "thanksgiving" },
          { "name": "date_from", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "date_to", "in": "query", "schema": { "type": "string", "format": "date" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 100, "maximum": 1000 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 }, "description": "Row offset for paging. `total` is the match count and `returned` is this page size (Issue #211)." }
        ],
        "responses": { "200": { "description": "Breaks." } }
      }
    },
    "/export": {
      "get": {
        "operationId": "exportCsv",
        "summary": "Bulk CSV export.",
        "security": [ { "bearerAuth": [] } ],
        "parameters": [
          { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "enum": ["csv", "json"], "default": "csv" }, "description": "csv (default) returns text/csv; json returns the same rows as JSON. Any other value returns 400 (Issue #211)." },
          { "name": "state", "in": "query", "schema": { "type": "string" } },
          { "name": "school_year", "in": "query", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 50000, "maximum": 100000 } },
          { "name": "offset", "in": "query", "schema": { "type": "integer", "default": 0 }, "description": "Row offset for paging. JSON responses carry total/returned/offset/truncated; CSV carries X-Total-Count, X-Returned-Count and X-Truncated headers (Issue #211)." }
        ],
        "responses": { "200": { "description": "CSV.", "content": { "text/csv": { "schema": { "type": "string" } } } } }
      }
    }
  },
  "components": {
    "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "description": "Keys look like ssd_live_… . Paid plans only; /sample/districts is keyless." } },
    "schemas": {
      "District": {
        "type": "object",
        "properties": {
          "district_id": { "type": "string", "example": "FL_1200180", "description": "{STATE}_{NCES_ID}." },
          "district_name": { "type": "string", "example": "Orange County Public Schools" },
          "state": { "type": "string", "example": "FL" },
          "enrollment": { "type": "integer", "example": 208000 }
        }
      },
      "Day": {
        "type": "object",
        "properties": {
          "district_id": { "type": "string", "example": "FL_1200180" },
          "district_name": { "type": "string" },
          "state": { "type": "string" },
          "enrollment": { "type": "integer" },
          "date": { "type": "string", "format": "date" },
          "school_year": { "type": "string", "example": "2026-2027" },
          "is_in_session": { "type": "number", "enum": [0.0, 0.5, 1.0], "description": "1.0 full day, 0.5 half day, 0.0 off." },
          "day_type": { "type": "string", "example": "BREAK" },
          "break_name": { "type": ["string", "null"], "example": "thanksgiving" },
          "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
          "source_method": { "type": "string", "enum": ["observed", "deterministic", "legacy", "inferred", "state_median_imputation"], "description": "observed/deterministic/legacy = confirmed. inferred/state_median_imputation = ESTIMATED — inferred from state patterns or prior years, not published by the district. There is no separate `estimated` field; derive it from this." }
        }
      }
    }
  }
}
