Tallys.uk

Developers

Tallys API v1

Read UK election data and contribute crowd-sourced declarations. All endpoints live under /api/v1/ and require a Bearer API key. The API reads exclusively from our own database; Democracy Club is ingested in the background only, so request paths never depend on a third-party upstream.

Live ingest status - last sync time, success rate, per-election freshness.

Quickstart

  1. Ask an admin for an API key (or create one in the admin panel).
  2. Pass it as Authorization: Bearer tly_live_....
  3. Hit any endpoint below. Errors are JSON: { error: { code, message } }.
curl -H "Authorization: Bearer $TALLYS_KEY" \
  https://tallys.uk/api/v1/by-elections

All endpoints at a glance

Generated from the live election registry. Machine-readable JSON: /api/public.

Live tracker snapshots

ElectionStatusSnapshot URLPage
Senedd 2026live/api/public/results/senedd.2026/elections/senedd/2026
Senedd 2021archive/api/public/results/senedd.2021/elections/senedd/2021
Scottish Parliament 2026live/api/public/results/holyrood.2026/elections/holyrood/2026
UK Parliament 2024archive/api/public/results/westminster.2024/elections/westminster/2024
English local councils 2026live/api/public/results/english-locals.2026/elections/english-locals/2026
Welsh local councils 2022archive/api/public/results/locals.2022/elections/locals/2022
Police & Crime Commissioners 2024archive/api/public/results/pcc.2024/elections/pcc/2024

Aggregate public feeds

MethodPathPurpose
GET/api/public/by-electionsRolling UK by-elections snapshot (local + Senedd + PCC).
GET/api/public/english-locals.2026Aggregated English principal council results, 7 May 2026.
GET/api/public/holyrood.2026.amsHolyrood 2026 constituency + AMS regional list output.
GET/api/public/locals.2027Welsh principal council preview/snapshot for May 2027.
GET/api/publicThis manifest, as JSON.

v1 API

MethodPathScopePurpose
GET/api/v1/health-Service status. No auth.
GET/api/v1/electionsreadList elections.
GET/api/v1/elections/{electionId}readSingle election with prediction windows.
GET/api/v1/by-electionsreadBy-elections feed with provenance flags.
GET/api/v1/results/{electionId}readPer-constituency live results snapshot.
POST/api/v1/crowd/submissionscrowd:writeSubmit a crowd-sourced declaration.
GET/api/v1/crowd/submissions/{id}crowd:writeStatus of a submission you authored.

Internal hooks (cron only)

PathPurpose
/api/public/hooks/refresh-snapshotsRecompute every live snapshot. Cron-triggered.
/api/public/hooks/sync-live-resultsPull latest live results from Democracy Club.
/api/public/hooks/sync-electionResync a single election's metadata + ballots.
/api/public/hooks/sync-democracy-clubFull DC ballot/candidate sync.
/api/public/hooks/reconcile-crowdMatch crowd submissions against verified DC ballots.

Archive pages

  • /elections/senedd/2021 - Senedd 2021
  • /elections/westminster/2024 - UK Parliament 2024
  • /elections/locals/2022 - Welsh local councils 2022
  • /elections/pcc/2024 - Police & Crime Commissioners 2024

Underlying static datasets

  • src/data/elections/archive.ts - Static archive index
  • src/data/elections/westminster-2024-seats.ts - Westminster 2024 seats
  • src/data/elections/notional-2021.ts - Notional 2021 (Westminster)
  • src/data/elections/senedd-2026-regions.ts - Senedd 2026 regions
  • src/data/elections/holyrood-regions.ts - Holyrood regions
  • src/data/elections/english-councils.ts - English councils
  • src/data/elections/welsh-councils.ts - Welsh councils
  • src/data/elections/party-history.ts - Party history
  • src/data/elections/registry.ts - Election registry

Authentication

Bearer tokens. Two scopes: read for public data, crowd:writefor posting declarations. Keys are hashed at rest and shown once on creation. Default rate limit: 60 requests / minute / key. Responses include X-RateLimit-Limit and X-RateLimit-Remaining headers.

Endpoints

GET /api/v1/health

No auth. Returns service status.

GET /api/v1/elections

List elections. Optional query: ?nation=wales, ?status=live.

GET /api/v1/elections/{electionId}

Single election with prediction windows.

GET /api/v1/by-elections

Snapshot of UK by-elections (local + Senedd + PCC) with provenance flags (dc, crowd, crowd-dc-verified,crowd-dc-mismatch).

GET /api/v1/results/{electionId}

Per-constituency live results snapshot.

POST /api/v1/crowd/submissions

Scope crowd:write. Owner of the key must hold a contributor or verifier role. Submissions are reconciled against Democracy Club every minute.

curl -X POST \
  -H "Authorization: Bearer $TALLYS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ballot_paper_id": "local.example.ward.2026-05-07",
    "election_id": "local.example.2026-05-07",
    "winning_party_id": "lab",
    "winner_votes": 1234,
    "second_party_id": "con",
    "second_votes": 980,
    "total_votes": 2400,
    "turnout_pct": 32.1,
    "source_type": "council",
    "source_url": "https://council.example/results",
    "candidate_votes": [
      { "party_id": "lab", "name": "A. Smith", "votes": 1234 },
      { "party_id": "con", "name": "B. Jones", "votes": 980 },
      { "party_id": "ld",  "name": "C. Patel", "votes": 186 }
    ]
  }' \
  https://tallys.uk/api/v1/crowd/submissions

candidate_votes is optional but recommended - it powers per-candidate displays and lets us reconcile against Democracy Club at the row level.

GET /api/v1/crowd/submissions/{id}

Status of a submission you authored, including the current ballot reconciliation state.

Errors

CodeMeaning
missing_api_keyNo Bearer token in Authorization header.
invalid_api_keyKey not recognised, malformed, or revoked.
insufficient_scopeKey lacks the required scope for the endpoint.
rate_limitedPer-minute quota exceeded. See Retry-After.
validation_errorBody failed schema validation.