Files
politics-tracking/docs/contributing/api.md
T
simonandClaude Opus 5.5 583ccba31c Politrack: track Austrian politicians from public sources
Initial import of Politrack, a self-hosted service that tracks Austrian
politicians from federal to municipal level - roles, votes, money flows,
statements, meetings, social media and legal proceedings - with every claim
linked to its sources.

- backend: FastAPI + Postgres/pgvector; adapter framework (fetch -> parse ->
  load -> enrich) with robots.txt/TDM-aware fetching, a raw-response archive
  for reparsing, and a claim/evidence model with corroboration
- sources: Parliament, Wikidata, EU Parliament/Commission, Council of
  Ministers, Rechnungshof party reports and donations, procurement, RTR media
  transparency, political ad libraries, WKStA, news feeds, Wikipedia edits,
  Bluesky, Mastodon, public Telegram channels, YouTube and X (official API)
- web: Next.js frontend in German and English with typed API client
- mcp: MCP server for AI agents and RAG
- docs: architecture, data model, sources, legal notes, Unraid deployment and
  contributor guides; Docker Compose setup for Unraid

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 20:02:01 +01:00

2.7 KiB
Raw Blame History

Extending the API (and the MCP server)

Data flows out through three layers that are kept deliberately thin:

politrack/queries/<domain>.py   SQL, returns dicts          (shared by REST API and MCP server)
politrack/api/schemas.py        Pydantic response models    (the contract → OpenAPI → TypeScript)
politrack/api/main.py           FastAPI endpoints           (parameters, 404s, response_model)
politrack/mcp_server.py         MCP tools for AI agents     (same query functions)

Adding an endpoint, step by step

  1. Query – add a function to the matching module in politrack/queries/ (people, organizations, claims, votes, money, search, admin) and export it from queries/__init__.py.
    • Only show visible claims: use VISIBLE (published, not merged) from queries/common.py.
    • Respect the user's source filter: take a SourceFilter and use evidence_json(source_sql) to aggregate evidence – claims whose evidence is entirely filtered out must disappear.
    • Always parameterise (%(name)s), never format user input into SQL. LIMIT/OFFSET on lists.
  2. Response model – add a class to api/schemas.py (inherit from Model). Field names = column names.
  3. Endpoint – in api/main.py, with response_model=.... Reuse the dependencies DB, Sources, Limit, Offset; comma-separated list parameters go through csv_list().
  4. Types for the web app:
    cd backend && politrack openapi --ts ../web/src/lib/api-types.ts
    
    Then add a typed function to web/src/lib/api.ts. Commit the regenerated api-types.ts.
  5. MCP tool (if agents should use it) – a @mcp.tool() in mcp_server.py with a docstring that tells the agent what the data means and how to cite it.
  6. Test – extend the API smoke test (see testing.md).

Conventions

  • URLs: /api/v1/<plural noun>[/<slug>[/<sub-resource>]]; slugs, never internal ids, for people, parties and organisations (vote events use ids – they have no natural slug).
  • Every claim-like object carries evidence: [{url, title, source, published_at, quote, …}] and source_count.
  • Legal matters always include legal_stage; the client decides about the presumption-of-innocence notice (needsInnocenceNotice in the web app, the instructions in the MCP server).
  • Admin endpoints require Authorization: Bearer $POLITRACK_ADMIN_TOKEN and are excluded from the schema.

Read-only database access for agents and BI tools

The role politrack_reader (password POLITRACK_READER_PASSWORD) can SELECT everything. Useful views: claim_with_evidence, person_status, person_identifier. See ../data-model.md.