When my train is delayed, I’m entitled to a partial or full refund through my rail operator’s delay-repay scheme. In practice, submitting a claim means cross-referencing my booking confirmation with the actual departure and arrival times for that service — tedious to do manually, easy to forget. I built this tool to automate it end-to-end.
View the interactive demo → · Open the live app → (requires authorised Google account)
How it works
Email parsing — A sync job reads booking confirmation emails from Gmail using the Gmail API. Each email is parsed to extract the journey legs: origin, destination, travel date, ticket type, and price.
Historical performance lookup — For each journey, the tool queries the Rail Data Marketplace HSP (Historical Service Performance) API to find the actual departure and arrival times recorded for that service on that date.
Delay calculation — The scheduled and actual times are compared. The delay in minutes is banded into the standard delay-repay thresholds (15–29 min, 30–59 min, 60–119 min, 120+ min).
Review UI — Results are stored in BigQuery and surfaced through a FastAPI backend and a Firebase-hosted web app. The UI shows each journey with its delay band, which services were matched, and the current claim status (pending / submitted / settled).
Architecture
Gmail → Email Parser → HSP API → BigQuery
↓
FastAPI (Cloud Run) → Firebase Hosting (web app)
- Email parser: reads raw MIME emails, extracts structured journey data
- HSP client: queries
serviceMetricsto list candidate service IDs, thenserviceDetailsfor per-stop times; handles 429 rate-limiting with exponential back-off - BigQuery: stores journeys and service candidates; station configuration lives in a
stationstable so the code is generic - FastAPI on Cloud Run: REST API with Firebase Auth — only my account can access real data
- Firebase Hosting: single-page app;
/api/*rewrites proxied to Cloud Run
Key features
- Automatically surfaces delay-repay opportunities from booking emails without any manual input
- Matches each journey against multiple candidate services and lets me pick the correct one
- Tracks claim status (pending → submitted → settled) per journey leg
- Supports both advance (fixed-time) and flexible return tickets, with different time-window logic for each
- Station configuration stored in BigQuery — no hardcoded routes in the source code
Stack
| Layer | Technology |
|---|---|
| Backend | Python, FastAPI |
| Data store | Google BigQuery |
| Train data | HSP API (Rail Data Marketplace) |
| Gmail API (OAuth2) | |
| Hosting | Firebase Hosting + Cloud Run |
| Auth | Firebase Authentication (Google sign-in) |
| Infra | Google Cloud (Secret Manager, Artifact Registry) |
| Package management | uv |