From Postman to Python: Your First GET Request

Maybe it's just me - but I feel like when we want to demonstrate product APIs to someone, we usually jump into Postman first. It's not without good reason though. Postman is a very easy to use platform for running API calls against REST endpoints & see the nicely formatted output.

That being said, often times I've seen that we stop there. We might mention Python as an advanced method of using our APIs, or maybe we talk about how "if APIs are the new CLI, Postman is the new PuTTY". I've seen some engineers who hear these statements and feel like Postman is being pushed on them - even when they're perfectly happy with an SSH-based CLI.

Network automation isn't usually accomplished with just one tool - it's a whole storage closet full of different tools & utilities, each with their own use cases or specializations. In this particular example - learning Python allows you to move beyond one-off API calls in Postman, and into being able to accomplish much more complex automation.

So the purpose of this post is to explore how to get beyond just Postman, and into using Python for REST API calls. This isn't going to be a complete run-down of all the capabilities of both tools - but rather a few examples of simple GET requests using both methods.

If you don't have Postman yet, go ahead and snag the download here.

Note: Much of the code below is minimal and does not contain any error handling. Therefore, it should not be used in a production network. Full example code here.


Postman: Simple GET Request

So first, let's start off with an example of using Postman for a simple GET request.

In this example, we'll keep things simple & use a non-authenticated API endpoint. We'll accomplish this using a free website called JSON Placeholder.

Let's go ahead and start up Postman, and we'll see a blank workspace:

001---Postman-1

What we'll need to pay attention to first, is what type of HTTP request we're sending - as well as the URL we want to send our request to. If we expand the request type dropdown, we'll see a handful of options - but we'll only be using a GET request for now:

002---Postman

In order to create our first request, we'll just need to enter our API endpoint URL. We'll use the users endpoint offered by JSON Placeholder, which is located at: https://jsonplaceholder.typicode.com/users

003---Postman

In the screenshot above, you'll see in the highlighted box that we entered our URL. Next, we just click the big Send button on the right side.

I already sent the GET request, so in the screenshot you'll also notice that we have our JSON response from the API. The mock data offered by this API provides us with a list of 10 different users, along with the data that's been entered for each user.

What if we only wanted to get data for one specific user? Well, our test API site supports using query parameters to filter our response. Let's say we want to find information for a user named Delphine. We would append ?username=Delphine to our URL:

004---Postman

So as we can see above - now our JSON response only contains the data for a single user. If we needed to find a user's phone number, this could be an easy way to quickly filter our data & get to what we need.

This is really where Postman is great. We're able to quickly & visually test out an API call. We can see what the response data looks like, and understand the structure of requests & responses.

But what about when we want to iterate through a number of users and pull only a specific few statistics? Or maybe we need a way to take a list of user information, and automatically upload or convert that data into another system.

For use cases like that, we'll jump over to Python.

Python: Simple GET Request

In this section, we'll walk through the same example from above - but this time using Python.

First thing we'll need to do, is install the Python requests library. While there are a handful of libraries that can accomplish this work, requests is fairly popular & easy to use.

So we'll kick things off by using pip to install our library:

pip install requests

Then, we'll create a very simple Python script to perform the same initial GET request from earlier. So we'll pull a list of ALL users from the API.

import requests

URL = "https://jsonplaceholder.typicode.com/users"

response = requests.get(URL)

print(response.text)

The code above should be pretty straightforward. First we'll import our requests library. Then, just to keep the code clean, we'll create a variable called URL to hold the URL for the API endpoint.

Next, we send that GET request, using requests.get. Last but not least, we'll go ahead and print out the text payload that we receive back. That output looks pretty similar:

[email protected]:~/postman-python$ python3 simpleGET.py 
[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "[email protected]",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
     -- output truncated -- 

Now, let's add a little extra logic to our next step. Rather than just specifying a static username that we want to search for, let's ask our user to specify a username:

import requests

URL = "https://jsonplaceholder.typicode.com/users"

print("Search by Username:")
user = input("> ")
queryURL = URL + f"?username={user}"
response = requests.get(queryURL)

print(response.text)

In the code above, we made just a few changes. One is printing out a prompt to "Search by Username". Then we use the Python input function to collect input from our user, then store that in the user variable.

Next, we create a queryURL - which is similar to the URL we used in the Postman example. Except in this case, we're supplying a dynamic username input based on whatever the end user wants to search for. We use a Python f-string to inject the username into our query parameters.

Let's see what that looks like:

[email protected]:~/postman-python$ python3 simpleGET.py 

Search by Username:
> Delphine
[
  {
    "id": 9,
    "name": "Glenna Reichert",
    "username": "Delphine",
    "email": "[email protected]",
    "address": {
      "street": "Dayna Park",
      "suite": "Suite 449",
      "city": "Bartholomebury",
      "zipcode": "76495-3109",
      "geo": {
        "lat": "24.6463",
        "lng": "-168.8889"
      }
    },
    "phone": "(775)976-6794 x41206",
    "website": "conrad.com",
    "company": {
      "name": "Yost and Sons",
      "catchPhrase": "Switchable contextually-based project",
      "bs": "aggregate real-time technologies"
    }
  }
]

Perfect! We get the result we expected, which is the single dataset from the user that we specified.

Let's take this one step further! Maybe we want to build a quick utility to search for a user's contact information. We can take the raw JSON output, pull out a few pieces of info, then apply some formatting to make it more user-friendly.

In the following example, we'll update our code to search that JSON response & collect the user's name, email address, and phone number.

import requests
import json

URL = "https://jsonplaceholder.typicode.com/users"

print("Search by Username:")
user = input("> ")
queryURL = URL + f"?username={user}"
response = requests.get(queryURL)

userdata = json.loads(response.text)[0]

name = userdata["name"]
email = userdata["email"]
phone = userdata["phone"]

print(f"{name} can be reached via the following methods:")
print(f"Email: {email}")
print(f"Phone: {phone}")

So a few things have changed in the above example. First thing you may notice, is that we've added an additional import: the json library. We use this in line 11, where we convert the JSON output into a native python object using the json.loads function.

What this allows us to do is easily pull individual data values from the JSON output. In the original JSON data that we received, we saw a bunch of user data organized into key-value pairs. So once we load that JSON into a Python dictionary, we can pull out individual values and assign them to variables.

Finally - we can print all of that data out to our terminal:

[email protected]:~/postman-python$ python3 simpleGET.py

Search by Username:
> Delphine
Glenna Reichert can be reached via the following methods:
Email: [email protected]
Phone: (775)976-6794 x41206

Nothing super fancy here - but this could be the beginnings of building out a user search web page, or maybe importing certain data fields into another system. Once we get the basics of working with REST APIs out of the way, there are a ton of possibilities for what can be built.

Okay - What About Network Automation?

Many new network technologies are now API enabled. Nearly every cloud-hosted platform or management controller offers some method of interacting programmatically. In fact, most routers & switches even offer a REST-based API that can be used for automated configuration or monitoring.

So let's take the following example: We have a couple of Meraki networks, and we've been tasked with providing a report of how many total clients have connected to our network in the last 30 days. In addition, it would be nice to see a breakdown of the distribution of operating systems.

Let's take a look at the following screenshot from Postman:

005---Postman

Using Meraki's API docs, we can determine the exact URL endpoint we need to query. This URL requires that we know the exact network ID for the network we want to get info from, which we'll pretend we already know. Also not shown here, we have an additional HTTP header that includes our API key - which was generated in Meraki Dashboard.

In addition, we have a few query parameters to help make sure we get the data we need. By default, this API endpoint will return 10 devices. In this particular network, we already know we have more than 10 - so we use the perPage query parameter to request up to 100 devices. We also wanted to query the last 30 days of devices, so we use the timespan parameter. This parameter expects the lookback to be in seconds, so we specify 43,200 seconds.

So we got back a list of devices - and specifically in the example shown, it looks like we have an Android device on our network. Easy enough to spot that info, right?

Well - maybe we have more than a handful of devices. We don't want to manually sort through all of that data & assemble a list. Or maybe this task needs to be run more than once. This is where we can use Python to automatically assemble that report with just a few lines of code.

import requests
import json

URL = "https://api.meraki.com/api/v1"
APIKEY = {"X-Cisco-Meraki-API-Key": "xxxxxxxxxxxxxxxxx"}

--- Code omitted ---

def getClients(orgID, networkList):
    """
    Query clients for each network, return client list
    """
    clientCount = {}
    total = 0
    # Query Parameters: Return up to 100 devices seen in the past 43,200 seconds (30 days)
    q = {"perPage": "100",
         "timespan": "43200"}
    for network in networkList:
        # Query clients for each network
        queryURL = URL + f"/networks/{network}/clients"
        response = requests.get(queryURL, params=q, headers=APIKEY)
        data = json.loads(response.text)
        # Grab client OS from each device & append to clientCount dictionary
        for client in data:
            try:
                clientCount[client["os"]] += 1
            except KeyError:
                clientCount[client["os"]] = 1
            except TypeError:
                continue
            total += 1
    # Append final count of all devices & return dict
    clientCount["Total Devices"] = total
    return clientCount

def printReport(clientOS):
    """
    Print final output to terminal
    """
    print("Count of clients by operating system:")
    for OS in clientOS:
        print(f"{OS}: {clientOS[OS]}")
        
--- Code omitted --- 

To keep things simple - we'll only look at a snippet of the code. The entire example will be posted to GitHub, and contains two additional functions that will automatically find our Organization ID & Network ID.

In our getClients function, we create an empty Python dictionary to hold our list of client operating systems - and we also create a total variable which we'll increment for every client in the list.

The HTTP GET request should look fairly similar to what we used previously. The big difference is that we're creating a dictionary called q to hold our perPage & timespan query parameters. Then we include that in our GET request by adding params=q to the request.

Next - we convert the JSON response into a Python object, and walk through every device in that list. For each device in the list, we look at the "os" value to determine the operating system detected by Meraki. We then use a try/except block to see if we can increment the counter for that operating system. If we get a KeyError, then we know the OS isn't currently on the list & we can just add it with a new value of 1.

After all that has been completed, we return our clientCount dictionary - which our primary function passes to the printReport function. This just prints out a header, then iterates through our clientCount dictionary and prints each operating system & count.

Let's take a look at that output below:

[email protected]:~/postman-python$ python getOScount.py
Count of clients by operating system:
None: 9
Sailfish OS: 2
Nokia: 1
Windows 10: 2
Raspberry Pi: 2
Android: 4
Meraki OS: 1
Total Devices: 21

In the list above, we can see that we have a total of 21 devices in our network - and 7 different operating systems were found as well.

That output may not be the prettiest of reports, but it was accomplished with ~50 lines of Python & takes less than a few seconds to run. If we wanted to format the data in another way, or include data from a non-Meraki source, we absolutely could.

That's part of what's exciting about using Python for network automation - most anything we could think of doing is possible.

TIP: Use Postman to Generate Python Code

Okay - so I wanted to save this bit for last. Now that you've seen examples in both tools, I wanted to make sure we cover a feature in postman that can save some time.

So over in the right-hand side of your Postman window, you'll see an icon that looks like this: </>

006---Postman

If you click that, you'll see a dropdown menu of various languages & tools. Select one of those options and Postman will auto-generate code you can use. This auto-generated code will execute the same request you have built in the Postman GUI.

For example, our last Postman request we used to get Meraki clients:

007---Postman

I wanted to save this for last, because I feel like it's important to understand how to write the code manually first - then take advantages of shortcuts after having a good understanding of what the code is doing.


That's about all I had for this example. Again, my intent here wasn't to create an all-inclusive resource for how to use Postman & Python - but rather to give some examples for each one & show where/why each would be used.

I've met a handful of people over the years who have seen many API demos using Postman, but aren't sold yet on the value of learning Python & getting into network automation.

Hopefully these examples help bridge that gap a little bit 😄