Create a card with an API proxy

Using external API's in your software can significantly enrich the user experience and reduce the development costs. Rather than building bespoke solutions it is often possible to use an available Software as a Service solution which solves the problem at a fraction of the cost and time.

Now Assistant is designed to be flexible by allowing Cards to integrate with any API through the use of a special middle layer that handles API requests. In addition, it only forwards data we specify to the Card template which gives us the ability to filter, modify or join data coming from API's before it reaches the Card. To demonstrate we'll create a card that displays the weather in Boston, MA by getting the weather data from OpenWeatherMap. Let's get started!

Prerequisites

Before we can start please ensure you have the latest stable version of Node.js installed.

Creating the card

Similarly to our previous guide on creating a new card, we start by navigating to Development → Manage Spaces → Global → Components and click on 'New Component' button on the top right corner.

In the Component creation window we'll select our template type to 'Card' and we'll choose the Basic Card with NodeJs API proxy template:

We select the card template to be Basic Card with NodeJs API proxy

We'll set the component name to be 'test-card' and roles to view this card to 'Authenticated', in order to display this card only for logged in users. Finally, we'll press 'create' to create our card:

Set the card title and authentication and save it

Managing the API

By default the template for Basic Card with NodeJs API proxy contains an additional folder called 'script' which contains a script.js file. This file is run whenever our Card is active e.g. whenever it is displayed on the screen. The default behavior of a new Card is set to send an API request and return your IP address to the Card template. We can test that it works by opening the Card component and editing the script.js file:

Edit the script.js file to test the API proxy works

Here, we'll click on the 'Test Request' button:

Test Request button

This will take us to the Workplace Manager REST Test Tool with pre-filled Card information for us to test:

REST Test Tool

The result of AJAX request should contain your IP address.

Modifying the script file

Now that we've tested that script.js works we can start editing our card. We'll need to edit the code inside script.js file to get the weather data and pass it into our Card's template. We can achieve that by either editing the file directly through Workplace Manager or with your favorite code editor. In this case we'll use Visual Studio Code.

Let's navigate to the Now Assistant's installation folder → SpacesLocal → Global → Components → test-card → script and open the script.js file. Here we'll have to change 3 things:

1. Change the API request Url

We'll start by changing the request Url string. At the moment it sends a request to get your IP address, however we wish to send a request to the weather API instead. We'll be using OpenWeatherMap API which has an extensive documentation. The API provides a range of options to get current weather data by specifying either a city name, ZIP code or latitude and longitude.

Assuming that we want to know the current weather in Boston, MA we'll be precise and use the latitude and longitude parameters of Boston which are 42.361145 and -71.057083. The Url string now looks like this:
https://api.openweathermap.org/data/2.5/weather?lat=42.361145&lon=-71.057083

Next, we'll add the API key we received when registering, which is a necessary to authenticate our API requests:
https://api.openweathermap.org/data/2.5/weather?lat=42.361145&lon=-71.057083&appid=<OUR API KEY>.

Finally, we would also like to our data to be formatted in imperial units. Luckily, the API allows us to specify the data format therefore we'll specify the units parameter to be imperial. The final url string looks like this:
https://api.openweathermap.org/data/2.5/weather?lat=42.361145&lon=-71.057083&appid=<OUR API KEY>&units=imperial

To make things simple we're using the got npm module to perform a HTTP GET request. We'll insert our Url into the got function:

const response = await got('https://api.openweathermap.org/data/2.5/weather?lat=42.361145&lon=-71.057083&appid=<OUR API KEY>&units=imperial', {
  json: true
});

2. Create an object to store API response

We'll create a new object which will have a neatly formatted city name and the temperature. The temperature will be set using the response we get from the OpenWeatherMap:

let weather = {
    city: 'Boston, MA',
    temperature: response.body.main.temp + ' °F'
}

3. Forward the data to the card template

Finally we'll insert our newly created object to the card template by setting the activity.Response.Data object:

// forward the response data to the card
    activity.Response.Data = weather;

The Final code looks like this:

const got = require('got');

module.exports = async function (activity) {

  try {

    const response = await got('https://api.openweathermap.org/data/2.5/weather?lat=42.361145&lon=-71.057083&appid=<OUR API KEY>&units=imperial', {
      json: true
    });

    let weather = {
      city: 'Boston, MA',
      temperature: response.body.main.temp + ' °F'
    }

    // forward the response data to the card
    activity.Response.Data = weather;

  } catch (error) {

    // return error response
    var m = error.message;    
    if (error.stack) m = m + ": " + error.stack;

    activity.Response.ErrorCode = (error.response && error.response.

statusCode) || 500;
    activity.Response.Data = { ErrorText: m };

  }

};

Using the API data in the card

Now that we have passed our API data to the Card template, let's modify the Card's template to display the city name and current temperature. We'll open the Card Designer, click on the body of the Card and navigate down to edit its template code:

Click on the card body and edit its template

The selected element 'content' is a Liquid View. API data can be passed to multiple different Liquid Views in case you want to render the data in different areas of the Card.

Since we want to display only the city name and temperature all we need to do is to change the template code to the following:

<div class="layout-horizontal p prsm">        
  <div class="font-body1 layout-self-center layout-flex">
    <p>City: {{city}}</p>
    <p>Temperature: {{temperature}}</p>
  </div>        
</div>

Here, we simply use the values city and temperature from the previously created weather object, which is now accessible to our template.

If we navigate to the 'Preview' tab we should see the following result:

Final result of the Card

Got an issue? Or want to submit feedback?
Submit your feedback

Our new Feedback and Issue Tracker is built on GitHub Issues. Just leave your comment below and you can track our team resolve it, or browse issues others have already submitted.

Read how to use the Feedback and Issue Tracker