Site icon APILayer Blog – All About APIs: AI, ML, Finance, & More APIs

Build a 7-Day Departure Board with Aviationstack

Build a 7-Day Departure Board with Aviationstack

One of the first problems you’ll face within a week of running a product in the aviation industry is how fast you can reach the rate limit, particularly if you allow users to make direct requests via your data provider. 

There are 2 main issues here. First, your provider might suspect you are attempting a DNS. Secondly, since you are making too many calls, your bills will increase far beyond normal.

A more excellent engineering approach will be not calling the API on every load. Instead, you can fetch the flight data for the week, save it locally, and serve customer queries from it. 

In this guide, we will be going through how you can build a 7-day departure board with the Aviationstack API endpoints. 

What is Aviationstack?

Aviationstack is an API product that supplies data around the aviation industry, and it is useful to aviation product builders, airports, and even individuals. The responses come in a well-structured JSON format, which you can further feed into your data pipeline. 

It covers over 250 countries and 13,000 airlines. If you are an enterprise company, it might also interest you to know that more than 5,000 other blue-chip companies get their aviation data from Aviationstack. 

With Aviationstack, you have access to data on everything from past flights, current flights, lookups and so on. 

What separates it is apt data updating, particularly 30 to 60 seconds. Meaning if you use the API, you will always get fresh aviation data for your business. 

To have a more technical understanding of Aviationstack and how the endpoints work, you should take some looks over the documentation.  

Explore Aviationstack API

Access real-time flight status, airline schedules, airport data, and global aviation information. Explore the API documentation to learn about available endpoints and start integrating aviation data into your application.

Explore API Documentation
Discover available API endpoints and flight data
Get started with Aviationstack API integration

Quick Guide to Building a 7-Day Departure Board with Aviationstack

The main idea of this script is to provide flight data of an airport for a week. Practically, we will spread this across:

  • 3 past days
  • Today
  • 3 days ahead 

That makes a week. 

Step 1: Import and Set Base

				
					import json, re, sys, time, urllib.error, urllib.parse, urllib.request
from datetime import date, timedelta

API_KEY = "ADD YOUR SECRET"
BASE_URL = "http://api.aviationstack.com/v1"
				
			

This is a straightforward script where you don’t need to have any external library installed or imported. Instead, internal Python libraries suffice. In this case, we’d be importing json, the url library, date and so on. 

We cannot call the Aviationstack without the API key. Get your secret from your Aviationstack dashboard and add to the script. As you should be aware, you can add your secrets via:

  • Encrypted CLI
  • Secret managers
  • Environment variable,
  • Or plain hardcoding

The first 2 options are more secure and we will encourage you to go that route. Nonetheless, for ease of reference, we will hardcode the secret for now. The next step from here is to add the Base URL you’re interacting with, which is the v1 of Aviationstack. 

Step 2: Calling the API

				
					def call_api(endpoint, **params):
    url = f"{BASE_URL}/{endpoint}?" + urllib.parse.urlencode({"access_key": API_KEY, "limit": 10, **params})
    for wait in (5, 60, None):  # first retry after 5s, then 60s
        time.sleep(2)  # space out calls; to avoid rate-limiting
        try:
            with urllib.request.urlopen(url, timeout=30) as r:
                body = json.load(r)
        except urllib.error.HTTPError as e:  
            body = json.load(e)
        err = body.get("error")
        if not err:
            return body.get("data") or [], None
        if wait and "rate" in json.dumps(err).lower():
            time.sleep(wait)
            continue
        return [], err


up = lambda s: s and s.upper()
				
			

This is the function that calls the API, loading parameters and endpoints. The url variable loads formatted Base URL along with the inputted endpoint, and it uses the API for access. Essentially, we added error handling mechanisms to handle bugs gracefully. 

More particularly, pay attention to how we handled rate limiting and responsible API calls above. 

  1. We limited the maximum number of flights to 10 per day. 
  2. We spaced the loads with the first try at 5 seconds, and 60 seconds for the retry. 
  3. In between requests, there is a 2 seconds sleep

We should emphasize though that 1 above isn’t for you if you’re already running a production-grade product and you’re on the plan that increases your request numbers accordingly. 

Nonetheless, 2 and 3 applies to any developer so you can make responsible requests. The main reason for spacing requests and adding sleep time is so the Aviationstack server doesn’t perceive you as a threat actor attempting to cause DNS. 

Step 3: Hour and Minute Function

				
					def hhmm(t):
    m = re.search(r"[T ](\d\d:\d\d)", t or "")
    return m and m.group(1)
				
			

