Ballots for developers
Python HTML
Switch branches/tags
Nothing to show

README.md

#Ballot API - Ballots for developers

NOTE: THIS PROJECT IS NOT LIVE YET. SEE PROGRESS AT GITHUB.

Use it here: http://www.ballotapi.com/api/ (doesn't work yet)

##Table of Contents

  1. What is Ballot API?
  2. Why make Ballot API?
  3. How do you use Ballot API?
  4. Current Status
  5. Authentication
  6. Response Formats
  7. Object Formats
  8. Election
  9. Precinct
  10. Measure
  11. Choice
  12. API Reference
  13. /elections/<id>
  14. /elections
  15. /precincts/<id>
  16. /precincts
  17. /measures/<id>
  18. /measures
  19. How to self-host
  20. License
  21. Contributions

##What is Ballot API? Ballot API is a database that contains information for what is on voting ballots for each election. You can query based on location to see the ballot for that location. Alternatively, you can query based on measure to see the precincts that contain that measure.

##Why make Ballot API? The purpose of this project is to make it easier to see what will be on your ballot before you go vote. Most ballot databases are either local to their particular jurisdiction (e.g. local county registrar of voters) or only contain higher level measures (e.g. national measures/contests only). This project aims to be a comprehensive source of ballot information for all levels of government.

##How do you use Ballot API? There are three ways to use the Ballot API. First, you can browse the database by visiting http://www.ballotapi.com/api/ in a web browser. Second, you can make API requests to http://www.ballotapi.com/api/ endpoints that are documented below. Third, you can copy this repository to self-host the database and make requests via either of the two methods described above to your self-hosted repo (see "How to self-host" below on how to do this).

##Current Status This project is in active development. Please file issues if you find bugs or want to request changes.

  • API docs - done
  • Database schema - done
  • Test cases
  • API implementation (json) - in development
  • API implementation (html)
  • Demo webapp - in development
  • Continuous integration
  • Status reports
  • Database population
  • User experience refinement

##Authentication All requests are open to the public and do not need authentication.

##Response Formats If you request an individual object (e.g. /elections/123), you will receive just that object (see Object Formats). If you request a list of objects (e.g. /elections?dates=2014-01-01:2014-12-31), you will recieve a paginated list of objects in the following format:

{
    "offset": 0, //where in the results this data list starts
    "data": [
        <json_object>,
        <json_object>,
        ...
    ]
}

Any API endpoint that returns a list of objects will accept optional limit=<int> and offset=<int> parameters in the request. See each endpoint for the default values of these parameters.

##Object Formats There are three base object formats: Election, Precinct, and Measure. Inside the Precinct object, the "geo" field contains a GeoJSON object. Inside the Measure object, the "choices" field contains a list of Choice objects. The rest of the fields in all base objects are either integers or strings.

###Election Election objects contains information on a particular election.

{
    "id": 123,     //unique id for this Election (integer)
    "date": "...", //date of the election (e.g. "2014-11-04") (YYYY-MM-DD)
    "info": "..."  //generic information on the election (string)
}

###Precinct Precinct objects contain information for a particular geographical area. They are the lowest common denominator for ballot measures in a particular election, so any location with that Precinct will have the same list of ballot measures. NOTE: Precincts are unique across elections, so you cannot use the same Precinct id for a different Election (since Precinct boundaries change over time). The "info" field may be the same, but is not guaranteed to be. Tracking precinct changes across Elections is outside of the scope of this project.

{
    "id": 123,          //unique id for this Precinct (integer)
    "election_id": 123, //unique id for this Precinct's Election (integer)
    "measures": [...],  //list of Measure ids that will be (list of integers)
    "confirmed": "...", //date the measures list was confirmed to be accurate (YYYY-MM-DD or null)
    "info": "...",      //generic information about the Precinct (string)
    "geo": {...}        //the boundary for this Precinct (GeoJSON object)
}

###Measure Measure objects contain information on ballot measures and contests.

{
    "id": 123,              //unique id for this Measure (integer)
    "election_id": 123,     //unique id for this Measure's Election (integer)
    "precincts": [...],     //list of Precinct ids that are (list of integers)
    "title": "...",         //title of the measure (string)
                            //(e.g. "Water and Rail Supervisor - District 23")
    "question": "...",      //question that the voter is asked to answer (string)
                            //(e.g. "Choose one of the following candidates.")
    "info": "...",          //generic information about the measure (string)
                            //(e.g. "This seat oversees the budgets of ...")
    "short_info": "...",    //<100 character version of the info field (string)
                            //(e.g. "This seat manages agriculture departments.")
    "type": "...",          //the type of measure (see Measure Type)
    "voting_method": "...", //the method of voting (see Voting Method)
    "threshold": "...",     //the threshold needed for a choice to win (see Threshold)
    "choices": [...],       //list of choices for the measure (list of Choice objects)
}

