Search code examples
pythongtfs

error 400 when I try to use an API (Python)


I am trying to use the API from Société du Métro de Montréal (STM), a transportation GTFS transportation API.

I get error code 400 ("Too many requests") when trying the Python code below. I wonder if anyone is working with transportation APIs and can give me some hints on what I did wrong.

import requests
api_key = "API-KEY-FROM-DEVELOPER-ACCOUNT"
api_url = f"https://api.stm.info/pub/od/gtfs-rt/ic/v2/vehiclePositions"

# Prepare the request headers with the API key
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
     }

# Send the HTTP GET request to the API endpoint
response = requests.get(api_url, headers=headers)

# if you get 200 as response... everything ok
print("response.status_code",response.status_code)

# Check if the request was successful (status code 200)

if response.status_code == 200:
    try:
        # Parse the JSON response
        data = response.json()

        # Process and use the retrieved data as needed
        print(data)
    except ValueError as e:
        print("Error parsing JSON:", e)
        print("Response content:", response.text)
else:
    # Handle unsuccessful request
    print(f"Error: {response.status_code}")

I expected a response 200 for:

print("response.status_code",response.status_code)

LATER UPDATE Actually the issue was in the authentication method. I replaced the headers by the ones below and it gave me the response 200, confirming that I was able to connect to the API. = issue closed

headers = { "apiKey":api_key, "Content-Type": "application/json" }

Thanks to all who tried to help... and thanks a lot to ChatGPT !!! :)


Solution

  • After some fiddling (in the APIs page you can try the APIs real time), I found out that the field name for the API key is apikey. Thus, the following code should work:

    import requests
    api_key = "API-KEY-FROM-DEVELOPER-ACCOUNT"
    api_url = f"https://api.stm.info/pub/od/gtfs-rt/ic/v2/vehiclePositions"
    
    # Prepare the request headers with the API key
    headers = {
        "apikey": api_key,
         }
    
    # Send the HTTP GET request to the API endpoint
    response = requests.get(api_url, headers=headers);
    
    print(f"{response.status_code}: {response.content}")
    

    A few points to notice:

    1. Your API key will only be available after you publish your application. The option will be on the bottom of the application editing screen. If your "Application" is not showing "Enabled", you didn't finish it and your API key will not work.
    2. The response is a protobuf, not a json.

    It will be easier to use the Python language bindings to read the results. You can use the example below (adapted to python3):

    from google.transit import gtfs_realtime_pb2
    from urllib.request import Request, urlopen
    
    api_key = "API-KEY-FROM-DEVELOPER-ACCOUNT"
    api_url = f"https://api.stm.info/pub/od/gtfs-rt/ic/v2/vehiclePositions"
    
    feed = gtfs_realtime_pb2.FeedMessage()
    request = Request(api_url)
    request.add_header('apikey', api_key)
    response = urlopen(request)
    
    print(f'Status: {response.status_code}')
    
    feed.ParseFromString(response.read())
    for i, entity in enumerate(feed.entity):
      if entity.HasField('vehicle') and entity.vehicle.HasField('position'):
        pos = entity.vehicle.position
        print(f'{i} lat: {pos.latitude}, long: {pos.longitude}')