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.

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

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"
  }' \
  https://tallys.uk/api/v1/crowd/submissions

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.