Democracy Club Developer API ¶
This API is currently in private beta. All requests must be made with an API key. If you're interested in working with the data, contact us for an API key. Usage must comply with our terms of use.
Postcode search ¶
The /postcode
and /address
endpoints find details of ballots, candidates and polling stations based on the user's registered address. This allows you to present Democracy Club's data to users in your website or app.
The entry point to a polling station search is a call to the /postcode
endpoint.
A valid postcode search may result in one of 3 outcomes:
No upcoming ballots: There are no upcoming ballots relevant to this area.
Results found: We hold data for this area and the same ballots, candidates and polling station data is relevant to all registered addresses with this postcode.
Address picker: We hold data for this area but different information is applicable to different addresses with this postcode. To find relevant data, we must show the user an address picker and make a second API call to the
/address
endpoint.
Postcode search: No upcoming ballots ¶
/postcode/{postcode}
Parameters
postcode
string
( required )Whitespace in postcodes is ignored, so format may be
SW1A1AA
orSW1A 1AA
Example:
SW1A1AA
Postcode search: No upcoming ballots ¶
Example of a response when there are no upcoming ballots.
In this case address_picker
is false
and dates
is an empty array.
/postcode/{postcode}
200
Content-Type: application/json
{
"address_picker": false,
"addresses": [],
"dates": [],
"electoral_services": {
"council_id": "W06000015",
"name": "Cardiff Council",
"nation": "Wales",
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"registration": {
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"postcode_location": {
"type": "Feature",
"properties": null,
"geometry": {
"type": "Point",
"coordinates": [
-3.113797,
51.521175
]
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"address_picker": {
"type": "boolean",
"description": "True if we need to show this user an address picker"
},
"addresses": {
"type": "array",
"description": "An array of address objects containing the addresses applicable to this request (if necessary)"
},
"dates": {
"type": "array",
"description": "An array of date objects containing details of relevant ballots, candidates and polling station information"
},
"electoral_services": {
"type": [
"object",
"null"
],
"properties": {
"council_id": {
"type": "string",
"description": "GSS code for this council"
},
"name": {
"type": "string",
"description": "Name of this council"
},
"nation": {
"type": "string",
"description": "Name of nation"
},
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Contact details for the user's local Electoral Services team. If we do not know the user's polling station, this can be used to provide contact info for their local council. This may be `null` if we are not able to determine the user's council."
},
"registration": {
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Sometimes the contact information for registration and proxy voting is different to the electoral services contact details. Use these if they exist and your users might have questions about voter registration. If this key is null, assume the electoral services contact details can be used for electoral registration related enquiries."
},
"postcode_location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"properties": {
"type": [
"object",
"null"
],
"properties": {}
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) containing a [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) describing the centroid of the input postcode. If providing a map or directions for a polling station journey, use this as the start point. This may be `null` if we are not able to accurately geocode."
}
}
}
Postcode search: Results found ¶
/postcode/{postcode}
Parameters
postcode
string
( required )Whitespace in postcodes is ignored, so format may be
SW1A1AA
orSW1A 1AA
Example:
SW1A1AA
Postcode search: Results found ¶
Example of a response when we hold data for this area and the same ballots, candidates and polling station data is relevant to all registered addresses with this postcode.
In this case address_picker
is false
and dates
is an array of date objects.
/postcode/{postcode}
200
Content-Type: application/json
{
"address_picker": false,
"addresses": [],
"dates": [
{
"date": "2017-05-04",
"polling_station": {
"polling_station_known": true,
"custom_finder": null,
"report_problem_url": "http://wheredoivote.co.uk/report_problem/?source=testing&source_url=testing",
"station": {
"id": "w06000015.QK",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-3.119229,
51.510885
]
},
"properties": {
"postcode": "",
"address": "Earlswood Social Club, 160-164 Greenway Road, Rumney"
}
}
},
"advance_voting_station": {
"name": "",
"address": "",
"postcode": "",
"location": {
"type": "Point",
"coordinates": [
-3.119229,
51.510885
]
},
"opening_times": [
[
"date",
"open",
"close"
]
]
},
"notifications": [
{
"title": "Some unexpected event is happening",
"type": "cancelled_election",
"detail": "Some more details",
"url": "https://foo.bar/baz"
}
],
"ballots": [
{
"ballot_paper_id": "local.cardiff.pontprennauold-st-mellons.2017-05-04",
"ballot_title": "Cardiff local election Pontprennau/Old St. Mellons",
"ballot_url": "https://developers.democracyclub.org.uk/api/v1/local.cardiff.pontprennauold-st-mellons.2017-05-04/",
"poll_open_date": "2017-05-04",
"elected_role": "Local Councillor",
"metadata": null,
"cancelled": false,
"cancellation_reason": "null",
"replaced_by": null,
"replaces": null,
"election_id": "local.cardiff.2017-05-04",
"election_name": "Cardiff local election",
"post_name": "Pontprennau/Old St. Mellons",
"candidates_verified": false,
"voting_system": {
"slug": "FPTP",
"name": "First-past-the-post",
"uses_party_lists": false
},
"hustings": [
{
"title": "",
"url": "",
"starts": "",
"ends": "",
"location": "",
"postevent_url": ""
}
],
"seats_contested": 1,
"candidates": [
{
"list_position": null,
"party": {
"party_id": "party:90",
"party_name": "Liberal Democrats"
},
"previous_party_affiliations": [
{
"party_id": "party:90",
"party_name": "Liberal Democrats"
}
],
"person": {
"ynr_id": 23417,
"name": "David Keigwin",
"absolute_url": "https://whocanivotefor.co.uk/person/23417/david-keigwin",
"email": "dave@example.com",
"photo_url": null,
"leaflets": [
{
"leaflet_id": 0,
"thumb_url": "",
"leaflet_url": ""
}
]
}
},
{
"list_position": null,
"party": {
"party_id": "party:52",
"party_name": "Conservative and Unionist Party"
},
"person": {
"ynr_id": 8071,
"name": "Joel Williams",
"absolute_url": "https://whocanivotefor.co.uk/person/8071/joel-williams",
"email": null,
"photo_url": "https://static-candidates.democracyclub.org.uk/media/images/images/8071.png"
}
}
],
"wcivf_url": "https://whocanivotefor.co.uk/elections/local.cardiff.2017-05-04/post-UTE:W05000900/pontprennauold-st-mellons"
}
]
}
],
"electoral_services": {
"council_id": "W06000015",
"name": "Cardiff Council",
"nation": "Wales",
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"registration": {
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"postcode_location": {
"type": "Feature",
"properties": null,
"geometry": {
"type": "Point",
"coordinates": [
-3.113797,
51.521175
]
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"address_picker": {
"type": "boolean",
"description": "True if we need to show this user an address picker"
},
"addresses": {
"type": "array",
"description": "An array of address objects containing the addresses applicable to this request (if necessary)"
},
"dates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "Polling day on which an election will occur"
},
"polling_station": {
"type": "object",
"properties": {
"polling_station_known": {
"type": "boolean",
"description": "Do we know where this user should vote?"
},
"custom_finder": {
"type": [
"string",
"null"
],
"description": "If we don't know a user's polling station, sometimes we can provide the URL of another polling station finder. This will always be populated for users in Northern Ireland where Electoral Office for Northern Ireland run their own service."
},
"report_problem_url": {
"type": [
"string",
"null"
],
"description": "If we provide a polling station result, this URL may be used to provide a user with a back-channel to report inaccurate data."
},
"station": {
"type": [
"object",
"null"
],
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"geometry": {
"type": [
"object",
"null"
],
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
},
"description": "A GeoJSON [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) object describing the location of this polling station. Optionally null if we know the address only but can't geocode a location."
},
"properties": {
"type": "object",
"properties": {
"postcode": {
"type": "string",
"description": "Postcode for this polling station"
},
"address": {
"type": "string",
"description": "Address for this polling station"
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) describing the user's polling station (if known)"
}
},
"description": "Results for polling station search"
},
"advance_voting_station": {
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the Advance Voting Station"
},
"address": {
"type": "string",
"description": "The address of the Advance Voting Station"
},
"postcode": {
"type": "string",
"description": "The postcode of the Advance Voting Station"
},
"location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
},
"description": "A GeoJSON [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) object describing the location of this Advance Voting Station."
},
"opening_times": {
"type": "array",
"items": {
"type": "array"
}
}
},
"required": [
"name",
"address",
"postcode",
"location",
"opening_times"
],
"additionalProperties": false,
"description": "Advance Voting Stations"
},
"notifications": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"cancelled_election",
"voter_id"
],
"description": "Type of notification"
},
"detail": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"description": "Array of notifications to be shown to the user about special conditions to be aware of on this date."
},
"ballots": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ballot_paper_id": {
"type": "string",
"description": "Identifier for this ballot"
},
"ballot_title": {
"type": "string",
"description": "Friendly name for this ballot"
},
"ballot_url": {
"type": "string",
"description": "API link for more detailed info about this ballot from the /elections endpoint"
},
"poll_open_date": {
"type": "string",
"description": "Polling day for this ballot (ISO 8601)"
},
"elected_role": {
"type": "string",
"description": "Name of the role the winner(s) of this election will assume"
},
"metadata": {
"type": [
"object",
"null"
],
"properties": {},
"description": "Object containing information about special conditions for the user to be aware about (e.g: cancelled elections, voter id pilot). (details TBC)"
},
"cancelled": {
"type": "boolean",
"description": "True if this ballot has been cancelled"
},
"cancellation_reason": {
"type": [
"string",
"null"
],
"enum": [
"NO_CANDIDATES",
"EQUAL_CANDIDATES",
"UNDER_CONTESTED",
"CANDIDATE_DEATH",
"null",
null
],
"description": "If a ballot has been cancelled, this key may hold a codified reason for that ballot's cancellation"
},
"replaced_by": {
"type": [
"string",
"null"
],
"description": "If a ballot has been cancelled (cancelled = true) and rescheduled for a later date, this key will hold the ballot_paper_id of the ballot that replaces it."
},
"replaces": {
"type": [
"string",
"null"
],
"description": "If this ballot replaces another cancelled ballot, this key will hold the ballot_paper_id of the ballot that it replaces."
},
"election_id": {
"type": "string",
"description": "Identifier for this ballot's parent election group"
},
"election_name": {
"type": "string",
"description": "Friendly name for this ballot's parent election group"
},
"post_name": {
"type": "string",
"description": "Name of the division or post the winner(s) of this election will represent"
},
"candidates_verified": {
"type": "boolean",
"description": "True if the list of candidates for this election has been confirmed against the nomination papers for this ballot. If this property is False, the candidate list is provisional or unconfirmed."
},
"voting_system": {
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "One of `AMS`, `FPTP`, `PR-CL`, `sv`, `STV`"
},
"name": {
"type": "string",
"description": "The name of this voting system (e.g: \"First-past-the-post\")"
},
"uses_party_lists": {
"type": "boolean",
"description": "True if this voting system uses party lists"
}
},
"description": "The voting system used in this election"
},
"hustings": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title of the event"
},
"url": {
"type": "string",
"description": "URL to the event or event sign up page"
},
"starts": {
"type": "string",
"description": "Start datetime"
},
"ends": {
"type": "string",
"description": "End datetime"
},
"location": {
"type": "string",
"description": "Address of the event"
},
"postevent_url": {
"type": "string",
"description": "Any post-event URL, e.g a YouTube recording of the event"
}
}
},
"description": "Hustings related to this election"
},
"seats_contested": {
"type": "number"
},
"candidates": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"list_position": {
"type": [
"number",
"null"
],
"description": "Numeric position in party list. This value is only relevant to elections using party lists. It will always be null in First-Past-The-post elections."
},
"party": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
},
"previous_party_affiliations": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
}
},
"person": {
"type": "object",
"properties": {
"ynr_id": {
"type": "number"
},
"name": {
"type": "string"
},
"absolute_url": {
"type": "string",
"description": "Link for more (human-readable) information about this candidate"
},
"email": {
"type": [
"string",
"null"
],
"description": "Email address for this candidate, if we hold it"
},
"photo_url": {
"type": [
"string",
"null"
],
"description": "URL for a photo of this candidate, if we hold one"
},
"leaflets": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"leaflet_id": {
"type": "number",
"description": "The electionleaflets.org ID for this leaflet"
},
"thumb_url": {
"type": "string",
"description": "URL to the thumbnail image of this leaflet"
},
"leaflet_url": {
"type": "string",
"description": "URL to the leaflet page on electionleaflets.org"
}
}
},
"description": "Leaflets uploaded to electionleaflets.org and tagged with this person"
}
}
}
}
},
{
"type": "object",
"properties": {
"list_position": {
"type": [
"number",
"null"
],
"description": "Numeric position in party list. This value is only relevant to elections using party lists. It will always be null in First-Past-The-post elections."
},
"party": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
},
"person": {
"type": "object",
"properties": {
"ynr_id": {
"type": "number"
},
"name": {
"type": "string"
},
"absolute_url": {
"type": "string",
"description": "Link for more (human-readable) information about this candidate"
},
"email": {
"type": [
"string",
"null"
],
"description": "Email address for this candidate, if we hold it"
},
"photo_url": {
"type": [
"string",
"null"
],
"description": "URL for a photo of this candidate, if we hold one"
}
}
}
}
}
],
"description": "Array of candidate objects describing candidates that will appear on this ballot paper. In an election which uses party lists, the `candidates` array is sorted by party and `list_position` within parties. For other election types it is sorted alphabetically by candidate name."
},
"wcivf_url": {
"type": "string",
"description": "Link for more (human-readable) information about this ballot"
}
}
},
"description": "List of ballots happening on this date. It is possible for more than one ballot to occur on the same date. For example, a user may vote in a local council election and mayoral election on the same day."
}
}
},
"description": "An array of date objects (each describing a date on which an election or poll will take place) containing details of relevant ballots, candidates and polling station information"
},
"electoral_services": {
"type": [
"object",
"null"
],
"properties": {
"council_id": {
"type": "string",
"description": "GSS code for this council"
},
"name": {
"type": "string",
"description": "Name of this council"
},
"nation": {
"type": "string",
"description": "Name of nation"
},
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Contact details for the user's local Electoral Services team. If we do not know the user's polling station, this can be used to provide contact info for their local council. This may be `null` if we are not able to determine the user's council."
},
"registration": {
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Sometimes the contact information for registration and proxy voting is different to the electoral services contact details. Use these if they exist and your users might have questions about voter registration. If this key is null, assume the electoral services contact details can be used for electoral registration related enquiries."
},
"postcode_location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"properties": {
"type": [
"object",
"null"
],
"properties": {}
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) containing a [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) describing the centroid of the input postcode. If providing a map or directions for a polling station journey, use this as the start point. This may be `null` if we are not able to accurately geocode."
}
}
}
Postcode search: Address picker ¶
/postcode/{postcode}
Parameters
postcode
string
( required )Whitespace in postcodes is ignored, so format may be
SW1A1AA
orSW1A 1AA
Example:
SW1A1AA
Postcode search: Address picker ¶
Example of a response when we must show the user an address picker. This should be followed by a second API call to the /address
endpoint.
In this case address_picker
is true
and dates
is an empty array. addresses
is an array of address objects.
/postcode/{postcode}
200
Content-Type: application/json
{
"address_picker": true,
"addresses": [
{
"address": "16 DUNCAN CLOSE, ST. MELLONS, CARDIFF",
"postcode": "CF3 1NP",
"slug": "100100106448",
"url": "http://developers.democracyclub.org.uk/api/v1/address/100100106448"
},
{
"address": "26 DUNCAN CLOSE, ST. MELLONS, CARDIFF",
"postcode": "CF3 1NP",
"slug": "100100106458",
"url": "http://developers.democracyclub.org.uk/api/v1/address/100100106458"
}
],
"dates": [],
"electoral_services": {
"council_id": "W06000015",
"name": "Cardiff Council",
"nation": "Wales",
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"registration": {
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"postcode_location": {
"type": "Feature",
"properties": null,
"geometry": {
"type": "Point",
"coordinates": [
-3.113797,
51.521175
]
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"address_picker": {
"type": "boolean",
"description": "True if we need to show this user an address picker"
},
"addresses": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"address": {
"type": "string"
},
"postcode": {
"type": "string"
},
"slug": {
"type": "string"
},
"url": {
"type": "string",
"description": "Call this URL to get data for this registered address"
}
}
},
{
"type": "object",
"properties": {
"address": {
"type": "string"
},
"postcode": {
"type": "string"
},
"slug": {
"type": "string"
},
"url": {
"type": "string",
"description": "Call this URL to get data for this registered address"
}
}
}
],
"description": "An array of address objects containing the addresses applicable to this request (if necessary)"
},
"dates": {
"type": "array",
"description": "An array of date objects containing details of relevant ballots, candidates and polling station information"
},
"electoral_services": {
"type": [
"object",
"null"
],
"properties": {
"council_id": {
"type": "string",
"description": "GSS code for this council"
},
"name": {
"type": "string",
"description": "Name of this council"
},
"nation": {
"type": "string",
"description": "Name of nation"
},
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Contact details for the user's local Electoral Services team. If we do not know the user's polling station, this can be used to provide contact info for their local council. This may be `null` if we are not able to determine the user's council."
},
"registration": {
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Sometimes the contact information for registration and proxy voting is different to the electoral services contact details. Use these if they exist and your users might have questions about voter registration. If this key is null, assume the electoral services contact details can be used for electoral registration related enquiries."
},
"postcode_location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"properties": {
"type": [
"object",
"null"
],
"properties": {}
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) containing a [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) describing the centroid of the input postcode. If providing a map or directions for a polling station journey, use this as the start point. This may be `null` if we are not able to accurately geocode."
}
}
}
Address search ¶
/address/{slug}
Parameters
slug
string
( required )A unique slug describing a residential address
Example:
60017560
Address search ¶
In the event that the same information is not applicable to all addresses described by a postcode, a call to /postcode
will return an array of address objects, each of which corresponds to a call to the /address
endpoint. A subsequent call to /address
will return an object of the same format as a valid call to /postcode
.
/address/{slug}
200
Content-Type: application/json
{
"address_picker": false,
"addresses": [],
"dates": [
{
"date": "2017-05-04",
"polling_station": {
"polling_station_known": true,
"custom_finder": null,
"report_problem_url": "http://wheredoivote.co.uk/report_problem/?source=testing&source_url=testing",
"station": {
"id": "w06000015.QK",
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-3.119229,
51.510885
]
},
"properties": {
"postcode": "",
"address": "Earlswood Social Club, 160-164 Greenway Road, Rumney"
}
}
},
"advance_voting_station": {
"name": "",
"address": "",
"postcode": "",
"location": {
"type": "Point",
"coordinates": [
-3.119229,
51.510885
]
},
"opening_times": [
[
"date",
"open",
"close"
]
]
},
"notifications": [
{
"title": "Some unexpected event is happening",
"type": "cancelled_election",
"detail": "Some more details",
"url": "https://foo.bar/baz"
}
],
"ballots": [
{
"ballot_paper_id": "local.cardiff.pontprennauold-st-mellons.2017-05-04",
"ballot_title": "Cardiff local election Pontprennau/Old St. Mellons",
"ballot_url": "https://developers.democracyclub.org.uk/api/v1/local.cardiff.pontprennauold-st-mellons.2017-05-04/",
"poll_open_date": "2017-05-04",
"elected_role": "Local Councillor",
"metadata": null,
"cancelled": false,
"cancellation_reason": "null",
"replaced_by": null,
"replaces": null,
"election_id": "local.cardiff.2017-05-04",
"election_name": "Cardiff local election",
"post_name": "Pontprennau/Old St. Mellons",
"candidates_verified": false,
"voting_system": {
"slug": "FPTP",
"name": "First-past-the-post",
"uses_party_lists": false
},
"hustings": [
{
"title": "",
"url": "",
"starts": "",
"ends": "",
"location": "",
"postevent_url": ""
}
],
"seats_contested": 1,
"candidates": [
{
"list_position": null,
"party": {
"party_id": "party:90",
"party_name": "Liberal Democrats"
},
"previous_party_affiliations": [
{
"party_id": "party:90",
"party_name": "Liberal Democrats"
}
],
"person": {
"ynr_id": 23417,
"name": "David Keigwin",
"absolute_url": "https://whocanivotefor.co.uk/person/23417/david-keigwin",
"email": "dave@example.com",
"photo_url": null,
"leaflets": [
{
"leaflet_id": 0,
"thumb_url": "",
"leaflet_url": ""
}
]
}
},
{
"list_position": null,
"party": {
"party_id": "party:52",
"party_name": "Conservative and Unionist Party"
},
"person": {
"ynr_id": 8071,
"name": "Joel Williams",
"absolute_url": "https://whocanivotefor.co.uk/person/8071/joel-williams",
"email": null,
"photo_url": "https://static-candidates.democracyclub.org.uk/media/images/images/8071.png"
}
}
],
"wcivf_url": "https://whocanivotefor.co.uk/elections/local.cardiff.2017-05-04/post-UTE:W05000900/pontprennauold-st-mellons"
}
]
}
],
"electoral_services": {
"council_id": "W06000015",
"name": "Cardiff Council",
"nation": "Wales",
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"registration": {
"address": "Electoral Registration Officer\\nCity of Cardiff Council\\nCounty Hall Atlantic Wharf",
"postcode": "CF10 4UW",
"email": "electoralservices@cardiff.gov.uk",
"phone": "029 2087 2034",
"website": "http://www.cardiff.gov.uk/"
},
"postcode_location": {
"type": "Feature",
"properties": null,
"geometry": {
"type": "Point",
"coordinates": [
-3.113797,
51.521175
]
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"address_picker": {
"type": "boolean",
"description": "True if we need to show this user an address picker"
},
"addresses": {
"type": "array",
"description": "An array of address objects containing the addresses applicable to this request (if necessary)"
},
"dates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "Polling day on which an election will occur"
},
"polling_station": {
"type": "object",
"properties": {
"polling_station_known": {
"type": "boolean",
"description": "Do we know where this user should vote?"
},
"custom_finder": {
"type": [
"string",
"null"
],
"description": "If we don't know a user's polling station, sometimes we can provide the URL of another polling station finder. This will always be populated for users in Northern Ireland where Electoral Office for Northern Ireland run their own service."
},
"report_problem_url": {
"type": [
"string",
"null"
],
"description": "If we provide a polling station result, this URL may be used to provide a user with a back-channel to report inaccurate data."
},
"station": {
"type": [
"object",
"null"
],
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"geometry": {
"type": [
"object",
"null"
],
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
},
"description": "A GeoJSON [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) object describing the location of this polling station. Optionally null if we know the address only but can't geocode a location."
},
"properties": {
"type": "object",
"properties": {
"postcode": {
"type": "string",
"description": "Postcode for this polling station"
},
"address": {
"type": "string",
"description": "Address for this polling station"
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) describing the user's polling station (if known)"
}
},
"description": "Results for polling station search"
},
"advance_voting_station": {
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string",
"description": "The name of the Advance Voting Station"
},
"address": {
"type": "string",
"description": "The address of the Advance Voting Station"
},
"postcode": {
"type": "string",
"description": "The postcode of the Advance Voting Station"
},
"location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
},
"description": "A GeoJSON [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) object describing the location of this Advance Voting Station."
},
"opening_times": {
"type": "array",
"items": {
"type": "array"
}
}
},
"required": [
"name",
"address",
"postcode",
"location",
"opening_times"
],
"additionalProperties": false,
"description": "Advance Voting Stations"
},
"notifications": {
"type": "array",
"items": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"cancelled_election",
"voter_id"
],
"description": "Type of notification"
},
"detail": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"description": "Array of notifications to be shown to the user about special conditions to be aware of on this date."
},
"ballots": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ballot_paper_id": {
"type": "string",
"description": "Identifier for this ballot"
},
"ballot_title": {
"type": "string",
"description": "Friendly name for this ballot"
},
"ballot_url": {
"type": "string",
"description": "API link for more detailed info about this ballot from the /elections endpoint"
},
"poll_open_date": {
"type": "string",
"description": "Polling day for this ballot (ISO 8601)"
},
"elected_role": {
"type": "string",
"description": "Name of the role the winner(s) of this election will assume"
},
"metadata": {
"type": [
"object",
"null"
],
"properties": {},
"description": "Object containing information about special conditions for the user to be aware about (e.g: cancelled elections, voter id pilot). (details TBC)"
},
"cancelled": {
"type": "boolean",
"description": "True if this ballot has been cancelled"
},
"cancellation_reason": {
"type": [
"string",
"null"
],
"enum": [
"NO_CANDIDATES",
"EQUAL_CANDIDATES",
"UNDER_CONTESTED",
"CANDIDATE_DEATH",
"null",
null
],
"description": "If a ballot has been cancelled, this key may hold a codified reason for that ballot's cancellation"
},
"replaced_by": {
"type": [
"string",
"null"
],
"description": "If a ballot has been cancelled (cancelled = true) and rescheduled for a later date, this key will hold the ballot_paper_id of the ballot that replaces it."
},
"replaces": {
"type": [
"string",
"null"
],
"description": "If this ballot replaces another cancelled ballot, this key will hold the ballot_paper_id of the ballot that it replaces."
},
"election_id": {
"type": "string",
"description": "Identifier for this ballot's parent election group"
},
"election_name": {
"type": "string",
"description": "Friendly name for this ballot's parent election group"
},
"post_name": {
"type": "string",
"description": "Name of the division or post the winner(s) of this election will represent"
},
"candidates_verified": {
"type": "boolean",
"description": "True if the list of candidates for this election has been confirmed against the nomination papers for this ballot. If this property is False, the candidate list is provisional or unconfirmed."
},
"voting_system": {
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "One of `AMS`, `FPTP`, `PR-CL`, `sv`, `STV`"
},
"name": {
"type": "string",
"description": "The name of this voting system (e.g: \"First-past-the-post\")"
},
"uses_party_lists": {
"type": "boolean",
"description": "True if this voting system uses party lists"
}
},
"description": "The voting system used in this election"
},
"hustings": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title of the event"
},
"url": {
"type": "string",
"description": "URL to the event or event sign up page"
},
"starts": {
"type": "string",
"description": "Start datetime"
},
"ends": {
"type": "string",
"description": "End datetime"
},
"location": {
"type": "string",
"description": "Address of the event"
},
"postevent_url": {
"type": "string",
"description": "Any post-event URL, e.g a YouTube recording of the event"
}
}
},
"description": "Hustings related to this election"
},
"seats_contested": {
"type": "number"
},
"candidates": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"list_position": {
"type": [
"number",
"null"
],
"description": "Numeric position in party list. This value is only relevant to elections using party lists. It will always be null in First-Past-The-post elections."
},
"party": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
},
"previous_party_affiliations": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
}
},
"person": {
"type": "object",
"properties": {
"ynr_id": {
"type": "number"
},
"name": {
"type": "string"
},
"absolute_url": {
"type": "string",
"description": "Link for more (human-readable) information about this candidate"
},
"email": {
"type": [
"string",
"null"
],
"description": "Email address for this candidate, if we hold it"
},
"photo_url": {
"type": [
"string",
"null"
],
"description": "URL for a photo of this candidate, if we hold one"
},
"leaflets": {
"type": [
"array",
"null"
],
"items": {
"type": "object",
"properties": {
"leaflet_id": {
"type": "number",
"description": "The electionleaflets.org ID for this leaflet"
},
"thumb_url": {
"type": "string",
"description": "URL to the thumbnail image of this leaflet"
},
"leaflet_url": {
"type": "string",
"description": "URL to the leaflet page on electionleaflets.org"
}
}
},
"description": "Leaflets uploaded to electionleaflets.org and tagged with this person"
}
}
}
}
},
{
"type": "object",
"properties": {
"list_position": {
"type": [
"number",
"null"
],
"description": "Numeric position in party list. This value is only relevant to elections using party lists. It will always be null in First-Past-The-post elections."
},
"party": {
"type": "object",
"properties": {
"party_id": {
"type": "string"
},
"party_name": {
"type": "string"
}
}
},
"person": {
"type": "object",
"properties": {
"ynr_id": {
"type": "number"
},
"name": {
"type": "string"
},
"absolute_url": {
"type": "string",
"description": "Link for more (human-readable) information about this candidate"
},
"email": {
"type": [
"string",
"null"
],
"description": "Email address for this candidate, if we hold it"
},
"photo_url": {
"type": [
"string",
"null"
],
"description": "URL for a photo of this candidate, if we hold one"
}
}
}
}
}
],
"description": "Array of candidate objects describing candidates that will appear on this ballot paper. In an election which uses party lists, the `candidates` array is sorted by party and `list_position` within parties. For other election types it is sorted alphabetically by candidate name."
},
"wcivf_url": {
"type": "string",
"description": "Link for more (human-readable) information about this ballot"
}
}
},
"description": "List of ballots happening on this date. It is possible for more than one ballot to occur on the same date. For example, a user may vote in a local council election and mayoral election on the same day."
}
}
},
"description": "An array of date objects (each describing a date on which an election or poll will take place) containing details of relevant ballots, candidates and polling station information"
},
"electoral_services": {
"type": [
"object",
"null"
],
"properties": {
"council_id": {
"type": "string",
"description": "GSS code for this council"
},
"name": {
"type": "string",
"description": "Name of this council"
},
"nation": {
"type": "string",
"description": "Name of nation"
},
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Contact details for the user's local Electoral Services team. If we do not know the user's polling station, this can be used to provide contact info for their local council. This may be `null` if we are not able to determine the user's council."
},
"registration": {
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": "string",
"description": "Contact address for this council"
},
"postcode": {
"type": "string",
"description": "Postcode component of contact address for this council"
},
"email": {
"type": "string",
"description": "Contact email address for this council's Electoral Services team"
},
"phone": {
"type": "string",
"description": "Telephone number for this council's Electoral Services team"
},
"website": {
"type": "string",
"description": "URL for this council's website"
}
},
"description": "Sometimes the contact information for registration and proxy voting is different to the electoral services contact details. Use these if they exist and your users might have questions about voter registration. If this key is null, assume the electoral services contact details can be used for electoral registration related enquiries."
},
"postcode_location": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"properties": {
"type": [
"object",
"null"
],
"properties": {}
},
"geometry": {
"type": "object",
"properties": {
"type": {
"type": "string"
},
"coordinates": {
"type": "array",
"items": [
{
"type": "number"
},
{
"type": "number"
}
]
}
}
}
},
"description": "A [GeoJSON Feature](https://tools.ietf.org/html/rfc7946#section-3.2) containing a [Point object](https://tools.ietf.org/html/rfc7946#section-3.1.2) describing the centroid of the input postcode. If providing a map or directions for a polling station journey, use this as the start point. This may be `null` if we are not able to accurately geocode."
}
}
}
Elections ¶
The /elections/
endpoint gives access to Democracy Club's full database of elections.
Each election object is assigned an Election Identifier
Democracy Club's election model is hierarchical.
The lowest level (or most detailed) election object is called the ballot id and describes a single ballot paper.
Each level above this is a group id. For example the ballot
local.worcestershire.bewdley.2017-05-04
is a child of the (organisation) group
local.worcestershire.2017-05-04
which is in turn a child of the (election) group
local.2017-05-04
.
An election object is described fully in the JSON schema, but broadly contains information about:
The election or group itself
The object's position in the hierarchy
The organisation (e.g: parliament or council) holding the election
The division (e.g: constituency or ward) that a candidate will be elected to represent
List Elections ¶
/elections/
Parameters
coords
string
( optional )Pass a lat/lon string as
?coords={lat},{lon}
to find elections covering the given coordinates. For lookup by postcode/address, use the /postcode endpoint.Example:
52.290719,-1.935395
current
string
( optional )Pass
?current=1
to return only elections which will happen in the near future (we may hold info on candidates or polling stations) or happened in the recent past (we may hold results). Usually this is an election whose polling date is either in the next 90 days or was in the last 20 days, but we may sometimes make an editorial decision that a major election (e.g: a scheduled general election) is "current" for a wider window than this.Example:
1
future
string
( optional )Pass
?future=1
to return only elections whose polling date is in the futureExample:
1
identifier_type
string
( optional )Pass
?identifier_type=election
,?identifier_type=organisation
or?identifier_type=ballot
to return only election groups, organisation groups or ballot objects.Example:
ballot
limit
number
( optional )Pass
?limit={num}
to specify number of election objects to return. Use withoffset
to page over resultsExample:
20
offset
number
( optional )Pass
?offset={num}
to specify Election object to start from. Use withlimit
to page over resultsExample:
20
List elections ¶
List or filter all election objects.
/elections/
200
Content-Type: application/json
{
"count": 18014,
"next": "https://developers.democracyclub.org.uk/api/v1/elections/?limit=100&offset=100",
"previous": null,
"results": [
{
"election_id": "naw.c.alyn-and-deeside.by.2018-02-06",
"election_title": "Alyn and Deeside (Constituencies) by-election",
"poll_open_date": "2018-02-06",
"election_type": {
"name": "National Assembly for Wales elections",
"election_type": "naw"
},
"election_subtype": {
"name": "Constituencies",
"election_subtype": "c"
},
"organisation": {
"official_identifier": "naw",
"organisation_type": "naw",
"organisation_subtype": "",
"official_name": "Welsh assembly",
"common_name": "Welsh assembly",
"slug": "naw",
"territory_code": "WLS",
"election_name": "National Assembly for Wales election",
"start_date": "1999-05-06",
"end_date": null
},
"group": "naw.c.2018-02-06",
"identifier_type": "ballot",
"children": [],
"elected_role": "Assembly Member",
"seats_contested": 1,
"division": {
"divisionset": {
"start_date": "2016-04-13",
"end_date": null,
"legislation_url": null,
"consultation_url": null,
"short_title": "2016 Boundaries",
"notes": "Auto imported from http://mapit.mysociety.org"
},
"name": "Alyn and Deeside",
"official_identifier": "gss:W09000007",
"slug": "alyn-and-deeside",
"division_type": "WAC",
"division_election_sub_type": "c",
"seats_total": null,
"territory_code": "WLS"
},
"voting_system": {
"slug": "FPTP",
"name": "First-past-the-post",
"uses_party_lists": false
},
"current": false,
"metadata": null,
"cancelled": false,
"replaces": null,
"replaced_by": null
}
]
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"count": {
"type": "number",
"description": "Total number of election objects"
},
"next": {
"type": [
"string",
"null"
],
"description": "Link to next page of results"
},
"previous": {
"type": [
"string",
"null"
],
"description": "Link to previous page of results"
},
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"election_id": {
"type": "string",
"description": "Identifier for this election"
},
"election_title": {
"type": "string",
"description": "Friendly name for this election"
},
"poll_open_date": {
"type": "string",
"description": "Polling day for this election (ISO 8601)"
},
"election_type": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Friendly name for this election type"
},
"election_type": {
"type": "string",
"description": "Identifier slug for this election type (a component of the identifier)"
}
}
},
"election_subtype": {
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string",
"description": "Friendly name for this election subtype"
},
"election_subtype": {
"type": "string",
"description": "Identifier slug for this election subtype (a component of the identifier)"
}
},
"description": "Election subtype provides details for the subtype in Additional Member System elections (Welsh Assembly, Scottish Parliament, Greater London Assembly). This key will be null for other election types"
},
"organisation": {
"type": "object",
"properties": {
"official_identifier": {
"type": "string",
"description": "An identifier for this organisation. Where possible, we'll us a code from the relevant [gov.uk register](https://www.registers.service.gov.uk/)."
},
"organisation_type": {
"type": "string",
"enum": [
"combined-authority",
"europarl",
"gla",
"local-authority",
"naw",
"nia",
"parl",
"police-area",
"sp"
]
},
"organisation_subtype": {
"type": "string",
"enum": [
"CA",
"CC",
"CTY",
"LBO",
"MD",
"NMD",
"SRA",
"UA"
],
"description": "If organisation_type = 'local-authority', an additional description of what type of local authority this is from the [gov.uk local authority registers](https://www.registers.service.gov.uk/category/regional-and-local-government). Empty string for other organisation types"
},
"official_name": {
"type": "string",
"description": "Long name of the organisation"
},
"common_name": {
"type": "string",
"description": "Short name of the organisation"
},
"slug": {
"type": "string",
"description": "Identifier slug for this organisation (a component of the identifier)"
},
"territory_code": {
"type": "string",
"enum": [
"ENG",
"WLS",
"SCT",
"NIR",
"GBN"
]
},
"election_name": {
"type": "string",
"description": "Base name for elections to this organisation"
},
"start_date": {
"type": "string",
"description": "Start date (ISO 8601) for this organisation, or the first date on which we can validly create an election for it"
},
"end_date": {
"type": [
"string",
"null"
],
"description": "End date (ISO 8601) for this organisation, or the last date on which we can validly create an election for it. Null when the organisation is current"
}
},
"description": "Object describing the body the winner of this election will be elected to"
},
"group": {
"type": [
"string",
"null"
],
"description": "Identifier for this election's parent group. If this is an election group (group_type = 'election'), this will be null"
},
"identifier_type": {
"type": "string",
"description": "One of 'election', 'organisation' or 'ballot'."
},
"children": {
"type": "array",
"description": "Identifiers for any elections belonging to this election group. Empty array for ballots"
},
"elected_role": {
"type": "string",
"description": "Name of the role the winner(s) of this election will assume"
},
"seats_contested": {
"type": [
"number",
"null"
],
"description": "Number of seats contested in this election. Populated only for ballots"
},
"division": {
"type": [
"object",
"null"
],
"properties": {
"divisionset": {
"type": "object",
"properties": {
"start_date": {
"type": "string",
"description": "Start date (ISO 8601) for this Division Set, or the first date on which we can validly create an election for a division in it"
},
"end_date": {
"type": [
"string",
"null"
],
"description": "End date (ISO 8601) for this Division Set, or the last date on which we can validly create an election for a division in it. Null when the Division Set is current"
},
"legislation_url": {
"type": [
"string",
"null"
],
"description": "Link to the legislation which defined the Division Set, if we hold it"
},
"consultation_url": {
"type": [
"string",
"null"
],
"description": "Link to the process which defined the Division Set, if we hold it."
},
"short_title": {
"type": "string",
"description": "Short name of the Division Set"
},
"notes": {
"type": "string",
"description": "Notes on the source of the boundaries"
}
},
"description": "Electoral divisions change over time. A Division Set represents a group of boundaries which are in use over a period of time."
},
"name": {
"type": "string",
"description": "Name of this division"
},
"official_identifier": {
"type": "string",
"description": "Identifier for this division. Where possible this will be a GSS code prefixed by `gss:`. If a GSS code is not available yet, we'll assign the division a temporary ID"
},
"slug": {
"type": "string",
"description": "Identifier slug for this division (a component of the identifier)"
},
"division_type": {
"type": "string",
"description": "An Ordnance Survey AREA_CODE describing what type of division this is. See https://www.ordnancesurvey.co.uk/docs/technical-specifications/boundary-line-technical-specification.pdf"
},
"division_election_sub_type": {
"type": "string",
"description": "Identifier slug for this election subtype (a component of the identifier)."
},
"seats_total": {
"type": [
"number",
"null"
],
"description": "Total number of seats in this division (may not all be elected in a single election)"
},
"territory_code": {
"type": "string",
"enum": [
"ENG",
"WLS",
"SCT",
"NIR"
]
}
},
"description": "Object describing the division (e.g: constituency or ward) the winner of this election will represent, if applicable. Election groups don't have a division. Also the ballot object for some election types don't have a division (e.g: Directly elected mayors and Police and Crime Commissioners represent an organisation directly)"
},
"voting_system": {
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "Identifier slug for voting system used by this election"
},
"name": {
"type": "string",
"description": "Friendly description for voting system used by this election"
},
"uses_party_lists": {
"type": "boolean",
"description": "True if this voting system uses party lists"
}
}
},
"current": {
"type": "boolean",
"description": "True if this election will happen in the near future or happened in the recent past. Usually this is an election whose polling date is either in the next 90 days or was in the last 20 days, but we may sometimes make an editorial decision that a major election is \"current\" for a wider window than this."
},
"metadata": {
"type": [
"object",
"null"
],
"properties": {},
"description": "Object containing information about special conditions for the user to be aware about (e.g: cancelled elections, voter id pilot)."
},
"cancelled": {
"type": "boolean",
"description": "True if this ballot has been cancelled"
},
"replaces": {
"type": [
"string",
"null"
],
"description": "If a ballot replaces another cancelled ballot, this key will hold the identifier of the ballot that it replaces."
},
"replaced_by": {
"type": [
"string",
"null"
],
"description": "If a ballot has been cancelled (cancelled = true) and rescheduled for a later date, this key will hold the identifier of the ballot that replaces it."
}
}
},
"description": "Array of Election objects"
}
}
}
Single election ¶
/elections/{id}
https://developers.democracyclub.org.uk/api/v1/elections/naw.c.alyn-and-deeside.by.2018-02-06
Parameters
id
string
( required )A Democracy Club election ID
Example:
naw.c.alyn-and-deeside.by.2018-02-06
Single election ¶
Retrieve a single election object by id.
/elections/{id}
200
Content-Type: application/json
{
"election_id": "naw.c.alyn-and-deeside.by.2018-02-06",
"election_title": "Alyn and Deeside (Constituencies) by-election",
"poll_open_date": "2018-02-06",
"election_type": {
"name": "National Assembly for Wales elections",
"election_type": "naw"
},
"election_subtype": {
"name": "Constituencies",
"election_subtype": "c"
},
"organisation": {
"official_identifier": "naw",
"organisation_type": "naw",
"organisation_subtype": "",
"official_name": "Welsh assembly",
"common_name": "Welsh assembly",
"slug": "naw",
"territory_code": "WLS",
"election_name": "National Assembly for Wales election",
"start_date": "1999-05-06",
"end_date": null
},
"group": "naw.c.2018-02-06",
"identifier_type": "ballot",
"children": [],
"elected_role": "Assembly Member",
"seats_contested": 1,
"division": {
"divisionset": {
"start_date": "2016-04-13",
"end_date": null,
"legislation_url": null,
"consultation_url": null,
"short_title": "2016 Boundaries",
"notes": "Auto imported from http://mapit.mysociety.org"
},
"name": "Alyn and Deeside",
"official_identifier": "gss:W09000007",
"slug": "alyn-and-deeside",
"division_type": "WAC",
"division_election_sub_type": "c",
"seats_total": null,
"territory_code": "WLS"
},
"voting_system": {
"slug": "FPTP",
"name": "First-past-the-post",
"uses_party_lists": false
},
"current": false,
"metadata": null,
"cancelled": false,
"replaces": null,
"replaced_by": null
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"election_id": {
"type": "string",
"description": "Identifier for this election"
},
"election_title": {
"type": "string",
"description": "Friendly name for this election"
},
"poll_open_date": {
"type": "string",
"description": "Polling day for this election (ISO 8601)"
},
"election_type": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Friendly name for this election type"
},
"election_type": {
"type": "string",
"description": "Identifier slug for this election type (a component of the identifier)"
}
}
},
"election_subtype": {
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string",
"description": "Friendly name for this election subtype"
},
"election_subtype": {
"type": "string",
"description": "Identifier slug for this election subtype (a component of the identifier)"
}
},
"description": "Election subtype provides details for the subtype in Additional Member System elections (Welsh Assembly, Scottish Parliament, Greater London Assembly). This key will be null for other election types"
},
"organisation": {
"type": "object",
"properties": {
"official_identifier": {
"type": "string",
"description": "An identifier for this organisation. Where possible, we'll us a code from the relevant [gov.uk register](https://www.registers.service.gov.uk/)."
},
"organisation_type": {
"type": "string",
"enum": [
"combined-authority",
"europarl",
"gla",
"local-authority",
"naw",
"nia",
"parl",
"police-area",
"sp"
]
},
"organisation_subtype": {
"type": "string",
"enum": [
"CA",
"CC",
"CTY",
"LBO",
"MD",
"NMD",
"SRA",
"UA"
],
"description": "If organisation_type = 'local-authority', an additional description of what type of local authority this is from the [gov.uk local authority registers](https://www.registers.service.gov.uk/category/regional-and-local-government). Empty string for other organisation types"
},
"official_name": {
"type": "string",
"description": "Long name of the organisation"
},
"common_name": {
"type": "string",
"description": "Short name of the organisation"
},
"slug": {
"type": "string",
"description": "Identifier slug for this organisation (a component of the identifier)"
},
"territory_code": {
"type": "string",
"enum": [
"ENG",
"WLS",
"SCT",
"NIR",
"GBN"
]
},
"election_name": {
"type": "string",
"description": "Base name for elections to this organisation"
},
"start_date": {
"type": "string",
"description": "Start date (ISO 8601) for this organisation, or the first date on which we can validly create an election for it"
},
"end_date": {
"type": [
"string",
"null"
],
"description": "End date (ISO 8601) for this organisation, or the last date on which we can validly create an election for it. Null when the organisation is current"
}
},
"description": "Object describing the body the winner of this election will be elected to"
},
"group": {
"type": [
"string",
"null"
],
"description": "Identifier for this election's parent group. If this is an election group (group_type = 'election'), this will be null"
},
"identifier_type": {
"type": "string",
"description": "One of 'election', 'organisation' or 'ballot'."
},
"children": {
"type": "array",
"description": "Identifiers for any elections belonging to this election group. Empty array for ballots"
},
"elected_role": {
"type": "string",
"description": "Name of the role the winner(s) of this election will assume"
},
"seats_contested": {
"type": [
"number",
"null"
],
"description": "Number of seats contested in this election. Populated only for ballots"
},
"division": {
"type": [
"object",
"null"
],
"properties": {
"divisionset": {
"type": "object",
"properties": {
"start_date": {
"type": "string",
"description": "Start date (ISO 8601) for this Division Set, or the first date on which we can validly create an election for a division in it"
},
"end_date": {
"type": [
"string",
"null"
],
"description": "End date (ISO 8601) for this Division Set, or the last date on which we can validly create an election for a division in it. Null when the Division Set is current"
},
"legislation_url": {
"type": [
"string",
"null"
],
"description": "Link to the legislation which defined the Division Set, if we hold it"
},
"consultation_url": {
"type": [
"string",
"null"
],
"description": "Link to the process which defined the Division Set, if we hold it."
},
"short_title": {
"type": "string",
"description": "Short name of the Division Set"
},
"notes": {
"type": "string",
"description": "Notes on the source of the boundaries"
}
},
"description": "Electoral divisions change over time. A Division Set represents a group of boundaries which are in use over a period of time."
},
"name": {
"type": "string",
"description": "Name of this division"
},
"official_identifier": {
"type": "string",
"description": "Identifier for this division. Where possible this will be a GSS code prefixed by `gss:`. If a GSS code is not available yet, we'll assign the division a temporary ID"
},
"slug": {
"type": "string",
"description": "Identifier slug for this division (a component of the identifier)"
},
"division_type": {
"type": "string",
"description": "An Ordnance Survey AREA_CODE describing what type of division this is. See https://www.ordnancesurvey.co.uk/docs/technical-specifications/boundary-line-technical-specification.pdf"
},
"division_election_sub_type": {
"type": "string",
"description": "Identifier slug for this election subtype (a component of the identifier)."
},
"seats_total": {
"type": [
"number",
"null"
],
"description": "Total number of seats in this division (may not all be elected in a single election)"
},
"territory_code": {
"type": "string",
"enum": [
"ENG",
"WLS",
"SCT",
"NIR"
]
}
},
"description": "Object describing the division (e.g: constituency or ward) the winner of this election will represent, if applicable. Election groups don't have a division. Also the ballot object for some election types don't have a division (e.g: Directly elected mayors and Police and Crime Commissioners represent an organisation directly)"
},
"voting_system": {
"type": "object",
"properties": {
"slug": {
"type": "string",
"description": "Identifier slug for voting system used by this election"
},
"name": {
"type": "string",
"description": "Friendly description for voting system used by this election"
},
"uses_party_lists": {
"type": "boolean",
"description": "True if this voting system uses party lists"
}
}
},
"current": {
"type": "boolean",
"description": "True if this election will happen in the near future or happened in the recent past. Usually this is an election whose polling date is either in the next 90 days or was in the last 20 days, but we may sometimes make an editorial decision that a major election is \"current\" for a wider window than this."
},
"metadata": {
"type": [
"object",
"null"
],
"properties": {},
"description": "Object containing information about special conditions for the user to be aware about (e.g: cancelled elections, voter id pilot)."
},
"cancelled": {
"type": "boolean",
"description": "True if this ballot has been cancelled"
},
"replaces": {
"type": [
"string",
"null"
],
"description": "If a ballot replaces another cancelled ballot, this key will hold the identifier of the ballot that it replaces."
},
"replaced_by": {
"type": [
"string",
"null"
],
"description": "If a ballot has been cancelled (cancelled = true) and rescheduled for a later date, this key will hold the identifier of the ballot that replaces it."
}
}
}
Sandbox outputs ¶
At any time the live data we expose via the API reflects reality. This means that there are conditions which are important to model in your application but are difficult to replicate using live data. To make it easier to replicate a variety of behaviours in test/development we provide a 'sandbox API' at http://developers.democracyclub.org.uk/api/v1/sandbox which serves fake but plausible data. The following test postcodes and address slugs are valid in the sandbox. Each one represents a different scenario:
postcode AA11AA - No upcoming ballots
postcode AA12AA - One upcoming ballot, station known, with candidates
postcode AA12AB - One upcoming ballot, station not known, with candidates
postcode AA13AA - We need to show the user an address picker. Each of the following
/address
calls has different polling station info:- address slug 10035187881
- address slug 10035187882
- address slug 10035187883
postcode AA14AA - Four upcoming ballots across 3 future dates with a cancellation:
mayor.lewisham.2018-05-03
- Mayoral electionlocal.lewisham.blackheath.2018-05-03
- This election is cancelled and rescheduled on 2018-05-10local.lewisham.blackheath.2018-05-10
- This election replaces the cancelledlocal.lewisham.blackheath.2018-05-03
parl.lewisham-east.by.2018-06-14
- This election is scheduled but we don't know of any candidates yet
postcode AA15AA - Northern Ireland. This example shows the
custom_finder
key in use. We can use this to redirect users to Electoral Office for Northern Ireland's website for polling station data.postcode EH11YJ - Scotland. This example shows different registration and electoral services contact details.
Notes and Tips ¶
Polling Stations
- If we don't know a user's polling station, sometimes we may provide an external link for more info in
custom_finder
. This will always be populated for users in Northern Ireland where the Electoral Office for Northern Ireland run their own service. e.g:
{
...
"custom_finder": "http://www.eoni.org.uk/Offices/Postcode-Search-Results?postcode=BT28%202EY"
}
- If we don't know a user's polling station and
custom_finder
is not populated, the contact details in theelectoral_services
orregistration
object can be used to provide contact details for the user's local electoral services or registration team.
Contact details
We provide two types of contact details; "electoral services" and "registration". This is because in Scotland and
Northern Ireland the local authority doesn't handle electoral registration. If you are using the data to deal with
electoral registration, use the registration
contact details. Please make sure you are using the correct contact
details for your users needs.
Ballots and Candidates
It is possible for more than one ballot to occur on the same date, so a
ballots
array may contain many objects. For example, a user may vote in a local council election and mayoral election on the same day.Occasionally a ballot needs to be cancelled. The most common reason for this is if one of the candidates dies between close of nominations and polling day, but there are other situations where this may happen. Remember to check the
cancelled
flag on ballot objects.In an election using party lists, candidates should be shown to users grouped by party and ordered by
list_position
within parties. In an election which uses party lists, thecandidates
array is sorted by party andlist_position
within parties. For other election types it is sorted alphabetically by candidate name.
Notifications
We'll use the notifications
array to provide additional info
to be shown to the user about special conditions to be aware of on this date
e.g: identification requirements, or a cancelled poll.
If there is something in the notifications array, we highly recommend you show it to your users
Formatting notifications
In general we will provide sensible defaults that you can show to your users directly.
You should iterate over the notifications array and show the title
and detail
fields in a way that will be
obvious to your users.
The URL field can be null
, but if it exists then it will be a link to some more detail that the user should be
directed to.
It's possible for there to be more than one notification, however if all polls are cancelled we will only ever return
a single cancelled_election
notification in the list.
Types of notification
If you want to handle each case differently to the default (for example to change our wording, or to translate the
message)
then you can look at the type
key.
The values for this are:
cancelled_election
: See belowpre_eco
: The council is due to have a boundary change meaning we can't create the full elections until it's finished. This response is a placeholder.(deprecated)
voter_id_pilot
: over 2018 and 19 some English councils conducted pilots of the voter ID scheme. We have replaced this notification with a value per ballot.
Cancelled Polls
Sometimes a scheduled poll may be cancelled. This is usually either because the election is uncontested or due to death of a candidate.
If the user has more than one ballot and only one of them is cancelled, we will not add a notification. In this case,
you should look at the cancelled
and cancellation_reason
values on each ballot.
If every ballot for a date is cancelled (meaning the user has no election to vote in) then we will add a notification alerting them that they don't have to vote on that day, e.g:
{
...
"notifications": [
{
"url": null,
"type": "cancelled_election",
"detail": "The poll for this election will not take place because it is uncontested.",
"title": "Uncontested Election"
}
]
}
When we know the reason for a cancelled ballot we will add a cancellation_reason
to the ballot object, next to the
cancelled
boolean:
NO_CANDIDATES
: No candidatesEQUAL_CANDIDATES
: Equal candidates to contested seatsUNDER_CONTESTED
: Fewer candidates than seatsCANDIDATE_DEATH
: Death of a candidate
Advance Voting Stations
For the 2022 local elections in Wales, four councils are piloting "Advance Voting". This means people in the pilot areas will be able to cast their vote in the days before polling day.
We support this pilot, and have an extra key in the API in the dates
array.
{
...
"advance_voting_station": {
"name": "Exeter Guildhall",
"address": "Exeter City Council\nCivic Centre\nParis Street\nExeter\nDevon",
"postcode": "EX1 1JN",
"location": {
"type": "Point",
"coordinates": [
-3.524551005678706,
50.72486002944331
]
},
"opening_times": [
[
"2018-11-20",
"10:00:00",
"16:00:00"
],
[
"2018-11-21",
"10:00:00",
"16:00:00"
]
]
},
}
If this object exists in the API response, it's highly recommended to display it to the user.
Each Advance Voting Station has a name, address, postcode and location. Opening times are given as an ordered list of lists, containing:
[date, open time, close time]
Previous Party Affiliations
The Local Elections (Principal Areas) (Wales) Rules 2021 Statutory Instrument, among other things introduced a requirement for candidates to list any other political party membership in the last 12 months on the Statement Of Persons Nominated.
We store this information, and present it for candidates in Welsh run elections. The field exists on the candidate
object in the candidates
list on each ballot. It wil be null
unless the candidate has declared affiliation with
another party in the last 12 months.
Note that this is not the same as previous candidacies for this person. We also track this, but a person must declare parties they have beem members of in the previous 12 months before the date of the election.
When data exists, it's a list of parties. This information is transcribed from the Statement of Persons Nominated.
Errors
Errors will be reported using HTTP status codes. The body of the error will be formatted as valid JSON and will give a description of the error