Part 2: Gentle Introduction to APIs for non-technical people… What is it? Why should we care ? And how to use them ?

NOTE: This article is part of the series. If you are new to this subject and want to learn the basics, you can start in Part 1. If you want to learn about benefits and use cases, you can skip to Part 3.

Let’s recap our list of Goals before we begin with Part 2:

Goals:

  1. Learn how APIs work in the grand scheme of things (Part 1)
  2. Demonstrate how API call works (Part 1)
  3. Demonstrate a simple example of real world use of APIs (Part 2)
  4. Discuss benefits & some use cases of API use in real life (Part 3)

In the previous section, we covered Goals #1 through #3. More specifically, we learned some basics of an API and saw how it works schematically between two services. In this section we will discuss how to make simple API call using Mac’s terminal and 3rd party GUI. Then we will use Python to demonstrate the same operation with some additional data manipulation operations.

Goal #4: Simple example of how to make an API call

Recall two important notes from Part 1:

Note 1: API Documentation

Figure — 1: Sample API Documentation view & main components

Note 2: API nothing but a code

Remember that API is nothing more but a code. API is not a server, nor a database, but a set of functions and procedures that gives an access to some server

… API is nothing but a code, which can be executed on your computer. In fact there are multiple ways to make an API call.

Execute API via Mac’s terminal

First, we will execute an API call from Mac’s terminal. Locate Terminal on your Mac and execute following command replacing “user-key: YOUR API KEY HERE” with your own API key

curl -X GET --header "Accept: application/json" --header "user-key: YOUR API KEY HERE" "https://developers.zomato.com/api/v2.1/categories"

CONGRATS! At this point you have made your first API call. If you get an output shown below, your API call was successful.

{"categories":[{"categories":{"id":1,"name":"Delivery"}},{"categories":{"id":2,"name":"Dine-out"}},{"categories":{"id":3,"name":"Nightlife"}},{"categories":{"id":4,"name":"Catching-up"}},{"categories":{"id":5,"name":"Takeaway"}},{"categories":{"id":6,"name":"Cafes"}},{"categories":{"id":7,"name":"Daily Menus"}},{"categories":{"id":8,"name":"Breakfast"}},{"categories":{"id":9,"name":"Lunch"}},{"categories":{"id":10,"name":"Dinner"}},{"categories":{"id":11,"name":"Pubs & Bars"}},{"categories":{"id":13,"name":"Pocket Friendly Delivery"}},{"categories":{"id":14,"name":"Clubs & Lounges"}}]}

Couple things to note:

  • Recall HTTP Protocol from Part 1. In this command we used GET command to retrieve information from Zomato.
  • The base URL stays the same for all API calls: http://developers.zomato.com/api/v2.1 . Only the API endpoint command changes. In our case it is categories/ . Referring back to Documentation, we could have done cities/ or any other API endpoint command.
  • All the “Parameters” described in the Documentation are located in the header: section of the Terminal command we executed. Note that Documentation didn’t specify whether parameters should be in the header or body part of the command (no documentation is perfect)

You can learn more about curl commands and how to use them.

Execute API via 3rd Party extensions

For the purpose of this demo, I used 3rd party GUI called Talend API, which is a Google Chrome extension.

Let’s execute the same operation, but with user friendly interface. The screenshot below illustrate the same command we performed using curl

Use 3rd party GUI to make an API call

The operation of making an API call is pretty standard and looks similar to that of executed in Terminal. In this case, we have user-friendly GUI that allows us to:

  1. Select HTTP Protocol. In our case, it is GET command to retrieve all the possible categories
  2. We specified both base and API endpoint URLs in one URL
  3. In the “HEADERS” section we provided the only required parameter, user-key along with API key. Note again that the parameter could have also been put as Query Parameter, which wasn’t specified in the Documentation.

Once we click on “Send”, we get the following output:

Output from API call using 3rd Party GUI

In the output, there 2 points to mention:

  1. The server response was 200, which means the request was successful. Alternatively, we could have gotten response code 403 — Invalid Key, as specified in Documentation.
  2. Body holds the same content we observed from the Terminal, but this time it is formatted so that it is easier to read.

Execute API using Python

In the following section we will write small Python script that will accomplish following:

  • Make 2 API calls: Get all the restaurants in the city of our choice, and get restaurant information for that city.
  • Filter the output from our API call to display only the information we need and save it in Excel file

First, let’s import libraries and set up all the variables.


import requests
import pandas as pd
import json
base_url = "https://developers.zomato.com/api/v2.1"headers = {
'Accept': 'application/json',
'user-key': 'YOUR API KEY HERE',
}
def as_json(json_object):
data = json.loads(json_object)
return data

If in the previous example, we used categories/ API endpoint to get started, in this example, we will use 2 API end points: /cities and /search . For each endpoint, let’s create two functions

  • Function get_cities() will get all the cities with similar names
  • Function get_restaurants() will find all the restaurants for particular city
# Function 1:def get_cities(city):    params = (
('q', city),
)
response = requests.get('{}/cities'.format(base_url), headers=headers, params=params)
return as_json(response.content)
#Function 2:def get_restaurants(city_id): params = (
('entity_id', city_id),
('entity_type', 'city'),
)
response = requests.get('{}/search'.format(base_url), headers=headers, params=params)

return as_json(response.content)

