Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Georgia Civic Data Datasets API
description: 'Read-only REST API serving cleaned, standardized tabular data for the state of Georgia: **education**, **census**, **health** and **immigration**, driven entirely by git-tracked ODCS data contracts — so every dataset''s columns, units, ranges, and allowed values are stable and documented.
**Base path:** all data routes live under `/api/v1`. Every dataset is addressed by its bare name (names are unique), e.g. `act_scores`.
**Discover, don''t hard-code.** `GET /api/v1/datasets` lists every dataset (compact; `?fields=full` for everything); `GET /api/v1/search?q=` finds one by meaning; `GET /api/v1/datasets/{name}` returns its schema (columns, units, the exact filter parameters with their allowed values, and a runnable `recommended_query` URL); `GET /api/v1/datasets/{name}/rows` returns the data.
**Note on filters:** every categorical column of a dataset is its own filter parameter, so the filters differ per dataset and are listed in the dataset''s schema (`filters`), not in this generic document. `GET /api/v1/datasets/{name}/openapi.json` is a per-dataset OpenAPI document with every filter and its allowed values, for function-calling clients that need one. Human docs: https://georgiacivicdata.org/api; agent reference: https://georgiacivicdata.org/llms-full.txt.
**R and Python packages:** `georgiacivicdata` on CRAN and PyPI wraps this API and returns data frames. Docs: https://georgiacivicdata.org/r/ and https://georgiacivicdata.org/py/ (overview: https://georgiacivicdata.org/packages).
**License:** data and documentation are licensed CC BY 4.0. Credit "Georgia Civic Data (georgiacivicdata.org)" and the original source. The license covers our cleaning, standardization, compilation, and documentation; source data stays under its original publisher''s terms (each dataset names its source). Every response carries a `Link: ; rel="license"` header, and `GET /api/v1/datasets` returns the terms as a `license` object. Details: https://georgiacivicdata.org/about#license.'
contact:
name: Georgia Civic Data
url: https://georgiacivicdata.org/api
email: shane@georgiacivicdata.org
license:
name: Creative Commons Attribution 4.0 International (CC BY 4.0)
url: https://creativecommons.org/licenses/by/4.0/
version: 0.2.0
servers:
- url: https://georgiacivicdata.org
description: Production (brand domain, same-origin proxy)
- url: https://georgia-civic-data-production.up.railway.app
description: Production (origin)
tags:
- name: Datasets
description: Every dataset through one set of routes keyed by its bare name (`/api/v1/datasets/{name}/rows`, `/values`, `/aggregate`, `/download`). Each categorical column is a filter; the dataset's schema lists them with their allowed values.
paths:
/api/v1/datasets:
get:
tags:
- Datasets
summary: The dataset catalog
description: Every served dataset. Compact by default (name, title, summary, kind, main_topic, detail_levels, year_min, year_max); `fields=full` adds descriptions, search aliases, sources, grain and coverage. Filter with `main_topic`, `level` (a detail level such as counties), `year` (a year the dataset publishes) and `kind` (table or geometry). Also lists the lookup tables (`dimensions`) and the data `license`. `/api/v1/search?q=` finds datasets by meaning.
operationId: list_datasets_api_v1_datasets_get
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/api/v1/datasets/{name}:
get:
tags:
- Datasets
summary: One dataset's schema
description: Columns (type, role, unit, range, what a NULL means), the exact filter parameters with their allowed values, the headline `key_metric`, a runnable `recommended_query.url`, `example_requests`, how the figures may and may not be combined (non_additive, partitions, pooled_rates, series_breaks, year_window), usage and limitations. `verbosity=schema` drops the prose.
operationId: get_dataset_api_v1_datasets__name__get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
- name: verbosity
in: query
required: false
schema:
enum:
- full
- schema
type: string
default: full
title: Verbosity
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/contract:
get:
tags:
- Datasets
summary: One dataset's ODCS data contract
description: '`format=yaml` (default) returns the contract verbatim; `format=json` returns it parsed.'
operationId: get_dataset_contract_api_v1_datasets__name__contract_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
- name: format
in: query
required: false
schema:
enum:
- yaml
- json
type: string
default: yaml
title: Format
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/openapi.json:
get:
tags:
- Datasets
summary: A per-dataset OpenAPI document
description: OpenAPI 3.1 for this dataset's rows and aggregate routes, listing every filter parameter and its allowed values (for function-calling clients that need an accurate OpenAPI; the generic document cannot list them).
operationId: get_dataset_openapi_api_v1_datasets__name__openapi_json_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/rows:
get:
tags:
- Datasets
summary: Rows of one dataset
description: 'Filtered rows with district, school, county and demographic names joined in. Every categorical column is a filter (`?column=a,b`; a repeated parameter adds values); the dataset''s schema lists them all. Also: `year` (one or more), `year_min`/`year_max`, `detail`, `school=DISTRICT-SCHOOL`, `{metric}_min`/`{metric}_max`, `numeric_filters`, `sort`, `columns`, `limit`/`offset`, `format`. JSON returns `data`, `pagination`, `links.next` and a `meta` block (units, null semantics, citation, advisories). CSV and Parquet without a `limit` return every matching row.'
operationId: get_rows_api_v1_datasets__name__rows_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/query:
post:
tags:
- Datasets
summary: Rows of one dataset, parameters in a JSON body
description: 'The rows route for long or nested parameters: the body takes the same names as the GET parameters, with `filters` as an object of column -> value or list, `sort` as a list, `numeric_filters` as a list, and `order_by` + `order` accepted as in the MCP tools. Not cached at the edge; prefer GET.'
operationId: post_query_api_v1_datasets__name__query_post
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: true
title: Body
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/download:
get:
tags:
- Datasets
summary: Every filtered row of one dataset, as a file
description: 'The same filters as `/rows`, no page cap: `format=csv` (default, streamed) or `parquet`. `X-Total-Count` gives the row count.'
operationId: download_api_v1_datasets__name__download_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/values:
get:
tags:
- Datasets
summary: Distinct combinations of category values
description: The distinct combinations of the `columns` named (categorical columns and `demographic`) with row counts, most rows first, under the same filters as `/rows` (e.g. which grade levels district 761 publishes in 2024). A `null` value means the column is unpopulated for those rows; filter it with `__null__`.
operationId: get_values_api_v1_datasets__name__values_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/datasets/{name}/aggregate:
get:
tags:
- Datasets
summary: Grouped figures computed on the server
description: '`agg` = avg, sum, min, max, count or weighted_rate (a population-weighted rate: SUM(numerator) / SUM(denominator), on the rate''s own per-N scale), `metric` (default the key metric), `group_by` (year, place codes, categories), the same filters as `/rows` (one `year` or a range), `sort`, `limit`, `offset`. Each group reports its coverage (input_rows, non-null counts), and `advisories` flag sums across overlapping rows, averages of rates and the like.'
operationId: get_aggregate_api_v1_datasets__name__aggregate_get
parameters:
- name: name
in: path
required: true
schema:
type: string
title: Name
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
type: object
required:
- loc
- msg
- type
title: ValidationError