This article was originally posted on Amazon Alexa Blog

Alexa Skill Recipe: Making HTTP Requests to Get Data from an External API

Amit Jotwani
7 min readApr 4, 2018

--

As a developer, every day you 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. When creating a skill, you are sure to run into situations in which you would want 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.

Making HTTP requests is a core functionality for modern languages, and when it comes to Node.js there are a fair amount of solutions to this problem, both built into the language and by the developer community. In this skill recipe, we look at two of the most popular methods you can use to call an external API through your Alexa skill using Node.js:

  • Recipe 1: Using the built-in “HTTP” or “HTTPS” modules in the standard library
  • Recipe 2: Using the “Request” module

We’ll look at both of these recipes to cook up some API integration into our skill. We will also look at the pros and cons of each approach.

Adding an HTTP Request to a Fact Skill

First, we’ll take this simple fact skill (written in Node.js), and modify the use case slightly to get facts about numbers (instead of space facts). Instead of using the hard-coded data as shown below, we will get the facts in real time by calling the simple (yet awesome) numbersapi.com, which is an API that offers interesting facts about numbers. You can give it a try in the browser by typing: https://numbersapi.com/21.

Here’s the kind of conversation we want to serve with this skill:

User: Alexa, ask number facts to give me a fact about 7 <Triggers the intent GetNumberFactIntent, and passes the number 7 as an AMAZON.NUMBER slot type>

Alexa: 7 is the number of main stars in the constellations of the Big Dipper and Orion. <Our skill calls numbersapi.com with https://numbersapi.com/7, and responds back with the fact>

This is what our code looks like with facts hard-coded into the skill:

Existing hard-coded data with facts about few numbers:

Your intent handler “GetNumberFactIntent” would then call upon the dataset above when triggered by the user:

The handler function for GetNumberFactIntent

Let’s now look at the Alexa recipes we can use to call our API to get facts about numbers dynamically.

Recipe 1: Using the Built-In “HTTP” Module in the Standard Library

Let’s begin by taking a quick look at our existing code for the GetNumberFactIntent above that gets fired when the user asks for a fact about a number.

The handler function for GetNumberFactIntent

As you can see on line 2 and 3 in the code for our GetNumberfactIntent handler above, we are passing the value of the number we received through our slot to the numberFacts object we looked at earlier to get our fact. Let’s now replace this line with our helper function, which will call numbersapi.com and get the fact about the number on the fly.

Step 1: Include the http module in our skill using the require statement.

Since numbersapi.com supports only HTTP calls, we are including only the HTTP library. Most APIs, however will support HTTPs, in which case you should include ‘HTTPS’ as well (require(‘https’).

Include the ‘http’ module

Step 2: Include this helper function in your skill code to make HTTP calls to REST APIs.

Let’s quickly run though what’s happening in this code: First, we prepare the options to send on to the HTTP call — we set up the host URI, the path, which is built using the number we receive from the user (query). So, if the user says “give me a fact about 21,” the number 21 is captured through our number slot (AMAZON.NUMBER slot type), and is passed on to the httpGet function wrapped inside the variable query. This code will make an HTTP GET request to the URI numbersapi.com/21. You can try this URL in your browser to see the result: http://numbersapi.com/42.

Then, we need to set up the HTTP request by calling the http.request method, and passing it the options we just set up. Since we are using Node.js, all of the functionality is handled asynchronously, which means we need to set up handlers within our httpGet function to accept incoming data, as well as to deal with the response once it’s complete. In this case, incoming data is simple. We just have to accept the data and concatenate it onto a string (responseString). Once the data return is complete, we call our callback function with this response.

Step 3: Finally, call the helper function from within your intent.

Call the httpGet helper function from the “GetNumberFactIntent” intent handler

We call our httpGet helper function from our intent handler (GetNumberFactIntent) by passing it the number we received from the user (query). Once, we receive the result, we use some console.log statements to log the response to CloudWatch, in case we need it to debug our code, and then finally we generate the speech response for the user through this.response.speak.

Pros and Cons of Using “HTTP” Module to Call an API from Your Alexa Skill

The main advantage of using the HTTP module is that there is no need to install external dependencies. It’s a built-in module part of the standard library, so you can just plug and play. If you are using AWS Lambda to host your skill code, this also means that you can make changes to your code by using the inline editor provided by the AWS Lambda console, without needing to upload the dependencies as a zip file to your Lambda function, which certainly comes pretty handy if you don’t like working with the command line.

While the HTTP module can do everything, the downside is that it can feel a bit clumsy to use. Much of the HTTP, and the HTTPS, module’s functionality is fairly low-level. You’re required to receive response data in chunks rather than just providing a callback function to be executed as soon as all of the data is received. You also need to parse the response data manually. This is fairly easy if the data returned by the API is in the JSON format, but it is still an extra step.

Recipe 2: Using the “Request” Module

The Request module is one of the most popular NPM module for making HTTP requests. It supports both HTTP and HTTPS and follows redirects by default. Behind the scenes, it actually uses the http module and adds a bit of magic to make it easier to use. A lot of common cases can be handled with just a tiny bit of code. The downside of using the “Request” module is that it’s not something that’s built-in to the standard library, and needs to be installed using npm, the default package manager for Node.js.

Having said that, as you expand the functionality of your skill, you will find yourself the need to use even more external modules, available through npm, like the `aws-sdk` module that makes it easy to work with the AWS services like Lambda, S3, Amazon DynamoDB, and more. This means that eventually you’d graduate to using this approach one way or the other. So, this isn’t really a disadvantage in the long run.

Let’s see how we can modify the code to use the “Request” module to call our API.

Step 1: Include the request module in our skill using the require statement.

Include the ‘request’ module

Step 2: Call the request.get() method from within your intent

Call the request.get() method from the intent handler (GetNumberFactIntent) to to send the number requested by the user (query) to the API, and respond back with the result.

As you can see, the “request” module makes it super simple for us to call our API. All we had to do was specify the URL for the API to be called, and the response is made available to us inside the object body, which we can then parse and use as part of our response.

The next step after this would be to zip up your index.js file along with other modules to create a deployment package and upload it to your Lambda function. To learn more about how to do that, read Prepare a Node.js Sample to Deploy in Lambda.

Choosing Your Recipe

You can obviously choose to use either of the recipes depending on your use case. A good rule of thumb to consider is that if your skill is using other external modules already, it may make sense to use the “requests” module and make your code simpler to read and easier to maintain. If, however, your skill is not using any other external modules and you don’t mind the extra bit of complexity in your code, you can stick with the “HTTP” module approach.

For more such recipes, see Alexa Recipes on Amazon Alexa Blog, or visit the Alexa Skill-Building Cookbook on GitHub.

More Resources

Build Engaging Skills, Earn Money with Alexa Developer Rewards

Every month, developers can earn money for eligible skills that drive some of the highest customer engagement. Developers can increase their level of skill engagement and potentially earn more by improving their skill, building more skills, and making their skills available in in the US, UK and Germany. Learn more about our rewards program and start building today. Download our guide or watch our on-demand webinar for tips to build engaging skills.

--

--

Amit Jotwani

Alexa Evangelist @Amazon. Hacker. Dreamer. Traveler. Minimalist. Opinions my own. Also, I am tall & slim.