The Provider API endpoints are intended to be implemented by mobility providers and consumed by regulatory agencies. When a municipality queries information from a mobility provider, the Provider API has a historical view of operations in a standard format.
This specification contains a data standard for mobility as a service providers to define a RESTful API for municipalities to access on-demand.
The following information applies to all provider
API endpoints. Details on providing authorization to endpoints is specified in the auth document.
This specification uses data types including timestamps, UUIDs, and vehicle state definitions as described in the MDS General Information document.
provider
APIs must handle requests for specific versions of the specification from clients.
Versioning must be implemented as specified in the Versioning section.
The response to a client request must include a valid HTTP status code defined in the IANA HTTP Status Code Registry.
See Responses for information on valid MDS response codes and Error Messages for information on formatting error messages.
The response must set the Content-Type
header as specified in the Versioning section.
Response bodies must be a UTF-8
encoded JSON object and must minimally include the MDS version
and a data
payload:
{
"version": "x.y.z",
"data": {
"trips": [{
"provider_id": "...",
"trip_id": "...",
}]
}
}
All response fields must use lower_case_with_underscores
.
MDS defines JSON Schema files for each endpoint.
provider
API responses must validate against their respective schema files. The schema files always take precedence over the language and examples in this and other supporting documentation meant for human consumption.
The /trips
and /status_changes
endpoints must not use pagination.
If Providers choose to use pagination for either of the /events
or /vehicles
endpoints, the pagination must comply with the JSON API specification.
The following keys must be used for pagination links:
first
: url to the first page of datalast
: url to the last page of dataprev
: url to the previous page of datanext
: url to the next page of data
At a minimum, paginated payloads must include a next
key, which must be set to null
to indicate the last page of data.
{
"version": "x.y.z",
"data": {
"trips": [{
"provider_id": "...",
"trip_id": "...",
}]
},
"links": {
"first": "https://...",
"last": "https://...",
"prev": "https://...",
"next": "https://..."
}
}
Municipalities requiring MDS Provider API compliance should provide an unambiguous digital source for the municipality boundary. This boundary must be used when determining which data each provider
API endpoint will include.
The boundary should be defined as a polygon or collection of polygons. The file defining the boundary should be provided in Shapefile or GeoJSON format and hosted online at a published address that all providers and provider
API consumers can access and download. The boundary description can be sent as a reference to an GeoJSON object or flat-file, if the agency is using Geography.
Providers are not required to recalculate the set of historical data that is included when the municipality boundary changes. All new data must use the updated municipality boundary.
Because of the unreliability of device clocks, the Provider is unlikely to know with total confidence what time an event occurred at. However, Providers are responsible for constructing as accurate a timeline as possible. Most importantly, the order of the timestamps for a particular device's events must reflect the Provider's best understanding of the order in which those events occurred.
For Timestamps, Vehicle Types, Propulsion Types, UUIDs, Costs, and Currencies, refer to the MDS General Information document.
A trip represents a journey taken by a mobility as a service customer with a geo-tagged start and stop point.
The trips endpoint allows a user to query historical trip data.
Unless stated otherwise by the municipality, the trips endpoint must return all trips with a route
which intersects with the municipality boundary.
Endpoint: /trips
Method: GET
Beta feature: No
Schema: trips
schema
data
Payload: { "trips": [] }
, an array of objects with the following structure
Field | Type | Required/Optional | Comments |
---|---|---|---|
provider_id |
UUID | Required | A UUID for the Provider, unique within MDS. See MDS provider list. |
provider_name |
String | Required | The public-facing name of the Provider |
device_id |
UUID | Required | A unique device ID in UUID format |
vehicle_id |
String | Required | The Vehicle Identification Number visible on the vehicle itself |
vehicle_type |
Enum | Required | See vehicle types table |
propulsion_types |
Enum[] | Required | Array of propulsion types; allows multiple values |
trip_id |
UUID | Required | A unique ID for each trip |
trip_duration |
Integer | Required | Time, in Seconds |
trip_distance |
Integer | Required | Trip Distance, in Meters |
route |
GeoJSON FeatureCollection |
Required | See Routes detail below |
accuracy |
Integer | Required | The approximate level of accuracy, in meters, of Points within route |
start_time |
timestamp | Required | |
end_time |
timestamp | Required | |
publication_time |
timestamp | Optional | Date/time that trip became available through the trips endpoint |
parking_verification_url |
String | Optional | A URL to a photo (or other evidence) of proper vehicle parking |
standard_cost |
Integer | Optional | The cost, in the currency defined in currency , that it would cost to perform that trip in the standard operation of the System (see Costs & Currencies) |
actual_cost |
Integer | Optional | The actual cost, in the currency defined in currency , paid by the customer of the mobility as a service provider (see Costs & Currencies) |
currency |
String | Optional, USD cents is implied if null. | An ISO 4217 Alphabetic Currency Code representing the currency of the payee (see Costs & Currencies) |
The /trips
API should allow querying trips with the following query parameters:
Parameter | Format | Expected Output |
---|---|---|
end_time |
YYYY-MM-DDTHH , an ISO 8601 extended datetime representing an UTC hour between 00 and 23. |
All trips with an end time occurring within the hour. For example, requesting end_time=2019-10-01T07 returns all trips where 2019-10-01T07:00:00 <= trip.end_time < 2019-10-01T08:00:00 UTC. |
If the data does not exist or the hour has not completed, /trips
shall return a 404 Not Found
error.
Without an end_time
query parameter, /trips
shall return a 400 Bad Request
error.
For the near-ish real time use cases, please use the events endpoint.
To represent a route, MDS provider
APIs must create a GeoJSON FeatureCollection
, which includes every observed point in the route, even those which occur outside the municipality boundary.
Routes must include at least 2 points: the start point and end point. Routes must include all possible GPS or GNSS samples collected by a Provider. Providers may round the latitude and longitude to the level of precision representing the maximum accuracy of the specific measurement. For example, a-GPS is accurate to 5 decimal places, differential GPS is generally accurate to 6 decimal places. Providers may round those readings to the appropriate number for their systems.
Trips that start or end at a Stop must include a stop_id
property in the first (when starting) and last (when ending) Feature of the route
. See Stop-based Geographic Data for more information.
"route": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"timestamp": 1529968782421,
// Required for Trips starting at a Stop
"stop_id": "95084833-6a3f-4770-9919-de1ab4b8989b",
},
"geometry": {
"type": "Point",
"coordinates": [
-118.46710503101347,
33.9909333514159
]
}
},
{
"type": "Feature",
"properties": {
"timestamp": 1531007628377,
// Required for Trips ending at a Stop
"stop_id": "b813cde2-a41c-4ae3-b409-72ff221e003d"
},
"geometry": {
"type": "Point",
"coordinates": [
-118.464851975441,
33.990366257735
]
}
}]
}
The status of the inventory of vehicles available for customer use.
The status changes endpoint allows a user to query the historical availability for a system within a time range.
Unless stated otherwise by the municipality, this endpoint must return only those status changes with a event_location
that intersects with the municipality boundary.
Note: As a result of this definition, consumers should query the trips endpoint to infer when vehicles enter or leave the municipality boundary.
Endpoint: /status_changes
Method: GET
Beta feature: No
Schema: status_changes
schema
data
Payload: { "status_changes": [] }
, an array of objects with the following structure
Field | Type | Required/Optional | Comments |
---|---|---|---|
provider_id |
UUID | Required | A UUID for the Provider, unique within MDS. See MDS provider list. |
provider_name |
String | Required | The public-facing name of the Provider |
device_id |
UUID | Required | A unique device ID in UUID format |
vehicle_id |
String | Required | The Vehicle Identification Number visible on the vehicle itself |
vehicle_type |
Enum | Required | see vehicle types table |
propulsion_types |
Enum[] | Required | Array of propulsion types; allows multiple values |
vehicle_state |
Enum | Required | See vehicle state table |
event_types |
Enum[] | Required | Vehicle event(s) for state change, allowable values determined by vehicle_state |
event_time |
timestamp | Required | Date/time that event occurred at. See Event Times |
publication_time |
timestamp | Optional | Date/time that event became available through the status changes endpoint |
event_location |
GeoJSON Point Feature | Required | See also Stop-based Geographic Data |
battery_pct |
Float | Required if Applicable | Percent battery charge of device, expressed between 0 and 1 |
trip_id |
UUID | Required if Applicable | Trip UUID (foreign key to Trips API), required if event_types contains trip_start , trip_end , trip_cancel , trip_enter_jurisdiction , or trip_leave_jurisdiction |
associated_ticket |
String | Optional | Identifier for an associated ticket inside an Agency-maintained 311 or CRM system |
The /status_changes
API should allow querying status changes with the following query parameters:
Parameter | Format | Expected Output |
---|---|---|
event_time |
YYYY-MM-DDTHH , an ISO 8601 extended datetime representing an UTC hour between 00 and 23. |
All status changes with an event time occurring within the hour. For example, requesting event_time=2019-10-01T07 returns all status changes where 2019-10-01T07:00:00 <= status_change.event_time < 2019-10-01T08:00:00 UTC. |
If the data does not exist or the hour has not completed, /status_changes
shall return a 404 Not Found
error.
Without an event_time
query parameter, /status_changes
shall return a 400 Bad Request
error.
All MDS compatible provider
APIs must expose a public GBFS feed as well. Compatibility with GBFS 2.0 or greater is advised due to privacy concerns and support for micromobility.
GBFS 2.0 includes some changes that may make it less useful for regulatory purposes (specifically, the automatic rotation of vehicle IDs). The /vehicles
endpoint offers an alternative to GBFS that may more effectively meet the use cases of regulators. Additional information on MDS and GBFS can be found in this guidance document.
The data returned by a near-realtime endpoint should be as close to realtime as possible, but in no case should it be more than 5 minutes out-of-date. Near-realtime endpoints must contain last_updated
and ttl
properties in the top-level of the response body. These properties are defined as:
Field Name | Required | Defines |
---|---|---|
last_updated | Yes | Timestamp indicating the last time the data in this feed was updated |
ttl | Yes | Integer representing the number of milliseconds before the data in this feed will be updated again (0 if the data should always be refreshed). |
The /events
endpoint is a near-realtime feed of status changes, designed to give access to as recent as possible series of events.
The /events
endpoint functions similarly to /status_changes
, but shall not included data older than 2 weeks (that should live in /status_changes.
)
Unless stated otherwise by the municipality, this endpoint must return only those events with an event_location
that intersects with the municipality boundary.
Note: As a result of this definition, consumers should query the trips endpoint to infer when vehicles enter or leave the municipality boundary.
See also Stop-based Geographic Data.
The schema and datatypes are the same as those defined for /status_changes
.
Endpoint: /events
Method: GET
Beta feature: No (as of 1.0.0)
Schema: events
schema
data
Payload: { "status_changes": [] }
, an array of objects with the same structure as in /status_changes
The events API should allow querying with a combination of query parameters:
Parameter | Type | Expected Output |
---|---|---|
start_time |
timestamp | status changes where start_time <= status_change.event_time |
end_time |
timestamp | status changes where status_change.event_time < end_time |
Should either side of the requested time range be missing, /events
shall return a 400 Bad Request
error.
Should either side of the requested time range be greater than 2 weeks before the time of the request, /events
shall return a 400 Bad Request
error.
Stop information should be updated on a near-realtime basis by providers who operate docked mobility devices in a given municipality.
In addition to the standard Provider payload wrapper, responses from this endpoint should contain the last update timestamp and amount of time until the next update in accordance with the Data Latency Requirements:
{
"version": "x.y.z",
"data": {
"stops": []
},
"last_updated": "12345",
"ttl": "12345"
}
Endpoint: /stops/:stop_id
Method: GET
Beta feature: Yes (as of 1.0.0)
data
Payload: { "stops": [] }
, an array of Stops
In the case that a stop_id
query parameter is specified, the stops
array returned will only have one entry. In the case that no stop_id
query parameter is specified, all stops will be returned.
The /vehicles
endpoint returns the current status of vehicles on the PROW. Only vehicles that are currently in available, unavailable, or reserved states should be returned in this payload. Data in this endpoint should reconcile with data from the /status_changes
enpdoint. As with other MDS APIs, /vehicles
is intended for use by regulators, not by the general public. It does not replace the role of a GBFS feed in enabling consumer-facing applications.
In addition to the standard Provider payload wrapper, responses from this endpoint should contain the last update timestamp and amount of time until the next update in accordance with the Data Latency Requirements:
{
"version": "x.y.z",
"data": {
"vehicles": []
},
"last_updated": "12345",
"ttl": "12345"
}
Endpoint: /vehicles
Method: GET
Beta feature: Yes (as of 0.4.1)
Schema: vehicles
schema
data
Payload: { "vehicles": [] }
, an array of objects with the following structure
Field | Type | Required/Optional | Comments |
---|---|---|---|
provider_id |
UUID | Required | A UUID for the Provider, unique within MDS. See MDS provider list. |
provider_name |
String | Required | The public-facing name of the Provider |
device_id |
UUID | Required | A unique device ID in UUID format, should match this device in Provider |
vehicle_id |
String | Required | The Vehicle Identification Number visible on the vehicle itself, should match this device in provider |
vehicle_type |
Enum | Required | see vehicle types table |
propulsion_types |
Enum[] | Required | Array of propulsion types; allows multiple values |
last_event_time |
timestamp | Required | Date/time when last state change occurred. See Event Times |
last_vehicle_state |
Enum | Required | Vehicle state of most recent state change. |
last_event_types |
Enum[] | Required | Vehicle event(s) of most recent state change, allowable values determined by last_vehicle_state . |
last_event_location |
GeoJSON Point Feature | Required | Location of vehicle's last event. See also Stop-based Geographic Data. |
current_location |
GeoJSON Point Feature | Required if Applicable | Current location of vehicle if different from last event, and the vehicle is not currently on a trip. See also Stop-based Geographic Data. |
battery_pct |
Float | Required if Applicable | Percent battery charge of device, expressed between 0 and 1 |