Democracy Works Candidates API

The Candidates API from Democracy Works — 1 operation retrieving a single candidate by id, with party affiliation, incumbency, write-in status, running mate, ranked-choice round and Ballotpedia link.

Operations 1

GET /candidates Candidate #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/democracy-works-candidates-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

democracy-works-candidates-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Democracy Works Candidates API
  version: '2.0'
  description: "# Introduction\n\nThe Democracy Works Elections API provides your application with comprehensive elections data and voting guidance, surfacing our unparalleled coverage of upcoming local, state, and federal elections. Power your platforms, apps, reminders, outreach campaigns, and much more.\n\nJoin the community of developers in our [Google Group](https://groups.google.com/a/democracy.works/g/democracy-works-data)\nfor updates about our data and elections.\n\n## Authentication\nAccess to the Democracy Works Elections API requires authentication. To access the DW API, include an `X-API-KEY` header with each API request. The key of that header should be lowercase. The value of that header should be your API key. For example:\n\n```sh\ncurl \"https://api.democracy.works/v2/elections\" \\\n    --header \"X-API-KEY: <YOUR API KEY>\"\n```\n\nFor pricing information and to obtain a test key, please [contact us](https://data.democracy.works/api-signup).\n\n## Base URL\nThe base URL for all API endpoints is: https://api.democracy.works/v2\n\n## Support\nIf you have any further questions or issues, please contact us at partnerships@democracy.works.\n\n## Data\n\nData is captured in two entities, an __Election__ and an __Authority__. The __Election__ has election-specific dates and deadlines, URLs for voters to get more information and take action, and detailed guidance in both English and Spanish. The __Authority__ includes statewide evergreen information and instructions on how to register and vote for each state, as well as election office contact information.\n\n# Open Civic Data IDs (OCD-IDs)\n\nWe use Open Civic Data IDs [(OCD-IDs)](https://opencivicdata.info/en/latest/ocdids.html)\nthroughout the API to describe entities and filter results.\n\nOCD-IDs start with what is being identified, and in our case it is always\n`ocd-division`.\n\nSince all authorities are, or are contained within, a state and all elections\nare run by some authority, almost every OCD-ID in our system starts with\n`ocd-division/country:us/state:__`, where `__` is a two-letter state postal code.\n\nThe only exception to this is for the District of Columbia, which has the OCD-ID\n`ocd-division/country:us/district:dc`.\n\n## OCD-ID on the Authority\nThe OCD-ID associated with an authority describes the political district covered\nby an authority. Authorities are uniquely identifiable by the associated OCD-ID.\n\nFor example:\n- The OCD-ID `ocd-division/country:us/state:ak/place:anderson` is associated\n  with the authority for Anderson, Alaska.\n- The OCD-ID `ocd-division/country:us/state:ny/county:albany/council_district:2`\n  is not associated with an authority because Albany's 2nd Ward is a legislative\n  ward which does not run its own elections.\n\n## OCD-ID on the Election\nThe OCD-ID associated with an election describes the highest-level district\nin which all voters have something to vote for on the ballot on Election Day.\nElections always have an associated OCD-ID, but are not uniquely\nidentifiable by the associated OCD-ID.\n\nFor example:\n- If there is a mayoral race in Philadelphia as well as a state-wide\nmeasure contest in Pennsylvania on a given day, there will be one election\nentity with OCD-ID `ocd-division/country:us/state:pa`.\n- If there is only a mayoral race in Pittsburgh in Allegheny County on a given\nday, there will be an election entity with OCD-ID\n`ocd-division/country:us/state:pa/county:allegheny`.\n\n# Standard Parameters\nFunctionality shared between API endpoints is noted here. Each endpoint will\nspecify whether it supports the following functionality.\n\n## Pagination\nAny endpoint that returns multiple results supports pagination. An endpoint that\nsupports pagination accepts two related query parameters:\n- `pageSize`\n  - Specifies the number of results requested. Defaults to 10 if not specified. The maximum value is 100.\n  - Example: `pageSize=15`\n- `page`\n  - Specifies the page to return, based on `pageSize`. Defaults to 1 if not specified.\n  - Example: `page=2`\n\nYou can send none, one, or both of these parameters. Each endpoint that supports\npagination will have a `pagination` field in the response, which details what\npage of information is returned, what page size was used for the request, and the\ntotal number of results found.\n\n## Localization\nSome endpoints support localization. An endpoint that supports localization accepts a\nheader parameter:\n- `Accept-Language`\n  - Specifies the language tag for localization. Accepted values are `en`, `en-US`, `es`, and `es-US`.\n  - Example: `Accept-Language: es`\n\nNot all fields on the response of a localized endpoint are localized. Each field that supports localization\nwill have a `Localized` tag on its field description.\n\nIf no localization in the requested language is found,\nlocalized fields will return `null`.\n\n## Content Formatting\nSome endpoints support content formatting. An endpoint that supports formatting accepts a\nquery parameter:\n- `contentFormatType`\n  - Specifies the format of certain fields in the response.\n    Accepted values are `html` and `json`. Defaults to `html` if not specified.\n  - Example: `contentFormatType=json`\n\nNot all fields on the response of a formatted endpoint are formatted.\nFormatting is generally supported on prose-like fields, including Question and Answer content and most instruction fields.\nEach field that supports formatting will have a `Formatted` tag on its field description.\n\nThe `json`-formatted content is the content represented as an [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree).\n\n## Fields\nSome endpoints support field masking to specify a list of fields to include in the API response. This helps to avoid unnecessary computation and improve performance. An endpoint that supports field masking accepts a\nquery parameter:\n- `fields`\n  - Specifies the symbolic field paths to include in the response, provided as comma-separated list. See more about [Field Masks](https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask).\n  - Example: `fields=\"ocdId,date,contact.email\"`\n\nPaths are validated against all possible fields, and providing an invalid path will result in a 400 response.\n"
