Undocumented MTA API capabilities


This morning on the MTA Developer Forum I received a question on my post from prior about my OBA Path Extractor tool. It got me thinking that, since the Bustime site seems to be a single page application, there must be a RESTful call to get all the bus stops that are listed in either direction under the left-hand column. I played around for a bit and was finally able to find the call. For route BX5, for example, the call http://bustime.mta.info/api/stops-on-route-for-direction?callback=jsonp1444833569642&_=1444833813644&routeId=MTA+NYCT_BX5&directionId=0 is made when navigating to that route. It is curious that the routes are decoupled from the shapefile, as I would imagine those would be useful.

Also strange is that the initial call that returns the encoded polylines (which I wrote the tool from a few posts ago to untangle), includes in its JSON response object a key store for stops yet this value is always null. Why not just throw in the stops at that points and save the subsequent call? Seems like an easy add, to me. Also strange is how the MTA does not seem to follow the One Bus Away (OBA) standards. If you look online at the MTA site for the OBA API, they send you to the organization’s RESTful API documentation. There, they have a section specifically for querying by route for stops. The method string is stops-for-route and and example is provided as such: http://api.pugetsound.onebusaway.org/api/where/stops-for-route/1_44.xml?key=TEST&version=2.

So, given that, why do they diverge in their implementation of OBA with the prior listed call http://bustime.mta.info/api/stops-on-route-for-direction?callback=jsonp1444833569642&_=1444833813644&routeId=MTA+NYCT_BX5&directionId=0? This question is, rhetorical, but it seems strange to me to link to a resource that, if actually followed, would enable users to easily query vast amounts of very useful information but, now, requires a user to munge throught the web browser console’s XHR results to find a call that is comparable to the one that was referenced in the documentation.

Either way, the endpoint is indeed useful and I intend to add it to the OBA Extractor tool I made from before so look out for that update shortly. For the time being, if you are interested in quickly grabbing all the stops for a particular route, then simply go to http://bustime.mta.info/api/stops-on-route-for-direction?routeId=MTA+NYCT_X12&directionId=0 where X12 is your route’s ID and directionId is set to either 1 or 0 for the direction you want.

I am still trying to figure out the nuances to this API. Some calls, such as a call to route Q6 (http://bustime.mta.info/api/stops-on-route-for-direction?routeId=MTA+NYCT_Q6&directionId=0), will result in an internal error (500). Also, the api will error on M60-SBS. Thus, there is some issue with the way those routes are called. I’ll need to figure that out prior to implementing the update. If anyone has thoughts I am all ears. From what I can see, the call when running for route Q6 is made such that the MTA+NYCT component is switched and the call then looks like this: http://bustime.mta.info/api/stops-on-route-for-direction?callback=jsonp1444837332588&_=1444837373240&routeId=MTABC_Q06&directionId=0.

A cleaned up version, without the callback value, looks like: bustime.mta.info/api/stops-on-route-for-direction?routeId=MTABC_Q06&directionId=0. I think the situation is that the Q6 line is operated by the MTABC rather than the MTA. Being a recent transplant I am not clear on what the difference is between the two. I googled around and was only able to find this, which suggests that riders are aware that there appears to be two operators. How one would know if the system is one or the other I am unsure of. A cursory review of the first call that is made on querying a route (http://bustime.mta.info/api/search?callback=jsonp1444837332584&_=1444837337187&q=Q6) shows that it seems to be using what is included in the suggestions response under the key value for the match id: MTABC_Q06. This result is then submitted under the routeId key value in the subsequent call. I wonder if there was some way, though, of getting a defacto list of all the routes that fall under each operator. That way, one could “construct” a call without needing to run the prior, first.