####Measure Type These are the types of measure (i.e. what kind of question is being asked). They will be one of the following strings:

  • "election" - voting is to elect a person or party
  • "measure" - voting is to decide on a specific initiative or policy

####Voting Method These are the voting methods for measures, which are the voting system used for the choices. The API is agnostic to what kind of entity or contest is actually being voted on (person, party, bond measure, etc.).

  • "plurality" - choose one choice
  • "approval" - choose all choices that you approve
  • "instant-runoff" - choose first and second choices
  • "ranked" - sort choices in order of preference (first is most preferred)

####Threshold These are the winning threshold requirements that the measure. The values in this field are strings because thresholds are often not as simple as a given number or percentage.

  • "1/2 + 1" - A majority is required (i.e. more than 50% of votes)
  • "2/3 + 1" - A two-thirds majority is required (i.e. more than 67% of votes)
  • "max, >30%" - The most voted for choice, and that choice has to win over 30% of all votes.
  • Need more. Please pull request!

###Choice Choice objects contain the details for each item in the choices list of the Measure object. They do not have unique ids because they are always include in the Measure object.

{
    "title": "...",       //title of the choice (e.g. "John Smith") (string)
    "info": "...",        //generic information about the choice (string)
}

##API Reference All Ballot API endpoints respond to only GET requests (i.e. read-only). There are json and html formats for every endpoint. You can specify which format by appending ".json" or ".html" to the end of the endpoint.

###/elections/<id> Return the Election object for the specified id.

Examples:

  1. Elections 1:
    http://www.ballotapi.com/api/elections/1

###/elections Returns a list of Election objects. Can be filtered by id, location, or date.

####?ids=<id>[,<id>,...] Return elections filtered to only these comma separated ids. This is just the plural form of the /elections/<id> endpoint.

Examples:

  1. Elections 1 and 2:
    http://www.ballotapi.com/api/elections?ids=1,2

####?coords=<latitude>,<longitude> Return only elections that include precincts that contain this location.

Examples:

  1. All the elections for 100 Market St, San Francisco, CA (37.7942635,-122.3955861):
    http://www.ballotapi.com/api/elections?coords=37.7942635,-122.3955861

####?election_dates=<start_date>[:<end_date>[,...]] Return only elections within a certain date range. You can omit either the start or end dates to leave that side open ended. Dates are inclusive, so results include elections that happen on the start or end dates. You can also specify a single date, which is the equivalent to specifying that date as both the start and end date. You can also have multiple date ranges, separated by commas.

Examples:

  1. The national elections in 2016 and 2020:
    http://www.ballotapi.com/api/elections?election_dates=2016-11-04,2020-11-04

  2. All the elections for 2014:
    http://www.ballotapi.com/api/elections?election_dates=2014-01-01:2014-12-31

  3. All elections after Nov 4th, 2014 for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/elections?election_dates=2014-11-05:2050-11-05&coords=37.7942635,-122.3955861

####?limit=<int> Limit results to a set number. By default, the limit value for elections is 100.

####?offset=<int> Start the list of results at an offset. By default, the offset value is 0 (e.g. start the results at the beginning).

###/precincts/<id> Return the Precinct object for the specified id.

Examples:

  1. Precinct 1:
    http://www.ballotapi.com/api/precincts/1

###/precincts Return a list of precincts. Can be filtered by id, election, election date, location, or measure.

####?ids=<id>[,<id>,...] Return precincts filtered to only these comma separated ids. This is just the plural form of the /precincts/<id> endpoint.

Examples:

  1. Precincts 1 and 2: http://www.ballotapi.com/api/precincts?ids=1,2

####?elections=<id>[,<id>,...] Return only precincts that are part of these elections. Multiple elections can be listed as comma separated ids, which will return precincts that contain any of the listed elections (i.e. treated as OR).

Examples:

  1. The precincts that contain Election 1:
    http://www.ballotapi.com/api/precincts?elections=1

  2. The precincts that contain Election 1 or 2 for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/precincts?elections=1,2&coords=37.7942635,-122.3955861

####?election_dates=<start_date>[:<end_date>[,...]] Return only precincts that belong to elections within a certain date range. You can omit either the start or end dates to leave that side open ended. Dates are inclusive, so results include elections that happen on the start or end dates. You can also specify a single date, which is the equivalent to specifying that date as both the start and end date. You can also have multiple date ranges, separated by commas.

