Fares v2¶
Fares v2 is a GTFS extension project that aims to address the limitations of Fares v1. This extension project is being adopted in iterations. The below examples outline how to model basic concepts, including fare products and how riders can use their fare for transfers. See more information about the Fares v2 extension project here.
In the interim, producers may implement Fares v2 alongside the implementation of Fares v1 in the same dataset as there is no technical conflict between the two. Consumers will have the choice of which implementation to consume independently from the other. With adoption and sufficient endorsement of Fares v2, Fares v1 may be deprecated in the future. In the interim, producers may implement Fares v2 alongside the implementation of Fares v1 in the same dataset as there exists no technical conflict between the two. Consumers will have the choice of which implementation to consume independently from the other.
The below examples outline how to model data using Fares v2 and it can be completed with experimental features outlined in the full proposal document.
Fares v2 training and free resources¶
To get started with GTFS Fares-v2, you can watch these four video tutorials and follow along with this written resource.
- Video 1: GTFS Fares-v2: An introduction
- Video 2: GTFS Fares v2: Setting up Google Sheets
- Video 3: GTFS Fares v2: Creating and Maintaining Data
- Video 4: Exporting and Publishing GTFS Fares v2
They have been created for transit agencies to understand the purpose of GTFS-Fares v2, as well as how to use Google Sheets to create, edit, and upload GTFS-Fares v2 data.
This Fares v2 template can be used for creating the necessary fares files from scratch.
Fares v2 data modelling examples¶
Define a transit fare¶
There are several ways to pay fares to use the Maryland Transit Administration system. There are four types of regular full price fare options:
- One-way ticket that costs $2.00 USD
- Day pass that costs $4.60 USD
- Weekly pass that costs $22 USD
- A monthly pass that costs $77 USD
Transit tickets or fares are referred to as fare products in GTFS. They can be described using the fare_products.txt file. Each entry corresponds to a specific fare.
fare_product_id | fare_product_name | amount | currency |
---|---|---|---|
core_local_oneway_fare | One Way Full Fare | 2.00 | USD |
core_local_1_day_fare | 1-Day Pass - Core Service | 4.60 | USD |
core_local_31_day_fare | 31-Day Pass - Core Service | 77.00 | USD |
core_local_7_day_fare | 7-Day Pass - Core Service | 22.00 | USD |
Download the Maryland Transit Administration local bus GTFS feed
Create rules for single leg journeys¶
In GTFS, a fare leg corresponds to a trip that a rider makes without transferring between different modes, routes, networks, or agencies. In the Maryland Transit Administration's feed, a single fare allows riders to travel within any pair of stops and subway stations within the core
network of BaltimoreLink buses, Light RailLink and Metro SubwayLink routes.
Leg groups define trips within a network from an origin to a destination (or a set of origins to a set of destinations if the area IDs correspond to grouped stops). The file below describes rules to travel anywhere within the Maryland Transit Administration’s core network. Each rule corresponds to one of the regular fare products in the Define a transit fare example.
leg_group_id | network_id | fare_product_id |
---|---|---|
core_local_one_way_trip | core | core_local_oneway_fare |
core_local_one_way_trip | core | core_local_1_day_fare |
core_local_one_way_trip | core | core_local_31_day_fare |
core_local_one_way_trip | core | core_local_7_day_fare |
Download the Maryland Transit Administration local bus GTFS feed
Create rules for transfers¶
There is a 90 minute transfer for riders who purchase a one-way fare to ride BaltimoreLink local buses, Metro SubwayLink, or Light RailLink. This means that they can transfer an unlimited number of times between the local buses, subway, and light rail within the 90 minute timeframe.
from_leg_group_id | to_leg_group_id | duration_limit | duration_limit_type | fare_transfer_type | transfer_count |
---|---|---|---|---|---|
core_local_one_way_trip | core_local_one_way_trip | 5400 | 1 | 0 | -1 |
The file above represents this in GTFS with the following fields:
- A transfer is possible to and from legs that are a one way trip (
core_local_one_way_trip
) - The
transfer_count
is set to-1
since there is no limit on the number of transfers permitted - The
duration_limit
is set to5400
seconds, which is equivalent to 90 minutes - The
duration_limit_type
is set to1
since the transfer time starts when the rider departs on any route in thecore_local_one_way_trip
fare leg and ends when they depart on a different fare leg. - The
fare_transfer_type
is set to0
since riders only pay for the first fare. There is no transfer fee or a second fare for transferring within the 90 minute window. Hence, the cost can be modeled as the sum of the first fare and the sum of the transfer fees. - The
transfer_count
is set to-1
as the rider can transfer an unlimited number of times within the 90 minuteduration_limit
window.
After defining the fare, creating the appropriate fare_leg_rule
, and defining the fare_transfer_rule
, you can see the $2.00 USD core_local_oneway_fare
appear in trip planners. Here is an example from Transit:
Download the Maryland Transit Administration local bus GTFS feed
Describe service locations in the same fare zone¶
Some transit agencies operate a zone-based fare structure. Fare zones are divided geographic areas associated with different fare prices. In Bay Area’s BART system, fares are different depending on the origin and destination (BART fare differences), and transit riders will need to know the right fare. Fare areas can be described using the stops_areas.txt file, which assigns stops from stops.txt to areas.txt.
First, identify the area in areas.txt . It is acceptable to leave area_name
blank if there is no area name. In the table below, there are three area_id
- ASHB
, GLEN
, and OAKL
.
area_id | area_name |
---|---|
ASHB | |
GLEN | |
OAKL |
Afterwards, using stop_id
from the stops.txt file, group stops together to its respective identified area (fare zone).
Next, group stop_id
to each area_id
. In the BART example, each area contains only 1 stop_id
. For instance, only stop ASHB
(Ashby Station) is included in the area ASHB
However, if an area includes multiple stops, multiple stop_id
should be listed.
area_id | stop_id |
---|---|
ASHB | ASHB |
GLEN | GLEN |
OAKL | OAKL |
In fare_leg_rules.txt
, different fare products can be identified based on different departure and arrival areas. For example, the first entry shows:
- Departure area is
ASHB
- Arrival area is
GLEN
- The fare product for the departure/arrival area is
BA:matrix:ASHB-GLEN
leg_group_id | from_area_id | to_area_id | fare_product_id |
---|---|---|---|
BA | ASHB | GLEN | BA:matrix:ASHB-GLEN |
BA | ASKB | OAKL | BA:matrix:ASHB-OAKL |
The fare is identified in fare_products.txt
.
fare_product_id | fare_product_name | amount | currency |
---|---|---|---|
BA:matrix:ASHB-GLEN | generated | 4.75 | USD |
BA:matrix:ASHB-OAKL | generated | 9.45 | USD |
See the San Francisco Bay Area Regional feed
Describe what fare media is accepted¶
San Francisco Muni riders can use several different types of fare media to pay for their trip and validate their fare:
- Use a Clipper card, the Bay Area’s transit card
- Use the Munimobile app
- Pay for the fare in cash
These validation methods are referred to as fare_media
in GTFS-Fares v2 and can be described using fare_media.txt
.
Below is an example snippet from the San Francisco Bay Area Regional Feed that can be accessed with the 511 SF Bay API.
Clipper
is described as a physical transit card with fare_media_type=2
. SFMTA Munimobile
is described as a mobile app with fare_media_type=2
. Cash
has no fare media, since it is given directly to the driver without a ticket. As a result, Cash
is fare_media_type=0
.
fare_media_id | fare_media_name | fare_media_type |
---|---|---|
clipper | Clipper | 2 |
munimobile | SFMTA MuniMobile | 4 |
cash | Cash | 0 |
See the San Francisco Bay Area Regional feed
Additionally, producers who want to describe a physical ticket as a fare media can use fare_media_type=1
.
The Massachusetts Bay Transportation Authority (MBTA) allows users to pay for trips and passes using a physical paper ticket called CharlieTicket. To reflect this, there is a charlieticket
fare media in MBTA’s feed with a fare_media_type=1
.
fare_media_id | fare_media_name | fare_media_type |
---|---|---|
cash | Cash | 0 |
charlieticket | CharlieTicket | 1 |
mticket | m Ticket app | 4 |
See the Massachusetts Bay Transportation Authority feed
Define price differences based on fare media¶
Muni's fare price is different based on the fare media the rider uses. This example will cover how the adult local fare price changes when using cash or Clipper card. An adult local fare paid for with cash costs $3 USD and the same fare paid for with the Clipper card costs $2.50, 50 cents less.
Each entry below describes a fare media.
fare_media_id | fare_media_name | fare_media_type |
---|---|---|
clipper | Clipper | 2 |
cash | Cash | 0 |
The fare_products.txt
file snippet below shows how the amount of the Muni single local fare
product varies depending on the fare media that the rider uses.
fare_product_id | fare_product_name | amount | currency | fare_media_id |
---|---|---|---|---|
SF:local:single | Muni single local fare | 3 | USD | cash |
SF:local:single | Muni single local fare | 2.5 | USD | clipper |
In Apple Maps, riders can see how their fare price changes. You can compare fare prices under the "Board the Muni J Church train" instruction:
See the San Francisco Bay Area Regional feed
Describe a contactless fare media option¶
The Clean Air Express in Northern Santa Barbara County accepts contactless payment by credit card, Google Pay and Apple Pay.
In the Clean Air Express feed, there is a tap_to_ride
fare media with a fare_media_type=3
, since it’s a cEMV (contactless Europay, Mastercard and Visa) option.
fare_media_id | fare_media_name | fare_media_type |
---|---|---|
tap_to_ride | Tap to Ride | 3 |
The single ride fare product shown below has both cash
and tap-to-ride
fare media options. When the single ride is paid for with the tap-to-ride
fare media, it is one USD dollar cheaper.
fare_product_id | fare_product_name | fare_media_id | amount | currency |
---|---|---|---|---|
single-ride | Single Ride | tap_to_ride | 6 | USD |
single-ride | Single Ride | 7 | USD |
Download the Clean Air Express feed
Define price differences based on time and day of trip¶
Certain transit agencies vary their fares based on the time and/or day of the week. This means that fares are associated with a time period where the trip is made, such as peak, off-peak hours, or weekends.
Washington DC’s Metrorail fares vary based on multiple factors, including the day and time of the trip. Variable time fares in GTFS can be defined using timeframes.txt
, in which it is possible to designate specific time periods that then can be associated in fare_leg_rules.txt
to assign the applicable fare product that corresponds to the time when the trip is made. The following is a fictional example, based on WMATA's fares as of spring 2023.
First, service days are defined using calendar.txt
.
service_id | monday | tuesday | wednesday | thursday | friday | saturday | sunday | start_date | end_date |
---|---|---|---|---|---|---|---|---|---|
weekday_service | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 20220708 | 20221231 |
saturday_service | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 20220708 | 20221231 |
sunday_service | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 20220708 | 20221231 |
Afterwards, the desired timeframes are defined in timeframes.txt
, providing an id, the applicable days via a reference to calendar.service_id
, and if applicable, the start time and end time for each time period.
timeframe_group_id | start_time | end_time | service_id |
---|---|---|---|
weekday_peak | 5:00:00 | 9:30:00 | weekday_service |
weekday_offpeak | 9:30:00 | 15:00:00 | weekday_service |
weekday_peak | 15:00:00 | 19:00:00 | weekday_service |
weekday_offpeak | 19:00:00 | 21:30:00 | weekday_service |
weekday_late_night | 21:30:00 | 24:00:00 | weekday_service |
weekday_late_night | 00:00:00 | 5:00:00 | weekday_service |
weekend | saturday_service | ||
weekend | sunday_service |
Next, the corresponding time specific fares in fare_products.txt
are created (e.g. Peak fare)
fare_product_id | fare_product_name | amount | currency |
---|---|---|---|
peak_fare | Peak fare | 5 | USD |
regular_fare | Off-peak fare | 3 | USD |
weekend_fare | Weekend Metrorail one-way fare | 2 | USD |
late_night_fare | Late Night flat fare (Mon - Fri after 9:30pm) | 2 | USD |
Lastly, timeframes are associated with fare products in fare_leg_rules.txt
using the fields from_timeframe_group_id
and to_timeframe_group_id
. These fields determine whether a fare applies solely to the start of the leg or both the start and end of the leg.
For this example, based on WMATA fares, the fare depends only on the leg's departure timeframe, so to_timeframe_group_id
is left blank.
network_id | fare_product_id | from_timeframe_group_id | to_timeframe_group_id |
---|---|---|---|
1 | weekend_fare | weekend | |
1 | late_night_fare | weekday_late_night | |
1 | peak_fare | weekday_peak | |
1 | regular_fare | weekday_offpeak |
Note that network_id
references the foreign ID networks.network_id
or routes.network_id
, and that the selection of the correct fare product for each trip will be a combination of arrival and departure times from stop_times.txt
along with the times defined in timeframes.txt
.
In this case, a user paying for a trip that departs at 7:30 AM would have to pay 5.00 USD (Peak fare) while another user departing at 11:30 AM would only have to pay a 3.00 USD fare (Off-peak fare).
Define time-variable fares along with zone based fares¶
In New York's MTA Metro-North railroad network, fares vary based on both the time of the day of the trip, as well as the trip’s origin and destination areas. The following example illustrates the fare rules applicable to a trip from Grand Central Station to Cold Spring (NY, USA).
This example is based on a dataset produced by ITO World, featuring a trip that uses ten stops distributed in six different areas.
stop_id | stop_name | stop_lat | stop_lon |
---|---|---|---|
ITO1669 | Peekskill | 41.285103 | -73.930916 |
ITO1777 | Beacon | 41.505814 | -73.984474 |
ITO1789 | New Hamburg | 41.58691 | -73.947624 |
ITO1804 | Croton-Harmon | 41.190002 | -73.882393 |
ITO1824 | Cortlandt | 41.246258 | -73.921783 |
ITO1856 | Garrison | 41.381126 | -73.947334 |
ITO1887 | Harlem-125th Street | 40.805256 | -73.939148 |
ITO1897 | Cold Spring | 41.415382 | -73.958092 |
ITO2096 | Poughkeepsie | 41.707058 | -73.93792 |
ITO2383 | Grand Central | 40.752823 | -73.977196 |
area_id | stop_id |
---|---|
mnr_1 | ITO1887 |
mnr_1 | ITO2383 |
mnr_HUD-5 | ITO1804 |
mnr_HUD-6 | ITO1669 |
mnr_HUD-6 | ITO1824 |
mnr_HUD-7 | ITO1856 |
mnr_HUD-7 | ITO1897 |
mnr_HUD-8 | ITO1777 |
mnr_HUD-8 | ITO1789 |
mnr_HUD-9 | ITO2096 |
network_id | route_id |
---|---|
mnr_hudson | 669 |
network_id | network_name |
---|---|
mnr_hudson | MNR Hudson Line |
Service days for train services 3 and 13 are defined using calendar.txt
. Notably, other records with generic days (i.e. weekdays, weekends, and anyday) that aren't associated with any trips are defined, and these will be associated with timeframes in order to model time-variable fares
.
service_id | monday | tuesday | wednesday | thursday | friday | saturday | sunday | start_date | end_date |
---|---|---|---|---|---|---|---|---|---|
13 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 20230612 | 20231006 |
3 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 20230609 | 20231006 |
weekdays | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 20220101 | 20240101 |
weekends | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 20220101 | 20240101 |
anyday | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 20220101 | 20240101 |
Records are created in timeframes.txt
, including cases where the time covers the 24-hour range period (anytime
, weekdays
and weekends
), and peak and off-peak periods:
- AM Peak: from 6 am to 10 am on weekdays
- AM2PM Peak: from 6 AM to 9 AM and from 4 pm to 8 pm on weekdays
- Not AM Peak: weekday time not included in AM Peak
- Not AM2PM Peak: weekday time not included in AM2PM Peak
timeframe_group_id | start_time | end_time | service_id |
---|---|---|---|
anytime | 00:00:00 | 24:00:00 | anyday |
weekdays | 00:00:00 | 24:00:00 | weekdays |
weekends | 00:00:00 | 24:00:00 | weekends |
mnr_ampeak | 06:00:00 | 10:00:00 | weekdays |
mnr_notampeak | 00:00:00 | 06:00:00 | weekdays |
mnr_notampeak | 10:00:00 | 24:00:00 | weekdays |
mnr_am2pmpeak | 06:00:00 | 09:00:00 | weekdays |
mnr_am2pmpeak | 16:00:00 | 20:00:00 | weekdays |
mnr_notam2pmpeak | 00:00:00 | 06:00:00 | weekdays |
mnr_notam2pmpeak | 09:00:00 | 16:00:00 | weekdays |
mnr_notam2pmpeak | 20:00:00 | 24:00:00 | weekdays |
Each individual fare product is defined in fare_products.txt
. Since Cold Spring is located in zone 7, this example only lists trips between zone 1 and 7. The full dataset would include a record for each price defined by a time and zone combination. Additionally, the example only displays one fare media (paper
), but additional combinations could be created if prices would also vary based on the fare media.
fare_product_id | fare_product_name | fare_media_id | amount | currency |
---|---|---|---|---|
mnr_1:HUD-7_adult_peak | Outbound Adult Peak Zonal Fare | paper | 20.00 | USD |
mnr_1:HUD-7_adult | Outbound Adult Off Peak Zonal Fare | paper | 15.00 | USD |
mnr_HUD-7:1_adult_peak | Inbound Adult Peak Zonal Fare | paper | 20.00 | USD |
mnr_HUD-7:1_adult | Inbound Adult Off Peak Zonal Fare | paper | 15.00 | USD |
Lastly, the combinations of origin and destination areas, along with their respective timeframes are associated with the corresponding fare product in fare_leg_rules.txt
. Here, trips starting or arriving in Zone 1 (i.e. area_id=mnr_1
) during peak times are subject to a specific peak fare corresponding to the arrival and departure zones of the trip (i.e. fare_product_id=mnr_1:HUD-7_adult_peak
).
network_id | from_area_id | to_area_id | fare_product_id | from_timeframe_group_id | to_timeframe_group_id |
---|---|---|---|---|---|
mnr_hudson | mnr_1 | mnr_HUD-7 | mnr_1:HUD-7_adult | mnr_notam2pmpeak | anytime |
mnr_hudson | mnr_1 | mnr_HUD-7 | mnr_1:HUD-7_adult | weekends | anytime |
mnr_hudson | mnr_1 | mnr_HUD-7 | mnr_1:HUD-7_adult_peak | mnr_am2pmpeak | anytime |
mnr_hudson | mnr_HUD-7 | mnr_1 | mnr_HUD-7:1_adult | weekdays | mnr_notampeak |
mnr_hudson | mnr_HUD-7 | mnr_1 | mnr_HUD-7:1_adult | weekends | anytime |
mnr_hudson | mnr_HUD-7 | mnr_1 | mnr_HUD-7:1_adult_peak | weekdays | mnr_ampeak |
Using this dataset, a user boarding train #869 (service_id=3
) scheduled to depart from Grand Central (zone mnr_1
) at 6:45 pm would have to pay an Outbound Adult Peak Zonal Fare of 20.00 USD, since the trip is originated in the mnr_am2pmpeak
period and from zone mnr_1
.
Alternatively, a user traveling in train #883 (service_id=13
) would pay an Outbound Adult Off Peak Zonal Fare of only 15.00 USD, as this train is scheduled to depart Grand Central (zone mnr_1
) at 9:04 pm.
In Apple Maps, riders can see how their fare price changes and compare fare prices next to the train scheduled departure: