Query layer
GraphQL
Data LiveAPI PlannedA typed schema over the same graph, for teams that want field selection, code generation and a stable contract without writing traversals themselves.
Schema
Node kinds become types and edge kinds become fields, with the full schema served from the endpoint and readable by any standard client.
type Candidacy {
slug: ID!
name: String!
person: Person!
contest: Contest!
party: Party
isIncumbent: Boolean
filingStatus: FilingStatus
ballotAccess: BallotAccess
campaignWebsite: URL
"""Requires the `contact` entitlement."""
campaignEmails: [EmailAddress!]!
positions: [Position!]!
"""Every source this candidacy's fields were drawn from."""
provenance: [Provenance!]!
confidence: Float!
}
type Query {
contests(state: StateCode!, level: Level, electionDate: Date): [Contest!]!
candidacy(slug: ID!): Candidacy
districtsAtPoint(lat: Float!, lng: Float!): [Region!]!
ballotAtPoint(lat: Float!, lng: Float!, date: Date!): [Contest!]!
}Example
query ArizonaCountyRaces {
contests(state: "AZ", level: COUNTY, electionDate: "2026-11-03") {
slug
office { name level }
region { name fips population }
candidacies {
person { name }
party { name }
isIncumbent
confidence
}
}
}Depth and complexity are budgeted. Queries are scored before they run and rejected above your plan's ceiling with an error naming the offending path, since heavy aggregate work belongs in Cypher or a bulk export instead.