Now, let’s say we are trying to find all the cities in the US that have word “London”. Also, let’s specify that we are looking for London in Connecticut, USA.

When we run get_cities(city="London") function, we get following raw output (not entire content is shown):

{'location_suggestions': [{'id': 61, 'name': 'London', 'country_id': 215, 'country_name': 'United Kingdom', 'country_flag_url': 'https://b.zmtcdn.com/images/countries/flags/country_215.png', 'should_experiment_with': 0, 'has_go_out_tab': 0, 'discovery_enabled': 0, 'has_new_ad_format': 0, 'is_state': 0, 'state_id': 142, 'state_name': 'England and Wales', 'state_code': 'England and Wales'}, {'id': 3454, 'name': 'London, ON', 'country_id': 37, 'country_name': 'Canada', 'country_flag_url': 'https://b.zmtcdn.com/images/countries/flags/country_37.png', 'should_experiment_with': 0, 'has_go_out_tab': 0, 'discovery_enabled': 0, 'has_new_ad_format': 0, 'is_state': 0, 'state_id': 124, 'state_name': 'Ontario', 'state_code': 'ON'}, ...

This looks messy, so let’s create additional functions that cleans some of the API output and filters only city names and their states. Also, let’s add some logic that finds “London” located in Connecticut.

all_london_rest = london_rest['location_suggestions']
city_code = None
city_name = None
for city in all_london_rest:
city_n = city["name"]
print("Current city: {}".format(city_n))
if "CT" in city_n:
city_code = city["id"]
city_name = city_n
print("-----")
print("Successfully found: {} with code: {}".format(city_name, city_code) )

Running the script above, we get:

Current city: London
Current city: London, ON
Current city: London, KY
Current city: Londonderry, VT
Current city: New London, CT
Current city: New London, IA
Current city: New London, NH
Current city: New London, NC
-----
Successfully found: New London, CT with code: 10545

We have found 8 cities in the US that have “London” in the city name. But we also found desired city of New London in CT.

Now, we narrow our search and find all the restaurants located in New London, CT.

all_london_rest = get_restaurants(city_code)
rest_count = all_london_rest["results_found"]
first_twenty_rest = all_london_rest["restaurants"]
print("Found {} restaurants in New London".format(rest_count))
print("Only showing: {} restaurants".format(all_london_rest["results_shown"]))

When we run the code above we get following output:

Found 842 restaurants in New London
Only showing: 20 restaurants

And printing the content of all_london_rest variable, we get following (snippet) data back

[{'restaurant': {'R': {'has_menu_status': {'delivery': -1, 'takeaway': -1}, 'res_id': 17712697}, 'apikey': '67d6129dda419556b694a3623bb3bed6', 'id': '17712697', 'name': "Captain Scott's Lobster Dock", 'url': 'https://www.zomato.com/new-london-ct/captain-scotts-lobster-dock-new-london-new-london?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1', 'location': {'address': '80 Hamilton Street, New London 06320', 'locality': 'New London', 'city': 'New London', 'city_id': 10545, 'latitude': '41.3460000000', 'longitude': '-72.0976000000', 'zipcode': '06320', 'country_id': 216, 'locality_verbose': 'New London, New London'}, 'switch_to_order_menu': 0, 'cuisines': 'Seafood', 'timings': '11 AM to 7 PM (Mon-Sun)', 'average_cost_for_two': 25, 'price_range': 2, 'currency': '$', 'highlights': ['Lunch', 'Cash', 'Takeaway Available', 'Dinner', 'Credit Card', 'Street Parking', 'Outdoor Seating', 'Indoor Seating', 'Kid Friendly', 'Casual Attire', 'BYOB', 'Private Parking'], 'offers': []

Now, let’s clean this up and get only following information:

  • Restaurant Name
  • Cuisine
  • Operating hours
  • Price Range
parsed_rest = {}for restaurant in first_twenty_rest:
rest_object = restaurant["restaurant"]
rest_name = rest_object["name"]
rest_id = rest_object["R"]["res_id"]
rest_cuisines = rest_object["cuisines"]
rest_time = rest_object["timings"]
rest_price = rest_object["price_range"]

parsed_rest[rest_id] = {"name": rest_name, "cuisines": rest_cuisines, "timing": rest_time, "price_range": rest_price }

In the code snippet above we filtered and selected only the data we want to see. In reality, you can parse and filter depending on your use case.

Let’s put the data into Pandas DataFrame as an object and display it

df = pd.DataFrame(parsed_rest).T
print(df)

Although not necessary, Pandas library is useful for manipulating data and performing various operations.

We can take a step further and save our output in Excel file, which is literally one line command in Python

try:
df.to_excel("rest_list.xlsx")
print("Converted file to Excel successfully!")
except:
print("Conversion to excel failed!")

That’s it! Using some Python we were able to make an API request, filter through the data to select what we needed and save it in Excel file.

Although, our goal was to retrieve data from Zomato, using little Python, we were able to perform much more.

Being able to retrieve the data is only the beginning of its journey. The next step would be to uncover insights from the data to ensure it adds value to your business venture.

Next Up: Part 3 — Benefits of using APIs and discussion of some use cases

Thanks for reading my article. Check out my other stories. If you liked it, or have any comments/questions, let me know! Feel free to connect on social media: Instagram, GitHub, LinkedIn.

Software Developer & Data Scientist