Examples:

  1. All the precincts for elections in 2014:
    http://www.ballotapi.com/api/precincts?election_dates=2014-01-01:2014-12-31

  2. All the precincts for elections after Nov 4th, 2014 for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/precincts?election_dates=2014-11-05:2050-11-05&coords=37.7942635,-122.3955861

####?coords=<latitude>,<longitude> Return only precincts that contain this location.

Examples:

  1. The Election 1 precinct for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/precincts?elections=1&coords=37.7942635,-122.3955861

####?measures=<id>[,<id>,...] Return only precincts that contain these measures. Multiple measures can be listed as comma separated ids, which will return precincts that contain any of the listed measures (i.e. treated as OR). Multiple measures parameters will intersect the precincts returned by each measures parameter (i.e. treated as AND).

Examples:

  1. The precincts that contain Measure 2:
    http://www.ballotapi.com/api/precincts?measures=2

  2. The precincts that contain Measures 2 or 3, and contains Measure 1:
    http://www.ballotapi.com/api/precincts?measures=2,3&measures=1

####?limit=<int> Limit results to a set number. By default, the limit value for precincts is 50.

####?offset=<int> Start the list of results at an offset. By default, the offset value is 0 (e.g. start the results at the beginning).

###/measures/<id> Return the Measure object for the specified id.

Examples:

  1. Measure 1:
    http://www.ballotapi.com/api/measures/1

###/measures Return a list of measures. Can be filtered by id, election, election date, location, or precinct.

####?ids=<id>[,<id>,...] Return measures filtered to only these comma separated ids. This is just the plural form of the /measures/<id> endpoint.

Examples:

  1. Measures 1 and 2:
    http://www.ballotapi.com/api/measures?ids=1,2

####?elections=<id>[,<id>,...] Return only measures that are part of these elections. Multiple elections can be listed as comma separated ids, which will return measures that contain any of the listed elections (i.e. treated as OR).

Examples:

  1. The measures that are in Election 1:
    http://www.ballotapi.com/api/measures?elections=1

  2. The measures that contain Election 1 or 2 for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/measures?elections=1,2&coords=37.7942635,-122.3955861

####?election_dates=<start_date>[:<end_date>[,...]] Return only measures that belong to elections within a certain date range. You can omit either the start or end dates to leave that side open ended. Dates are inclusive, so results include elections that happen on the start or end dates. You can also specify a single date, which is the equivalent to specifying that date as both the start and end date. You can also have multiple date ranges, separated by commas.

Examples:

  1. All the measures for elections in 2014:
    http://www.ballotapi.com/api/measures?election_dates=2014-01-01:2014-12-31

  2. All the measures for elections after Nov 4th, 2014 for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/measures?election_dates=2014-11-05:2050-11-05&coords=37.7942635,-122.3955861

####?coords=<latitude>,<longitude> Return only measures that have a precinct encompassing this location.

Examples:

  1. The Election 1 measures for 100 Market St, San Francisco, CA:
    http://www.ballotapi.com/api/measures?elections=1&coords=37.7942635,-122.3955861

####?precincts=<id>[,<id>,...] Return only measures that are a part of these precincts. Multiple precincts can be listed as comma separated ids, which will return measures that are a part of any of the listed precincts (i.e. treated as OR). Multiple precincts parameters will intersect the measures returned by each precincts parameter (i.e. treated as AND).

Examples:

  1. The measures that contain Precinct 1:
    http://www.ballotapi.com/api/measures?precincts=1

  2. The measures that are a part of Precinct 1 or 2, and a part of Precinct 3:
    http://www.ballotapi.com/api/measures?precincts=1,2&precincts=3

####?limit=<int> Limit results to a set number. By default, the limit value for measures is 100.

####?offset=<int> Start the list of results at an offset. By default, the offset value is 0 (e.g. start the results at the beginning).

##How to self-host Want to set up your own mirror of this API? Great! Here's how:

  1. Download this repo.
  2. Install the prerequisites:
  • PostgreSQL
  • PostGIS
  • Python
  • Psycopg
  1. Add the database user.
  2. Import the database.
  3. Start the API server.
  4. Try it out! http://localhost:8000/api/

To update to the latest version of the API, simply re-download this repo and re-import the database.

##License This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to http://unlicense.org

##Contributions This project is hosted https://github.com/sfbrigade/ballotapi and maintained by a team at Code for America. Want to contribute? Submit an issue or pull request!