Using APIs to Pull Dynamic Data
Application programming interfaces (APIs) allow developers to retrieve data from various services, based on some queries and parameters. The API providor decides what and how data can be accessed, and this information is usually made available in the form of documentation.
For our latest demo, we will be looking at the weather much closer to home and the basic workflow of working with APIs.
OpenWeatherMap provides a free API, capable of getting detailed weather information from over 200,000 cities. To use the service in our Incari demo, you will first need to create an account and generate an API Key. An API Key is a 32-character code, unique to your account, which will be used every time you make an API request.
As an example of how to use an API and how the data retrieved can be used in Incari, we have created a fully-functional weather application, which you can download from the Remote Projects section of Incari Hub. There, you will see a project called 'WeatherWidget', which you can download to your local machine by pressing the download icon.
If you open up the Project and look inside the Logic Editor, under the 'Root' Scene tab, you will see the top-level Logic for the demo. To get things working, you will first need to change a few variables, which can be seen in the Variables tab of the Logic Editor. The Variables are:
apiKey- The 32-character API key, unique to your OpenWeatherMap account.
locationsList- A list of four locations for which you want to retrieve the weather. To avoid ambiguity issues with location names, it is preferred to use both the city name and country. "San Francisco" could be 1 of 5 locations, but "San Francisco, US" yields only one result. To see the search results beforehand, you can check them here.
isMetric- Whether the temperature should be in metric (°C) or imperial (°F) units.
Once these Variables are changed you can press play to start the simulation. You should now be able to see current weather information for the locations listed in
Incari's HTTP GET Node is what makes this kind of functionality possible. It takes some information, based on the documentation of the API provider, constructs and calls an API request, and asynchronously returns the response as a string.
Remote IP- The first section of this request is
http://api.openweathermap.org, which is our endpoint. This is the value we put inside the
Remote IPAttribute. A couple of notes regarding this Attribute:
- 1.An IP address can also be used, instead of a URL.
- 2.The HTTP GET Node currently supports the HTTP protocol only. HTTPS is not supported.
Remote Port- For the
Remote PortAttribute, this should be set to 80, which is the standard port for HTTP usage.
Method- Because we want to get data, the
MethodAttribute should be set to "GET".
Path- This is the specific path defined by the API provider. Usually, this is the text after the main root URL but before the
?character. In the case above, the path is
Authentication- This is used if the API requires a username and password, however OpenWeatherMap doesn't require this, so we set it to "None".
A query is a selection of key-value pairs, which form the parameters of the API call. One of these pairs almost always relates to the API key. In the case of OpenWeatherMap, this parameter is called
appidand needs to be used whenever attempting to retrieve data.
In the example call above, you will see that part of the string says
q=London. By looking at the documentation, you will see that the parameter
qis the "City name, state code and country code divided by comma".
Also, for localization purposes, there is one more query which determines the temperature format. By default, the SI unit Kelvin is used when making API calls on OpenWeatherMap. To change this to degrees Celsius (°C) or degrees Fahrenheit (°F), the
unitsparameter should be set to "metric" or "imperial".
If we were to put this information directly into the Attributes of the Node, it would look something like the image here:
Although building the query directly in the Attribute Editor may work correctly, it is much better practice to break this up into Variables, so that all settings of our application can be changed in one place (the Variable tab of the Logic Editor) and can be dynamically adjusted on-the-fly. If you look at the initialization Logic above, we are using the variables
cityto build a Dictionary, which will form a query for each location in the
locationsListArray and put it into the
Each element of the
queryListArray is then used as a
Queryinput parameter for the
This parameter is passed into the
QueryInput Socket, overriding any information in the Node's
Request QueryAttribute. The
SetResponseFunction outputs a
Responseparameter that is used to set different
Because HTTP GET returns the JSON as one big String, we need to convert this into a format that we can use. The Dictionary data type is the perfect option for this, as it is made up of key-value pairs, which can be accessed by name in other parts of our Logic.
To convert the
Bodyoutput (the response) into a Dictionary, we can use the new JSON Parse Node to convert the String. Because JSON can also be parsed as an Array, we need to tell Incari that we are expecting a Dictionary, not an Array. We do this by using the Conversion Node to cast the Any-type output of the JSON Parse Node to a Dictionary.
Dictionaries are a common data structure, used in many programming languages. The term "dictionary" stems from the fact that, like a dictionary, you look up a string of characters (a word in the case of a physical dictionary) to get the information or definition associated with that particular string.
Dictionaries share some similarities with Arrays, namely that they are both collections of data. Where they differ, though, is that Dictionaries are unordered (can't be iterated over using loops) and their values can only be accessed via their key. Conversely, Arrays are ordered and the values are accessed by their index.
The reason why Dictionaries are advantageous when dealing with APIs is that once the JSON has been parsed we can access what we need by a key name that relates to the information we need. Dictionaries can even contain other Dictionaries.
For example, if you look at the image above, you will see that from the main
Responsevariable, we are getting another Dictionary called
main. From this, we are then able to get the temperature (
temp) as a Float. This structure (
temp) corresponds to the OpenWeatherMap documentation, which shows an example of the hierarchy of the API response.
For each location, after generating a
ResponseDictionary-type Variable with the
SetResponseFunction, this output is passed to the
SetWeatherScreenValuesFunction and fed into a number of custom Functions to get the relevant key-value pairs and process them.
This Function outputs a set of Strings and Int values which is then passed to the
Inside the Prefab Logic, every input parameter is passed on to a local Variable.
By putting input parameters into local Variables, it is possible to trigger a Logic Branch only in the case that a Variable is changed at runtime.
Although we have focused primarily on weather information in this example, there are thousands of different APIs which can be applied in infinite ways. The core functionality in Incari, however, will remain the same:
- 1.You use the HTTP Get Node to make an API call, parse the data into a Dictionary using the JSON Parse Node
- 2.You then use that data to change aspects of your application.