District Pages API Documentation¶
This document provides API documentation for building congressional district pages, intended for the cbpublic team.
Developer Resources
CLAUDE.md - AI-assisted development guide
Overview¶
The Congressional Districts API provides structured data about U.S. congressional districts including: - Census demographic data (population, income, education, etc.) - Geographic boundaries (GeoJSON) - Wikipedia-sourced information (representative, party, Cook PVI)
Base URL: https://districts.nominate.ai/api/v1
Authentication¶
No authentication required. Public API.
Endpoints¶
Get District Details¶
Returns census demographic data for a district.
Parameters:
- geoid (path, required): 4-digit Census GEOID (state FIPS + district number)
Example:
Response:
{
"geoid": "1903",
"name": "Iowa's 3rd Congressional District",
"state_fips": "19",
"state_name": "Iowa",
"population": 818737,
"median_age": 36.8,
"median_income": 72456,
"bachelors_plus": 245621,
"unemployment_rate": 3.2,
"median_home_value": 198500
}
Get District Wikipedia Data¶
Returns Wikipedia-sourced information including current representative, party affiliation, and Cook PVI.
Parameters:
- geoid (path, required): 4-digit Census GEOID
Example:
Response:
{
"geoid": "1903",
"state_code": "ia",
"state_name": "Iowa",
"district_number": 3,
"is_at_large": false,
"title": "Iowa's 3rd Congressional District",
"summary": "Iowa's 3rd congressional district is a congressional district in the U.S. state of Iowa. It includes the Des Moines metropolitan area and extends into rural western Iowa.",
"population": "818,737",
"representative": "Zach Nunn",
"party": "Republican",
"cook_pvi": "R+3",
"counties": ["Adair", "Adams", "Cass", "Dallas", "Guthrie", "Madison", "Polk", "Story", "Warren"],
"wikipedia_url": "https://en.wikipedia.org/wiki/Iowa%27s_3rd_congressional_district",
"cached_at": "2024-01-15T10:30:00+00:00",
"cache_expires_at": "2024-01-17T10:30:00+00:00"
}
Cache Behavior:
- Data is cached for 48 hours
- cached_at and cache_expires_at indicate cache freshness
- Stale cache is automatically refreshed on next request
Get District Geometry¶
Returns GeoJSON geometry for the district boundary.
Example:
Response: GeoJSON Feature with Polygon/MultiPolygon geometry
List All Districts¶
Returns paginated list of all districts.
Query Parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| limit | int | 50 | Max items (1-500) |
| offset | int | 0 | Items to skip |
| state_fips | string | - | Filter by state (2-digit FIPS) |
| format | string | json | json or geojson |
| include_geometry | bool | false | Include geometry data |
| sort | string | geoid | Sort field |
| order | string | asc | asc or desc |
Example:
# Get all Iowa districts
curl "https://districts.nominate.ai/api/v1/districts?state_fips=19"
# Get all districts as GeoJSON
curl "https://districts.nominate.ai/api/v1/districts?format=geojson&limit=500"
GEOID Reference¶
The GEOID is a 4-digit code: 2-digit State FIPS + 2-digit District Number
| GEOID | State | District |
|---|---|---|
| 0601 | California | 1st |
| 0652 | California | 52nd |
| 1903 | Iowa | 3rd |
| 3600 | New York | At-large (if applicable) |
| 4801 | Texas | 1st |
At-Large Districts: District number is 00 (e.g., Alaska = 0200, Wyoming = 5600)
State FIPS Codes¶
| FIPS | State | FIPS | State |
|---|---|---|---|
| 01 | Alabama | 28 | Mississippi |
| 02 | Alaska | 29 | Missouri |
| 04 | Arizona | 30 | Montana |
| 05 | Arkansas | 31 | Nebraska |
| 06 | California | 32 | Nevada |
| 08 | Colorado | 33 | New Hampshire |
| 09 | Connecticut | 34 | New Jersey |
| 10 | Delaware | 35 | New Mexico |
| 11 | District of Columbia | 36 | New York |
| 12 | Florida | 37 | North Carolina |
| 13 | Georgia | 38 | North Dakota |
| 15 | Hawaii | 39 | Ohio |
| 16 | Idaho | 40 | Oklahoma |
| 17 | Illinois | 41 | Oregon |
| 18 | Indiana | 42 | Pennsylvania |
| 19 | Iowa | 44 | Rhode Island |
| 20 | Kansas | 45 | South Carolina |
| 21 | Kentucky | 46 | South Dakota |
| 22 | Louisiana | 47 | Tennessee |
| 23 | Maine | 48 | Texas |
| 24 | Maryland | 49 | Utah |
| 25 | Massachusetts | 50 | Vermont |
| 26 | Michigan | 51 | Virginia |
| 27 | Minnesota | 53 | Washington |
| 54 | West Virginia | ||
| 55 | Wisconsin | ||
| 56 | Wyoming |
Integration Guide for cbpublic¶
Building a District Page¶
To build a comprehensive district page, combine data from multiple endpoints:
import httpx
async def get_district_page_data(geoid: str):
"""Fetch all data needed for a district page."""
base = "https://districts.nominate.ai/api/v1"
async with httpx.AsyncClient() as client:
# Fetch census demographics
census_resp = await client.get(f"{base}/districts/{geoid}")
census_data = census_resp.json()
# Fetch Wikipedia data (representative, party, summary)
wiki_resp = await client.get(f"{base}/districts/{geoid}/wiki")
wiki_data = wiki_resp.json()
# Combine into page data
return {
"geoid": geoid,
"name": census_data.get("name"),
"state": wiki_data.get("state_name"),
# From Census
"population": census_data.get("population"),
"median_income": census_data.get("median_income"),
"median_age": census_data.get("median_age"),
"unemployment_rate": census_data.get("unemployment_rate"),
# From Wikipedia
"representative": wiki_data.get("representative"),
"party": wiki_data.get("party"),
"cook_pvi": wiki_data.get("cook_pvi"),
"summary": wiki_data.get("summary"),
"counties": wiki_data.get("counties"),
"wikipedia_url": wiki_data.get("wikipedia_url"),
}
Converting District Code to GEOID¶
If you have a district code like "ia03", convert to GEOID:
STATE_TO_FIPS = {
"al": "01", "ak": "02", "az": "04", "ar": "05", "ca": "06",
"co": "08", "ct": "09", "de": "10", "dc": "11", "fl": "12",
"ga": "13", "hi": "15", "id": "16", "il": "17", "in": "18",
"ia": "19", "ks": "20", "ky": "21", "la": "22", "me": "23",
"md": "24", "ma": "25", "mi": "26", "mn": "27", "ms": "28",
"mo": "29", "mt": "30", "ne": "31", "nv": "32", "nh": "33",
"nj": "34", "nm": "35", "ny": "36", "nc": "37", "nd": "38",
"oh": "39", "ok": "40", "or": "41", "pa": "42", "ri": "44",
"sc": "45", "sd": "46", "tn": "47", "tx": "48", "ut": "49",
"vt": "50", "va": "51", "wa": "53", "wv": "54", "wi": "55",
"wy": "56"
}
def code_to_geoid(code: str) -> str:
"""Convert district code (e.g., 'ia03') to GEOID (e.g., '1903')."""
code = code.lower()
state = code[:2]
district = code[2:].zfill(2)
fips = STATE_TO_FIPS.get(state)
return f"{fips}{district}"
# Examples
code_to_geoid("ia03") # -> "1903"
code_to_geoid("ca52") # -> "0652"
code_to_geoid("ak00") # -> "0200" (at-large)
Error Handling¶
async def safe_get_wiki_data(geoid: str):
"""Fetch Wikipedia data with error handling."""
try:
resp = await client.get(f"{base}/districts/{geoid}/wiki")
if resp.status_code == 404:
return None # District not found
resp.raise_for_status()
return resp.json()
except httpx.HTTPError as e:
logger.warning(f"Failed to fetch wiki data for {geoid}: {e}")
return None
Response Schema Reference¶
WikipediaDistrictData¶
| Field | Type | Description |
|---|---|---|
geoid |
string | Census GEOID (4 digits) |
state_code |
string | 2-letter state abbreviation (lowercase) |
state_name |
string | Full state name |
district_number |
int | District number (0 for at-large) |
is_at_large |
bool | Whether this is an at-large district |
title |
string | Formal district title |
summary |
string | Wikipedia summary (2-3 sentences) |
population |
string? | Population from Wikipedia |
representative |
string? | Current representative name |
party |
string? | Party: "Republican" or "Democrat" |
cook_pvi |
string? | Cook PVI (e.g., "R+5", "D+10", "EVEN") |
counties |
string[] | List of counties in district |
wikipedia_url |
string | Full Wikipedia page URL |
cached_at |
datetime | When data was cached |
cache_expires_at |
datetime | When cache expires |
DistrictDetail¶
| Field | Type | Description |
|---|---|---|
geoid |
string | Census GEOID |
name |
string | District name |
state_fips |
string | 2-digit state FIPS |
state_name |
string | Full state name |
population |
int? | Total population |
median_age |
float? | Median age |
median_income |
int? | Median household income |
bachelors_plus |
int? | Population with bachelor's degree or higher |
unemployment_rate |
float? | Unemployment rate (%) |
median_home_value |
int? | Median home value |
Rate Limits¶
No rate limits currently enforced, but please:
- Cache responses on your end when appropriate
- Avoid polling endpoints more than once per minute
- Use limit=500 for bulk fetches instead of many small requests
OpenAPI/Swagger¶
Interactive API documentation available at: - Swagger UI: https://districts.nominate.ai/docs - ReDoc: https://districts.nominate.ai/redoc - OpenAPI JSON: https://districts.nominate.ai/openapi.json
Contact¶
For API issues or feature requests, contact the cbdistricts team or file an issue in the repository.