We will still need this function later. We defined it here to store hours and minutes. By the way, the t parameter here is not to be inputted as you can see we didn’t specify the type of variable it should be. It is a definition of the t variable within the function. 

In short, it’s to handle the error of where t in the function runs into error. Instead of having that break our script, it will simply return empty strings. 

Step 4: Live Flight Function 

				
					def live(f):
    d, cs = f["departure"], f["flight"].get("codeshared")
    return {"flight": f["flight"]["iata"], "airline": f["airline"]["name"], "to": f["arrival"]["iata"],
            "time": hhmm(d["scheduled"]), "gate": d["gate"], "delay": d["delay"], "status": f["flight_status"],
            "operated_by": cs and up(cs["flight_iata"])}
				
			

We can’t build our 7-day departure script without collecting live data. In the live function, departure and codeshare are the dictionaries. They mainly return everything about every live flight from delay to airline and every other detail. 


You should also pay attention to the
operated_by endpoint as it works for codeshares of seats among airlines, pointing out whether or not there’s a codeshare to be mindful of. 

Step 5: Future Flight Function

				
					def future(f):
    cs = f.get("codeshared")
    return {"flight": up(f["flight"]["iataNumber"]), "airline": (f["airline"]["name"] or "").title(),
            "to": up(f["arrival"]["iataCode"]), "time": hhmm(f["departure"]["scheduledTime"]),
            "gate": f["departure"]["gate"] or None, "delay": None, "status": "scheduled",
            "operated_by": cs and up(cs["flight"]["iataNumber"])}
				
			

Our implementation of future flight is almost in tandem with the previously explained live flight above. The same explanation works for this one. 

Step 6: Flight Boarding Function

				
					def board(airport):
    today, days, restricted = date.today(), {}, None
    for n in (0, 1, 2, 3, -1, -2, -3):  # today, future, then past (past often not on plan)
        day = (today + timedelta(n)).isoformat()
        if n == 0:
            rows, err = call_api("flights", dep_iata=airport)
            flights = [live(f) for f in rows]
        elif n > 0:
            rows, err = call_api("flightsFuture", iataCode=airport, type="departure", date=day)
            flights = [future(f) for f in rows]
        else:
            rows, err = restricted or call_api("flights", dep_iata=airport, flight_date=day)
            flights = [live(f) for f in rows]
            if err and err.get("code") == "function_access_restricted":
                restricted = ([], err)  # don't waste calls on the remaining past days
        days[day] = {"flights": flights, **({"error": err} if err else {})}
    return {"airport": airport, "days": dict(sorted(days.items()))}
				
			

The nature of our 7-day flight departure script is to stream data from 3 days ago, today, and 3 more days for continuously relevant data. 

In today, days, restricted = date.today(), {}, None we have, loosely speaking, mapped:

Do you remember the call_api function we created earlier? We will call it internally along with its parameters and return the same. 

Step 7: Putting Responses in a JSON File

				
					if __name__ == "__main__":
    airport = (sys.argv[1:] or ["JFK"])[0].upper()
    path = f"departures_{airport}_{date.today()}.json"
    with open(path, "w") as f:
        json.dump(board(airport), f, indent=2)
    print(f"Saved {path}")
				
			

We exported the script execution with main. Then we configured the airport to either a distinctly supplied parameter; if not, the J.F. Kennedy airport should be the default. 

For proper rendering of the results, we formatted the key data we want to return, such as departure and airport, to be reported as JSON. 

Once the formatting is done, all the fetched data should be dumped into a separate JSON file, and print out in the terminal that the responses have been duly saved. 

Full Code

Here is the full code in this tutorial so far:

 

				
					import json, re, sys, time, urllib.error, urllib.parse, urllib.request
from datetime import date, timedelta

API_KEY = "ADD YOUR SECRET"
BASE_URL = "http://api.aviationstack.com/v1"


def call_api(endpoint, **params):
    url = f"{BASE_URL}/{endpoint}?" + urllib.parse.urlencode({"access_key": API_KEY, "limit": 10, **params})
    for wait in (5, 60, None):  # first retry after 5s, then 60s
        time.sleep(2)  # space out calls; to avoid rate-limiting
        try:
            with urllib.request.urlopen(url, timeout=30) as r:
                body = json.load(r)
        except urllib.error.HTTPError as e:  
            body = json.load(e)
        err = body.get("error")
        if not err:
            return body.get("data") or [], None
        if wait and "rate" in json.dumps(err).lower():
            time.sleep(wait)
            continue
        return [], err


up = lambda s: s and s.upper()


def hhmm(t):
    m = re.search(r"[T ](\d\d:\d\d)", t or "")
    return m and m.group(1)


