DEV Community

Amit Jotwani
Amit Jotwani

Posted on

How to make HTTP Requests from an Alexa Skill to Get Data from an External API using Python 3

As a developer, every day we interact with remote APIs and web servers. Almost all services we consume on the internet today are available in the form of an API: weather forecasts, geolocation services, Twitter feeds, and so on.

It’s only fair to imagine, that you may run into situations in which you would want an Alexa Skill to get meaningful data from one of these remote sources by making HTTP requests to their APIs. HTTP requests allow you to fetch data from a remote source. It could be an API, a website, or something else.

In this post, we will take a quick look how you can get external data from an external API from an Alexa Skill using Python 3.

While there are many libraries to make an HTTP request in Python, including http.client (formerly named httplib ), urllib , httplib2 , treq , etc., the Requests library is among the most popular Python libraries for making HTTP requests. The subtitle of “HTTP for Humans” perfectly captures the philosophy behind it. It abstracts the complexities of making requests behind a simple interface, and makes HTTP requests easy and simple.

If you’re using Alexa Hosted as the backend for your skills, there’s an added advantage of the Requests library being built-in, so you don’t need to install or upload it manually. If you’re using AWS Lambda or any other service as the backend, you may need to install the requests module locally, and then upload it to the service.

So, with that out of the way, let’s jump into how you can use the Requests library to make an HTTP request to an API. For the purposes of this tutorial, we will be using the Chuck Norris API. You can obviously replace that with other APIs of your choice.

Using Requests library to make an API call from an Alexa Skill

Step 1: Import the requests package by adding an import statement to the top of lambda_function.py:

import requests

Step 2: Create a helper function to make the call to the API using the endpoint

def getResponseFromAPI():
    url = 'https://api.chucknorris.io/jokes/random'
    response = requests.get(url)
    print(response.status_code) 

    json_data = response.json()
    joke = json_data['value']
    return joke

Here’s a sample of what the data that would get returned by the Chuck Norris API, and would be stored in the variable

Alt Text

Step 3: Call the helper function from inside the LaunchRequestHandler (or any other intent handler that may be appropriate).

class LaunchRequestHandler(AbstractRequestHandler):
    """Handler for Skill Launch."""

    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool

        return ask_utils.is_request_type("LaunchRequest")(handler_input) or ask_utils.is_intent_name("AMAZON.YesIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        logging.info("LaunchRequest was trigerred")

        joke = getResponseFromAPI()
        return (
            handler_input.response_builder
            .speak(f"{joke}. Would you like to hear another Chuck Norris joke?")
            .ask("Would you like to hear another joke?")
            .response
        )

Hopefully that makes it easy to make API requests from your Alexa Skills. If you're looking to learn more about building Alexa Skills, I’ll leave you with some resources if you’re looking to learn more about Alexa Skills, and the Python requests library in general.

  1. Create an Alexa Skill in Five Minutes - Python & Node - Step-by-step training course from the Amazon team to build your first Alexa Skill
  2. Alexa Skills Kit SDK for Python
  3. Alexa Skills Kit SDK for Node.js

Discussion (1)

Collapse
w4krl profile image
Karl Berger • Edited

As a complete newbie, I don't know where to begin with your example. I have an Alexa Developer Console account and created a skill with the Custom Model and Alexa-Hosted Python. The next screen forces me to choose a template from Hello World Skill, Fact Skill, Quiz Game, High-Low Game, or Sauce Boss. None seem appropriate. I tried adding your example to Hello World but it didn't work. It says "Sorry, I had trouble doing what you asked. Please try again." Once it said "Here's something I found on the web. According to wikipedia.org: Chuck says that the fact she doesn't like olives is the only thing he knows about her that is real."

Here is my modification to the Hello World code:

import requests

def getResponseFromAPI():
url = 'api.chucknorris.io/jokes/random'
response = requests.get(url)
print(response.status_code)

json_data = response.json()
joke = json_data['value']
return joke

class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool

    return ask_utils.is_request_type("LaunchRequest")(handler_input)

def handle(self, handler_input):
# type: (HandlerInput) -> Response
logging.info("LaunchRequest was trigerred")

joke = getResponseFromAPI()
return (
        handler_input.response_builder
        .speak(f"{joke}. Would you like to hear another Chuck Norris joke?")
        .ask("Would you like to hear another joke?")
        .response
    )

class ChuckNorrisIntentHandler(AbstractRequestHandler):
"""Handler for Chuck Norris Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("ChuckNorrisIntent")(handler_input)

def handle(self, handler_input):
    # type: (HandlerInput) -> Response
    speak_output = "Hi from Chuck Norris!"

    return (
        handler_input.response_builder
            .speak(speak_output)
            # .ask("add a reprompt if you want to keep the session open for the user to respond")
            .response
    )