arrow_backDocs

Step 3

Get the election.

Before showing the voter login form, load the election attached to your public key. This tells your app whether the election is live, remote, and configured for API voting.

Is the request successful?

If status is false, show the API message and stop the flow.

Is this a remote election?

This starter guide is remote-only, so votingMode must be remote.

Is API voting enabled?

accessMode must be api before a custom frontend can continue.

Is the election live?

Only show the voter login form when the election status is live.

The election object controls the UI.

For this beginner guide, we only continue when the election is a remote API election and its status is live.

code GET /election response
{
  "status": true,
  "data": {
    "election": {
      "title": "SRC General Elections 2026",
      "institution": "CrownVote Demo Institution",
      "description": "Official voting event for the SRC General Elections.",
      "instructions": "Login with your voter ID and password to cast your vote.",
      "status": "live",
      "startsAt": "2026-06-01T08:00:00.000Z",
      "endsAt": "2026-06-01T17:00:00.000Z",
      "votingMode": "remote",
      "accessMode": "api",
      "inPersonRequireAdminLogin": null,
      "inPersonRequireVoterPassword": null
    }
  }
}

Add getElection() to index.js.

This function loads the election, updates the page title and description, checks the election mode, and reveals the voter login form only when the election is ready.

code Add to index.js
async function getElection() {
  hideNotice()

  const response = await fetch(`${API_URL}/election`, {
    headers: {
      'X-PUBLIC-KEY': PUBLIC_KEY,
    },
  })

  const result = await response.json()

  if (!result.status) {
    showNotice(result.message || 'Unable to load election.')
    return
  }

  state.election = result.data.election

  elements.title.textContent = state.election.title
  elements.description.textContent =
    state.election.description || state.election.instructions || 'Login to cast your vote.'

  if (state.election.votingMode !== 'remote') {
    showNotice('This starter guide is for remote voting only.')
    return
  }

  if (state.election.accessMode !== 'api') {
    showNotice('This election is not configured for API voting.')
    return
  }

  if (state.election.status !== 'live') {
    showNotice('This election is not currently live.')
    return
  }

  elements.loginForm.classList.remove('hidden')
}

getElection()

Your index.js should now look like this.

Replace cv_pub_xxxxx with the public key from your CrownVote election.

code index.js
const API_URL = 'https://api.crownvote.com/api/v1'
const PUBLIC_KEY = 'cv_pub_xxxxx'

const state = {
  election: null,
  accessToken: null,
  ballots: [],
  selections: {},
}

const elements = {
  title: document.querySelector('#electionTitle'),
  description: document.querySelector('#electionDescription'),
  notice: document.querySelector('#notice'),
  loginForm: document.querySelector('#loginForm'),
  voterId: document.querySelector('#voterId'),
  password: document.querySelector('#password'),
  ballotScreen: document.querySelector('#ballotScreen'),
  voterInfo: document.querySelector('#voterInfo'),
  ballots: document.querySelector('#ballots'),
  submitVote: document.querySelector('#submitVote'),
}

function showNotice(message) {
  elements.notice.textContent = message
  elements.notice.classList.remove('hidden')
}

function hideNotice() {
  elements.notice.textContent = ''
  elements.notice.classList.add('hidden')
}

async function getElection() {
  hideNotice()

  const response = await fetch(`${API_URL}/election`, {
    headers: {
      'X-PUBLIC-KEY': PUBLIC_KEY,
    },
  })

  const result = await response.json()

  if (!result.status) {
    showNotice(result.message || 'Unable to load election.')
    return
  }

  state.election = result.data.election

  elements.title.textContent = state.election.title
  elements.description.textContent =
    state.election.description || state.election.instructions || 'Login to cast your vote.'

  if (state.election.votingMode !== 'remote') {
    showNotice('This starter guide is for remote voting only.')
    return
  }

  if (state.election.accessMode !== 'api') {
    showNotice('This election is not configured for API voting.')
    return
  }

  if (state.election.status !== 'live') {
    showNotice('This election is not currently live.')
    return
  }

  elements.loginForm.classList.remove('hidden')
}

getElection()
task_alt

What you have now

Your app can now contact CrownVote, load the election, confirm it is suitable for this remote starter, and show the voter login form when voting is available.