Documentation
API Endpoints
Data Types
We don't want there to be any surprises when you're using our API, so we have defined the specific data formats you'll see across our API below. In general, you will be linked back here from elsewhere, so feel free to skip right to reading the full documentation for the API Endpoints.
- Response
- Error Response
- Election (on separate page)
- Precinct (on separate page)
- Contest (on separate page)
- ExtraObject
- ObjectType
- OCD-ID
- String
- URL
- Date
- DateTime
- DateTimeRange
- Coordinates
- GeoJSON
Response object
Response objects contain a list of data results, as well as any extra
aggregated data and some meta-data about the request. In general, this
will be the response format for any list API endpoints (e.g.
/elections
), where the data list are the API request results.
Also, if you request that some additional sub-queries be included with your
results (e.g. include=contests
), those includes will be
contained within another Response object.
Response example
{ "type": "response", "data": [...], "next": null, "extra": {}, "timestamp": "2018-01-01T00:00:00+00:00", "url": "https://api.ballotapi.org/...", }
Response attributes
Attribute | Format | Description | Example |
---|---|---|---|
type
|
ObjectType | This object's data type. Will always be "response". |
"response"
|
data
|
List(Election | Contest | Precinct) | The actual response content for the API request. Will be a list of whatever particular endpoint object is being queried. |
[{"type": "election", ...}, ...]
|
next
|
URL or null
|
If there are more data objects in the results, this will
be a url to the next page of results. If there are no
more results, this will be null .
|
"https://api.ballotapi.org/..."
|
extra
|
ExtraObject |
If an extra parameter was included in the
api request, this object will contain the results of
that extra parameter. If no extra parameter was given,
this will be an empty object (i.e. {} ).
|
{"merge_geos": {"type": "MultiPolygon", ...}}
|
timestamp
|
DateTime | The datetime at which the results were generated. Since results are often cached, this timestamp won't necessarily be close to the current time, but we do invalidate caches when data changes, so you will always be receiving the latest available results. |
"2018-01-23T04:55:12+00:00"
|
url
|
URL | The API request that was performed to produce the results. If you included extra request parameters that we didn't recognize, they will be ignored, so this is helpful to compare against to see if you got the parameters right for your API request. |
"https://api.ballotapi.org/..."
|
...
|
We may add additional attributes in the future, so be able to unknown attributes. |
Error Response object
These are responses that are returned when something you requested raised an error. The most common case you will see these is when the query parameters you set in your request are malformed and you get back a 400 HTTP response code.
Error Response example
{ "error": "invalid_param", "message": "You need to specify a timezone for each datetime in your 'dates' parameter.", "docs": "https://ballotapi.org/docs/data-types#datetime-range" }
Error Response attributes
Attribute | Format | Description | Example |
---|---|---|---|
error
|
String |
The error type raised. Usually something like
invalid_param , but could be any string.
|
"missing_param"
|
message
|
String | A human-readable error message describing what caused the error. We try to make our error messages clear so you know exactly what went wrong. Please feel free to reach out to us if you think an error message is confusing! |
"Your 'coords' parameter doesn't look like coordinates (e.g. '12.2928,-84.7573')"
|
docs
|
URL or null
|
A link to the documentation where you can find more information.
We try to include links to docs for each error, but sometimes we
haven't set that link yet, so this attribute may be null .
|
"https://ballotapi.org/docs/api/elections/list#include"
|
Extra object
The Extra object is an object in Response objects
that contain attributes requested via extra
parameters. The data in this object are usually aggregated from the
results. For example, if you specify extra=merge_geos
in a
request, the Extra object will contain the merge_geos
attribute with the merged geography of the results in the Response
data
attribute.
Extra object example
{ "merge_geos", { "type": "MultiPolygon", ... }, ... }
Extra object attributes
Attribute | Format | Description | Example |
---|---|---|---|
...
|
Extra object attributes can be any value that is defined
in the extra request parameters for the
various API Endpoints.
|
ObjectType
For complex data objects returned by the API, there is a defined object type value that lets you know what kind of object it is.
ObjectType values
Value | Format | Description |
---|---|---|
"response"
|
String | Will be the object type for Response objects. |
"election"
|
String | Will be the object type for Election objects. |
"precinct"
|
String | Will be the object type for Precinct objects. |
"contest"
|
String | Will be the object type for Contest objects. |
"choice"
|
String | Will be the object type for Choice objects (these are included in Contest objects). |
...
|
We may add additional object types in the future, so be able to unknown object type values. |
OCD-ID
These are Open Civic Data Identifiers (OCD-ID), which is an open standard for giving unique identifiers for civic information, such as localities, elected officials, or jurisdictions. When available, we include the OCD-ID in our API so you can map our data to other civic database that also use OCD-ID.
OCD-ID Example
"ocd-jurisdiction/country:us/state:ex/place:example/legislature"
String
These are arbitrary strings of text. In API responses, they are encoded in UTF-8 . In URL parameters, they are percent encoded .
UTF-8 Example
"ὁ ἄνθρωπος φύσει πολιτικὸν ζῷον —Aristotle"
Percent Encoded Example
"Man%20is%20by%20nature%20a%20political%20animal%20%E2%80%94Aristotle"
URL
This is a URL that points to somewhere on the API. We do not link to external resources.
URL Example
"https://api.ballotapi.org/v1/elections?dates=now,future"
Date
This is a
ISO-8601
date (e.g. YYYY-MM-DD
). There is no timezone associated
with dates, so if timezone is important, use DateTime.
Date Example
"2018-01-23"
DateTime
This is a
ISO-8601
combined date and time with timezone (e.g. YYYY-MM-DDTHH:MM:SS+00:00
).
All API response datetimes have a timezone. If you provide a datetime in
a request parameter, be sure to specify the timezone offset (so we can
know how to compare it to other datetimes).
DateTime Example
"2018-01-23T22:55:12-08:00"
DateTimeRange
This is a timespan between two DateTimes or special values, separated
by a comma (,
). There are also special formats that allow you to easily build
dynamic ranges you can re-use without having to build new datetimes.
Formats accepted:
-
YYYY-MM-DDTHH:MM:SS+00:00
- ISO 8601 DateTime -
now
- the current time -
future
- anytime after the current time -
past
- anytime before the current time -
+{N}d
- a number of days (24 hours) after the current time (e.g.+30d
) -
-{N}d
- a number of days (24 hours) before the current time (e.g.-365d
)
DateTimeRange Examples:
Valid: "2018-01-01T00:00:00-08:00,2019-01-01T00:00:00-08:00" (all of 2018 in PST Timezone) "now,future" (everything going forward) "past,now" (everything prior to now) "-365d,+30d" (everything in the past year and in the next 30 days) "2016-11-08T00:00:00-05:00,now" (everything since Nov 8, 2016 EST up to now) Invalid: "2018-01-01,2019-01-01" (dates without timezones aren't allowed) "365d,now" (day values need to have a "+" or "-") "now," (need two values in the range, if you need open ended, use "past" and "future")
Coordinates
These are a single point or area of
geographic coordinates
.
Single coordinates are a comma separated latitude, longitude pair
(e.g. "{lat},{lon}"
). Areas are semicolon separated
single coordinates (e.g. "{lat},{lon};{lat},{lon};..."
),
where the area is the polygon created by the list of single coords (the
first and last coords are assumed to connect, so you don't have to copy
the first the coord at the end).
Coordinates Example
(Ferry Building, San Francisco, CA) "37.795508,-122.393478" (Treasure Island, CA) "37.832225,-122.373404;37.830429,-122.377653;37.826768,-122.379198;37.815751,-122.371687;37.818632,-122.364521;37.820565,-122.363705;37.819785,-122.360444;37.820124,-122.360444;37.820870,-122.363491;37.822565,-122.362890;37.831073,-122.368597"
Converting addresses to coordinates
If you don't have coordinates, but instead have addresses, you will need to use a geocoding service to convert the addresses into coordinates. Geocoding is not built into BallotAPI by default because it is quite complex, and we don't want to have to spend all of our time maintaining a geocoding service when our focus is ballot data. Also, there are already many services that do geocoding quite well, so we don't feel the need to re-invent the wheel or try to figure out how to include a geocoding service as part of a public-domain project.
Here are some free geocoding resources:
Here are some paid geocoding services:
GeoJSON
These are GeoJSON : objects. You will see mostly Polygon and Multipolygon objects that outline district or precinct boundaries.
GeoJSON Example
Treasure Island, CA:
{ "type": "Polygon", "coordinates": [ [ [-122.37340450,37.83222583], [-122.37765312,37.83042938], [-122.37919807,37.82676854], [-122.37168788,37.81575104], [-122.36452102,37.81863270], [-122.36370563,37.82056504], [-122.36044406,37.81978533], [-122.36044406,37.82012433], [-122.36349105,37.82087014], [-122.36289024,37.82256513], [-122.36859798,37.83107340], [-122.37340450,37.83222583] ] ] }
Did we miss a data type? Please open an issue or pull request