servers:
- url: https://api.democracy.works/v2
tags:
- name: Candidates
paths:
  /candidates:
    get:
      operationId: getCandidate
      summary: Candidate
      description: 'This endpoint gets one candidate by `id`.

        '
      security:
      - ApiKeyAuth: []
      parameters:
      - name: id
        in: path
        schema:
          type: string
          description: Hash identifier of the candidate to get.
          example: can_6669354db52bcd7c83d732ffa7e006a81aabba0e
        required: true
      responses:
        '200':
          description: Candidate fetched by query.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/candidate'
              examples:
                sampleCandidateResponse:
                  $ref: '#/components/examples/candidates'
        '400':
          $ref: '#/components/responses/badRequestError'
        '404':
          description: Not Found Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/errors'
              example:
                status: 404
                message:
                - Candidate not found.
        '429':
          $ref: '#/components/responses/tooManyRequestsError'
        '500':
          $ref: '#/components/responses/internalServerError'
      tags:
      - Candidates
components:
  examples:
    candidates:
      summary: Sample Candidate response
      description: 'This is **fictional** data to provide examples of fields values.

        '
      value:
        data:
          candidates:
            id: can_92800009b57ea6d51a701ebaec4ce10be78494f3
            fullName: Jesse Lee Gunn
            firstName: Jesse
            lastName: Gunn
            partyAffiliation:
            - Nonpartisan
            isIncumbent: false
            isWriteIn: false
            ballotpediaUrl: https://ballotpedia.org/Jesse_Lee_Gunn
            status: lost
            runningMateFullName: null
            runningMateTitle: null
            rankedChoiceVotingRound: null
            endorsementCount: 1
            contact:
              campaign:
                email: jg4act@gmail.com
                website: https://www.jesse2024.com/
                facebook: https://www.facebook.com/jesse4transit
                twitter: null
                instagram: https://www.instagram.com/jesse4transit
                youtube: null
                mailingAddress: 510 Schafer Road Hayward CA 94544
                phone: 510-512-4236
              personal:
                website: null
                facebook: https://www.facebook.com/jesse4transit
                twitter: jessegunnmath
                instagram: null
                youtube: https://www.youtube.com/@jessegunn5994
                linkedIn: https://www.linkedin.com/in/jesse4transit/
  responses:
    badRequestError:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errors'
          example:
            status: 400
            message:
            - Something has gone wrong parsing your request. Please refer to our documentation at https://developers.democracy.works/api/v2 to confirm all required fields are present and all fields are formatted correctly.
    internalServerError:
      description: InternalServerError
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errors'
          example:
            status: 500
            message:
            - Something went wrong.
    tooManyRequestsError:
      description: TooManyRequestsError
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/gatewayErrors'
          example:
            message: Too Many Requests
  schemas:
    candidate:
      description: A representation of a candidate.
      type: object
      required:
      - id
      - fullName
      - firstName
      - lastName
      - partyAffiliation
      - isWriteIn
      properties:
        id:
          type: string
          description: The ID of the candidate.
        fullName:
          type: string
          description: The full name of the candidate.
        firstName:
          type: string
          description: The first name of the candidate.
        lastName:
          type: string
          description: The last name of the candidate.
        partyAffiliation:
          type: array
          description: Describes the party affiliation of the candidate.
          items:
            type: string
        isIncumbent:
          type: boolean
          description: Indicates whether a candidate is an incumbent.
        isWriteIn:
          type: boolean
          description: Indicates whether a candidate is a write-in candidate.
        ballotpediaUrl:
          type: string
          description: The URL of the candidate's Ballotpedia page.
        status:
          type: string
          description: The status of the candidate in that contest.
          enum:
          - won
          - lost
          - advanced
          - declared
          - disqualified
          - onBallot
          - withdrew
          - notable
          - acclaimed
          - withdrewStillOnBallot
        runningMateFullName:
          type: string
          description: The full name of the candidate's running mate.
        runningMateTitle:
          type: string
          description: The title of the candidate's running mate.
        rankedChoiceVotingRound:
          type: number
          description: RCV results are reported in “rounds” of calculations. Ballotpedia reports each round of these results, so a candidate in an RCV will have a row for each round of calculation in that stage. The first round of results reported will have this attribute = 1. Rounds will count up until the final round.
        endorsementCount:
          type: number
          description: The number of endorsements available for this candidate.
        contact:
          type: object
          properties:
            campaign:
              type: object
              properties:
                email:
                  type: string
                  description: The candidate’s campaign email address.
                website:
                  type: string
                  description: The candidate’s campaign website.
                facebook:
                  type: string
                  description: The candidate’s campaign Facebook.
                twitter:
                  type: string
                  description: The candidate’s campaign Twitter.
                instagram:
                  type: string
                  description: The candidate’s campaign Instagram.
                youtube:
                  type: string
                  description: The candidate’s campaign YouTube.
                mailingAddress:
                  type: string
                  description: The candidate’s campaign mailing address.
                phone:
                  type: string
                  description: The candidate’s campaign phone number.
            personal:
              type: object
              properties:
                website:
                  type: string
                  description: The candidate’s personal website.
                facebook:
                  type: string
                  description: The candidate’s personal Facebook.
                twitter:
                  type: string
                  description: The candidate’s personal Twitter.
                instagram:
                  type: string
                  description: The candidate’s personal Instagram.
                youtube:
                  type: string
                  description: The candidate’s personal YouTube.
                linkedIn:
                  type: string
                  description: The candidate’s personal LinkedIn.
    errors:
      type: object
      properties:
        status:
          type: integer
        message:
          type: array
      required:
      - status
      - message
    gatewayErrors:
      type: object
      properties:
        message:
          type: string
      required:
      - message
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY