Query layer
REST
Data LiveAPI PlannedFixed, cacheable endpoints for the questions almost everyone asks, with predictable shapes and no query language required.
Endpoints
| Endpoint | Returns | Key parameters |
|---|---|---|
GET /v1/districts_by_point | Every district containing a coordinate | lat, lng |
GET /v1/districts_by_address | The same, from a postal address | address |
GET /v1/ballot | The full ballot for a point on a date | lat, lng, date |
GET /v1/contests | Contests, filtered | state, level, date |
GET /v1/candidacies | Candidacies, filtered | contest, state, party |
GET /v1/officeholders | Who currently holds an office | office, region |
GET /v1/results | Certified results with vote shares | contest |
GET /v1/election_dates | Upcoming election dates | state, from, to |
Resolve a ballot from a coordinate
The lookup runs against real district boundaries rather than an approximate mapping from postal codes, and no third-party district service is involved.
{
"point": { "lat": 33.4484, "lng": -112.0740 },
"regions": [
{ "slug": "region:az-state", "name": "Arizona", "level": "state" },
{ "slug": "region:az-maricopa-county", "name": "Maricopa County", "level": "county" },
{ "slug": "region:az-congressional-district-3",
"name": "Arizona's 3rd Congressional District",
"level": "congressional-district" }
],
"contests": [
{
"slug": "contest:az-us-house-03-2026-general",
"office": "U.S. Representative (Arizona, District 3)",
"date": "2026-11-03",
"candidacies": [
{ "person": "…", "party": "Democratic Party", "is_incumbent": true, "confidence": 0.85 }
]
}
]
}Conventions
- Pagination is cursor-based. Pass the
cursorvalue fromnext_cursoruntil it comes back null. - Confidence filtering works everywhere. Set
min_confidenceon any endpoint, and leave it at the default of zero to see everything with its score attached. - Versioning is by date header. Setting
Civoren-Versionpins your response shapes, and within a version changes are only ever additive, so a new field never breaks an existing integration. - Caching uses standard headers. Geographic endpoints hold for a day and candidacy endpoints for five minutes, both revalidating conditionally so an unchanged response costs almost nothing.
- Errors name the problem. Every error carries a stable machine-readable type, a human-readable explanation, and the offending field itself rather than a hint about it.