Changelog
What changed in the API, newest first. New fields and parameters are added without notice, so ignore fields you don’t know. Anything that could break a client is marked Changed or Removed.
November 13, 2026
- Election results: every contest has a
resultonce a source publishes one (status, total votes, precincts, the source and its URL, ranked-choice rounds, write-ins), and every choice hasresultwith itsvotes,vote_pctandwinner. InGET /v1/contests,GET /v1/contests/{id}, the election export (JSON, and new result columns at the end of the CSV),GET /v1/candidatesandGET /v1/candidates/{id}. See Election results. has_resultandresult_statusesonGET /v1/contests, andresult_countonGET /v1/elections.- Past elections, starting with the November 5, 2024 general election, with their results:
details.historicalmarks them. - Contests:
office(the office, normalized across states, with its level and branch of government),race_type(regular,special,recallorretention),partisan, andtopicson measures. Newofficesandtopicsfilters onGET /v1/contests, andGET /v1/measure-topicslists the topics. - Candidates:
namein parts (given, middle, family, suffix, nickname),ids(FEC and Congress bioguide ids for federal candidates),contact(website and social accounts from Wikidata, the campaign committee’s FEC mailing address, and what the campaign publishes on its own site, each with its source), andfinance(FEC totals) onGET /v1/candidates/{id}. - Choices:
endorsement_count, how many endorsers back each candidate or each Yes and No answer. - Endorsements:
stage(general,primaryorrunoff).
November 12, 2026
- Candidate issue positions: where candidates stand on common issues (abortion, guns, immigration, schools, the safety net, taxes, tariffs and more), each with a neutral summary, their own words where we have them, and the links it came from.
GET /v1/issueslists the issues,GET /v1/issue-positionslists positions by issue, stance, candidate, contest, election or state, andGET /v1/candidates/{id}has a newissue_positionsfield. - Changed: request rate limits are back. Each account has a per-minute limit and a daily cap (UTC) shared by its keys, and a number of open streams, set by its plan: 600 a minute and 200,000 a day for every purchase. Every response carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset(andX-Daily-Limit/X-Daily-Remaining); over a limit is a429withRetry-After. The client libraries wait and retry for you. See keys, limits and errors.
November 11, 2026
- Measures:
ballot_text(the wording as printed on the ballot),full_text_url, andvote_meaningon each Yes and No choice. - Candidates:
incumbenton each choice (true,false, ornullwhere we don’t know yet), in the API and in Endorsement Stream events. - Contests:
unopposed, andparty_lines_unverifiedandquestion_wordingindetails. GET /v1/endorsements/{id}/history: every change to an endorsement, with the values before and after, including its deletion.changed_sinceonGET /v1/endorsements, to sync only what’s new.GET /v1/changes: every endorsement added, changed or deleted since a time, with the values before and after.GET /v1/candidatesandGET /v1/candidates/{id}: search candidates, and every endorsement each one received.GET /v1/elections/{slug}/export: a whole election in one download, as JSON or CSV.added_byon every endorsement (automatic,staffordata_load), andendorsement_idon each pick inGET /v1/contests/{id}.- Endorsement Stream:
endorsement.updatedevents carrychangedandprevious(the values before the change), and every event carriesendorsement.added_by. min_endorsementsonGET /v1/endorsers, andendorsement_countonGET /v1/endorsers/{slug}.- Changed: an endorser’s
endorsement_countnow counts contests, so a ranked-choice order or a vote-for-N slate counts once, as on endorsedby.org. It used to count each pick.
October 28, 2026
- Every parameter is described with an example, and each reference entry has a sample using every parameter.
October 26, 2026
- The ballotdata client libraries for JavaScript and Python.
October 24, 2026
- Changed:
GET /v1/endorsementslists the basics of each endorsement;GET /v1/endorsements/{id}has the full record. - No request rate limits.
October 22, 2026
- Removed: the combined per-contest view.
GET /v1/contests/{id}has every endorser’s position in a contest. - Keys and the stream read only what the account bought; asking for a state outside it is a
403 outside_purchase. - Every error carries a
request_id, also sent as theX-Request-Idheader.
October 20, 2026
- The API moved to
api.ballotdata.ai.
October 16, 2026
- Removed: address, ZIP, district and representative lookups. Choose contests by state, election or id.
October 15, 2026
- First release: elections, contests, endorsers, endorsements, officeholders, coverage, Spanish ballot text and the Endorsement Stream.