Endpoints
Every route is a GET under https://georgiacivicdata.org/api/v1, except the school-zone lookup, which also accepts a POST. Per-dataset filter parameters are listed on each dataset page.
At a glance
| Endpoint | Purpose |
|---|---|
/datasets | List every dataset + dimension |
/datasets/{main}/{topic} | Full schema for one dataset (JSON) |
/datasets/{main}/{topic}/contract | Raw ODCS contract (YAML/JSON) |
/{main}/{topic} | Query a dataset’s rows |
/education/_dimensions/{name} | Read an education dimension (districts/schools/demographics) |
/_dimensions/{name} | Read a global dimension (counties/demographics) |
/education/_dimensions/{name}/schema | A dimension’s schema |
/education/school_attendance_zones | School attendance zone polygons, plus /schema and /coverage |
/education/school_attendance_zones/lookup | Zones at a point or address, or covering a census tract (GET or POST) |
/education/school_district_boundaries | School district boundaries (Census TIGER/Line) |
Catalog
/api/v1/datasetsOne summary per dataset (title, source, year range, detail levels, endpoint) plus a dimensions block. No parameters.
curl "https://georgiacivicdata.org/api/v1/datasets"Dataset schema
/api/v1/datasets/{main_topic}/{topic}The full schema: every column (name, type, role, unit, range, allowed values, description), the structured filters list, foreign keys, the key_metric pointer, available years, and the schema_hash. This is what powers these docs.
curl "https://georgiacivicdata.org/api/v1/datasets/education/act_scores"/api/v1/datasets/{main_topic}/{topic}/contractThe authoritative ODCS v3.2 contract. ?format=yaml (default) returns it verbatim; ?format=json returns it parsed.
curl "https://georgiacivicdata.org/api/v1/datasets/education/act_scores/contract?format=yaml"Dataset query
/api/v1/{main_topic}/{topic}Query a dataset’s rows. Common parameters:
| Parameter | Description |
|---|---|
year | Exact year. Mutually exclusive with the range below. |
year_min / year_max | Inclusive year range. |
detail | states / counties / districts / schools (whatever the dataset publishes). |
district_code / school_code / county_fips / demographic | Comma-separated code lists (where the dataset has the column). |
| per-categorical params | One parameter per categorical column (see the dataset page). |
limit / offset | Page size (default 1000, max 10000) and offset. |
format | json (default) / csv / parquet. |
curl "https://georgiacivicdata.org/api/v1/education/act_scores?year=2024&test_component=composite&detail=districts"Dimensions
/api/v1/education/_dimensions/{name}Read an education-scoped lookup table — districts, schools, or demographics — paginated with limit / offset. These supply the label columns the fact queries join in.
curl "https://georgiacivicdata.org/api/v1/education/_dimensions/districts?limit=10"/api/v1/_dimensions/{name}Read a global lookup table — counties (all 159 Georgia counties, FIPS code + name) or demographics. The education route above remains for districts, schools, and demographics.
curl "https://georgiacivicdata.org/api/v1/_dimensions/counties?limit=10"/api/v1/education/_dimensions/{name}/schemaA dimension’s primary key, attributes, and link keys.
School attendance zones
Attendance zones are the areas a school district uses to assign an address to a school, by level (elementary, middle, high) and grade span. The zones are reconstructed from published district and vendor sources of varying currency and accuracy, and some districts have no zones (see /coverage). A zone or lookup is not an official enrollment determination: confirm results with the school district.
/api/v1/education/school_attendance_zonesZone polygons, one per school, level, and grade span. Parameters:
| Parameter | Description |
|---|---|
district_code / school_code / zone_level | Comma-separated lists. zone_level is elementary, middle, or high. |
grade | pk, k, or 01–12: only zones that serve that grade. |
year | School year the zones are in effect for, as its ending year (2027 = 2026–27). |
format | geojson (default) / shapefile (a zip with one layer per level) / geoparquet / json (attributes only, no geometry). |
resolution | display (default; simplified as a coverage, so neighboring zones keep their shared edges) / full (the full-resolution polygons the lookup uses). |
Each zone’s properties include school and district labels, nces_school_id, nces_lea_id, and its provenance: method, accuracy_class, positional_rmse_m, boundary_vintage, currency_status, currency_note (what changed and when, for a zone whose source predates an adopted change), source_url, source_publisher, and retrieved_on. Every format carries the note that a zone is not an official enrollment determination: a top-level note in GeoJSON and json, a README.txt in the shapefile zip, and the GeoParquet file metadata.
curl "https://georgiacivicdata.org/api/v1/education/school_attendance_zones?district_code=761&zone_level=high"/api/v1/education/school_attendance_zones/schemaEvery field with its type and description, the meaning of each enum value, the coordinate reference system (OGC:CRS84: longitude, latitude), the map from each field to its 10-character shapefile field name, and the companion files, with the columns of the coverage table. A shapefile text field holds at most 254 bytes, so a longer value (a long boundary_vintage or source_url) is cut there and ends with ...; the other formats carry the full text, and currency_note always fits.
/api/v1/education/school_attendance_zones/coverageOne row per Georgia school district: its status (complete, partial, one_school_per_grade, or not_available), the status of each level (zoned, one_school_per_grade, partial, not_available, or served_by_other_district), the share of its land and 2020 population the zones cover, and why anything is missing. format=json (default) or geojson (with district outlines).
/api/v1/education/school_attendance_zones/lookupGive lat and lon, or tract_geoid, plus an optional grade and year.
| Parameter | Returns |
|---|---|
lat + lon | The zones containing the point, the point’s 2020 census tract and county, its district (code, name, Census id, NCES LEA id), a level_status for each school level, and a coverage_status with the reason. A zone whose source predates a boundary change that could not be applied adds a currency_warning that says what changed, by level. |
tract_geoid | Every zone covering a 2020 census tract, with the share of the tract’s 2020 population in each (from the school_attendance_zone_tracts crosswalk dataset). When no zone covers the tract, a coverage_reason says why. |
| coverage_status | Meaning |
|---|---|
zoned | The point is inside a zone at every school level its grades fall in. |
gap | The district has zones, but at least one school level has none at this point (zones found at the other levels are still listed). |
one_school_per_grade | The district runs one school for each grade, so that school’s zone is the whole district. |
not_available | The district publishes no zones at one or more school levels the point’s grades fall in (zones found at the other levels are still listed); the reason says why. |
not_zoned | No attendance zone in the district assigns the grade asked (pre-K, whose places are filled by application). |
outside_georgia | The point is outside Georgia. |
Every response carries a note that it is not an official enrollment determination, and is sent with Cache-Control: no-store. A GET puts the coordinates in the URL, which passes through our hosting platform; our application never writes them to its logs. To keep a point out of URLs, send it by POST.
curl "https://georgiacivicdata.org/api/v1/education/school_attendance_zones/lookup?lat=33.7479&lon=-84.3903&grade=09"/api/v1/education/school_attendance_zones/lookupA JSON body with exactly one of the following, plus an optional grade and year:
| Body | Description |
|---|---|
{"address": "..."} | One address, geocoded by the U.S. Census Geocoder (benchmark Public_AR_Current, vintage Census2020_Current). The response adds the matched address, its coordinates, and the geocoder’s tract. |
{"lat": .., "lon": ..} | One point. |
{"points": [{"id", "lat", "lon"}, ...]} | Up to 1,000 points; each result carries its id. |
Addresses are accepted only by POST, so they never appear in a URL. Our application never writes addresses or coordinates to its application logs, and never caches or records them. POST is also the private way to send a point. Responses are sent with Cache-Control: no-store. Rate limits per client: 120 requests a minute for GET lookups and 20 a minute for POST.
curl -X POST "https://georgiacivicdata.org/api/v1/education/school_attendance_zones/lookup" \
-H "Content-Type: application/json" \
-d '{"address": "55 Trinity Ave SW, Atlanta, GA 30303"}'/api/v1/education/school_district_boundariesCensus TIGER/Line school district boundaries for Georgia, keyed to district_code. Filter with district_code; the same format options as the zones.