omnitravel / transitous
Omnitravel's Transitous, under any PHP host, with no key: journeys from A to B, a stop's next departures and arrivals in real time (delays, tracks, cancellations), a stop and its lines, the stops near a point or by name - across the open timetables Transitous gathers worldwide, through its MOTIS 2 A
Requires
- php: >=8.2
- omnisense/contracts: ^1.0@dev
- omnisense/omnitravel: ^1.0@dev
- symfony/http-client: ^6.4|^7.0|^8.0
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-10 00:35:31 UTC
README
omnisense/omnitravel's Transitous, under any PHP host, with no key: Transitous is a community-run MOTIS 2 instance over the open timetables it gathers worldwide, with their real-time feeds and OpenStreetMap for the walks.
- journeys from A to B (
/api/v6/plan): legs on foot and on board, the line, its colours, the headsign, the stops called at, the path as a polyline, the real-time departure; - a stop's departures and arrivals (
/api/v6/stoptimes): the scheduled and the expected time, the track, cancellations; - a stop and its lines (
/api/v6/stop), the stops near a point (/api/v6/map/stops), stops by name (/api/v1/geocode).
use Omnitravel\Model\DepartureQuery; use Omnitravel\Transitous\TransitousFactory; $transitous = (new TransitousFactory($httpClient))->create([ 'user_agent' => 'MySite/1.0 (https://example.org; travel@example.org)', 'language' => 'fr', ]); $stop = $transitous->searchStops('Ralliement', 1, new Coordinates(47.4712, -0.5518))[0]; foreach ($transitous->departures(new DepartureQuery($stop->id, limit: 5)) as $departure) { echo $departure->line?->name, ' ', $departure->headsign, ' ', $departure->time()->format('H:i'), "\n"; }
Options: user_agent (required), base_uri (https://api.transitous.org; another MOTIS 2 server),
language, timeout.
Transitous' usage policy, as read on 2026-11-10
transitous.org/api: the API is for open-source, non-commercial projects that are light on its resources, on a best-effort basis.
- Every request carries a
User-Agentnaming the application, its version and a contact: the factory refuses one without (MySite/1.0 (https://example.org; travel@example.org)). - More than 720 requests a day of
/plan(or/one-to-many,/one-to-all) is heavy use, to be agreed with Transitous first: keep what you read (a cache of the application's), plan on a traveller's request only. Don't scrape: the data itself can be downloaded. - Link to transitous.org/sources in a visible place, follow each
source's conditions, and OpenStreetMap's attribution guidelines
(
Capabilities::$attribution,$terms). - Commercial use is not allowed; the staging server is not for applications.
The package declares it as data, in policy.json (omnisense/contracts' usage
policy, verifiedAt 2026-11-10): through omnitravel's registry, the 721st journey of a day is
refused before it reaches Transitous (UsageLimitReachedException), a 429 and its Retry-After
hold every call until the wait is over, and a site may lower the share
('policy' => ['rateLimits' => [['max' => 600, 'window' => 'day', 'operations' => ['journeys']]]]),
never raise it. A site that says it is commercial ('usage' => ['commercial' => true]) is refused.
The manual: docs/index.md. MIT.