def live(f):
    d, cs = f["departure"], f["flight"].get("codeshared")
    return {"flight": f["flight"]["iata"], "airline": f["airline"]["name"], "to": f["arrival"]["iata"],
            "time": hhmm(d["scheduled"]), "gate": d["gate"], "delay": d["delay"], "status": f["flight_status"],
            "operated_by": cs and up(cs["flight_iata"])}


def future(f):
    cs = f.get("codeshared")
    return {"flight": up(f["flight"]["iataNumber"]), "airline": (f["airline"]["name"] or "").title(),
            "to": up(f["arrival"]["iataCode"]), "time": hhmm(f["departure"]["scheduledTime"]),
            "gate": f["departure"]["gate"] or None, "delay": None, "status": "scheduled",
            "operated_by": cs and up(cs["flight"]["iataNumber"])}


def board(airport):
    today, days, restricted = date.today(), {}, None
    for n in (0, 1, 2, 3, -1, -2, -3):  # today, future, then past (past often not on plan)
        day = (today + timedelta(n)).isoformat()
        if n == 0:
            rows, err = call_api("flights", dep_iata=airport)
            flights = [live(f) for f in rows]
        elif n > 0:
            rows, err = call_api("flightsFuture", iataCode=airport, type="departure", date=day)
            flights = [future(f) for f in rows]
        else:
            rows, err = restricted or call_api("flights", dep_iata=airport, flight_date=day)
            flights = [live(f) for f in rows]
            if err and err.get("code") == "function_access_restricted":
                restricted = ([], err)  # don't waste calls on the remaining past days
        days[day] = {"flights": flights, **({"error": err} if err else {})}
    return {"airport": airport, "days": dict(sorted(days.items()))}


if __name__ == "__main__":
    airport = (sys.argv[1:] or ["JFK"])[0].upper()
    path = f"departures_{airport}_{date.today()}.json"
    with open(path, "w") as f:
        json.dump(board(airport), f, indent=2)
    print(f"Saved {path}")
				
			

Result

Here is how the result will look.

 

				
					  {
          "flight": "VS2492",
          "airline": "Virgin Atlantic",
          "to": "SAV",
          "time": "14:35",
          "gate": "A14",
          "delay": 0,
          "status": "scheduled",
          "operated_by": "9E5460"
        }
      ]
    },
    "2026-10-02": {
      "flights": [
        {
          "flight": "6E4016",
          "airline": "Indigo",
          "to": "IST",
          "time": "00:25",
          "gate": null,
          "delay": null,
          "status": "scheduled",
          "operated_by": "TK12"
        },
        {
          "flight": "AV6634",
          "airline": "Sa Avianca",
          "to": "IST",
          "time": "00:25",
          "gate": null,
          "delay": null,
          "status": "scheduled",
          "operated_by": "TK12"
        },



// AND SO ON

				
			

As seen above, you’ll get quite sufficient data including 

  • Flight reference
  • Respective airlines
  • Destination
  • Time
  • Status, and so on

Conclusion

If you’ve coded along in this tutorial, you’d have built a functional departure board script with the Aviationstack. With the data saved in your JSON and updating as often as you call it, you can point your users to querying it.

This way, you are not hitting the API on every load. Additionally, you can keep serving your 7-day departure board without hitting any rate limit at all. That said, you might also want to think of adding a UI for users to interact with your application, if you don’t already have one or if it is necessary.

That said, enterprise teams can simply tap into the Aviationstack API for continuously streamed accurate aviation data. Ready to check out Aviationstack?

Explore Aviationstack API Pricing

Access real-time flight status, airline schedules, airport information, and global aviation data through the Aviationstack API. Explore available plans to find the right fit for your application.

Explore API Pricing
Compare available plans and API request limits.
Find the right plan for your aviation data needs.

FAQ

How do I get future flight schedules from an API?

You can get future flight schedules from the Aviationstack API by calling endpoints such as flightsFuture. 

How do I serve a week-long departure board without hitting rate limits?

Fetch your data from reliable APIs like Aviationstack, store it locally, and serve requests from the DB you’ve built already.

How do I handle the Aviationstack rate limit?

You can handle Aviationstack rate limits by spacing your retries and having sleeps between your calls. 

What is the Aviationstack flightsFuture endpoint?

The Aviationstack flightsFuture endpoint helps you request data about the flight schedules of many airlines and airports in the coming days or months. 

How do I build a flight departure board?

You can build a flight departure board by writing a script that supplies data on all the 7 days in the week, and probably adding a UI to it for user interactions. 

STAY CONNECTED

Exit mobile version