Blog · 21 October 2026 · TransCAPI

Building Truvel on TransCAPI

The best way to find out whether an API is any good is to build something real on it. So we recently started Truvel, a public journey planner for Great Britain and Ireland, and gave it one rule: it holds no transport data of its own. Every journey, fare, live time and percentage on it comes from TransCAPI, through the same endpoints and the same kind of key anyone can get.

This is how it's put together, how it stays fast, and what building it found wrong with the API.

What Truvel does

Truvel's pitch is the journey planner that tells you what will actually happen. Most planners show you a timetable with some live times on top. Truvel adds the things TransCAPI measures:

  • The chance of making each change, from how those exact buses ran on recent days: "15 min to change at Weeton, works almost every day", or "Risky: 2 changes, all work 1 day in 3".
  • How punctual each line really is at your stop, and its worst hour.
  • The fare for every journey, with railcards, a change of train priced as one through ticket.
  • Where you can get to in 15, 30 and 45 minutes, drawn on a map.
  • Carbon and walking effort on every journey, with a "gentle slopes only" option for anyone who needs it.

Plus the usual: live departure boards for any station or stop, live train platforms and expected times, and journey detail with a map of every leg.

How it's built

Truvel is deliberately small: a Flask app of about 6,500 lines of Python, 4,000 lines of plain JavaScript and no build step. The browser only ever talks to Truvel. Truvel adds the TransCAPI key on the server and calls the API, so the key never reaches a page.

That makes Truvel's own /api/ routes a public front door to a paid API, so each one is narrow. Every route makes one known TransCAPI call, from parameters that are checked first, so it can't be used as an open relay. Routes are rate-limited per IP address, and Truvel's calls to TransCAPI have a site-wide limit and a cache. If you're putting a TransCAPI key behind a public site, that's the pattern we'd suggest.

Station and stop boards are rendered on the server, so they work without JavaScript and search engines can find them. They refresh every 30 seconds by fetching the same page again, which suits TransCAPI caching boards for 20.

Making search feel instant

A journey search through TransCAPI takes about 1.5–4 seconds on MOTIS. On slow phones and networks it's more. Truvel hides most of that wait:

  • It searches before you press Search. A request starts 400 ms after both places are set, and again whenever the time or options change, cancelling the one before. Pressing Search shows the search that's already in flight, or already finished.
  • It asks only for what it shows. Results leave out turn-by-turn steps and intermediate stops. Those are fetched when you open a journey.
  • It caches twice. Places are snapped to about 50 metres and "leave now" to the minute, so repeated searches are cached for two minutes on the server, and identical requests already in flight share one call. The page keeps results too, so Back, Later and re-sorting are instant.
  • It fills the wait. Skeleton cards appear straight away, "Checking live times and fares…" after two seconds, and live departures from the nearest stop or station, which take about a second.
  • It caps the load. At most 12 journey searches run at once, so a burst of slow ones can't take every thread.

In practice, someone choosing Sheffield to Leeds had results 2.1 seconds after picking the second place, before they'd pressed Search.

What building it found

Building Truvel was the most thorough review TransCAPI has had. Its developer kept a running list of everything in the API that was wrong, surprising or missing, with the exact requests. Some of what it found:

  • The old journey engine was too slow. On OpenTripPlanner, journeys took 4–15 seconds, and a search with a walking limit could time out entirely. Truvel was the first client to use MOTIS, and its measurements were part of why we switched engines.
  • "Arrive by" picked the wrong end of the window. Asked to arrive by 08:30, the new engine returned the right journeys but kept the earliest five, so people were told to leave an hour early. Fixed the next day: it now keeps the journeys arriving closest to the time asked.
  • Walking limits returned nothing on the new engine. Also fixed the next day.
  • Dublin's trams showed up a tram early. The cause was in the source feed: Luas runs to a frequency, and the feed attached each forecast to whichever timetabled trip came next, so times were right but on the wrong trips. We now show Luas from its timetable until the feed can be trusted.
  • Reachable areas in Ireland were walking only on the day Ireland launched, because that morning's reachability data had been built before Ireland's timetables were added. Rebuilding it gave 45 minutes from Dublin centre reaching 142 km² and 2,345 stops.
  • Place search doesn't put stations first. "Leeds" finds the town but not the station, because the national stop database calls it "Leeds Rail Station". This one is still on our list. Truvel works around it by running a general search and a station-only search side by side.

Truvel also set the bar for how honest the data has to be. It shows "Today: N min to spare" for a change only when the arriving bus is actually tracked, and warns about changes with no spare time even when there's no history to give a percentage.

Build your own

Everything Truvel does is available to anyone with a key: journeys with connection chances and fares (/v1/journey.json), boards (/v1/bus/stop_timetables, /v1/rail/station_timetables), punctuality (/v1/bus/stop_reliability), rail fares (/v1/rail/fares.json) and reachability (/v1/journey/reachable.json). The guides have runnable code for each, and Truvel shows what they look like put together.


Try it. TransCAPI is one API for buses, trains and journey planning across Great Britain. A free key gives you 500 requests a day with no card; the journey docs cover the parameters.