Design an Interface Asset Descriptor for a REST-based Web Service

Table of Contents


    NOTE: With IntuiFace API Explorer available since IntuiFace version 6, there is no need to hand-craft your own interface asset for a REST-based Web Service. This article presents the manual creation process, a process that should typically be unnecessary.

    Introduction

    Before proceeding, be sure to review Interface Asset general concepts and our introduction to creating your own interface asset. Treat these articles as prerequisites to the content below.

    An Interface Asset using the REST protocol only needs a descriptor file with a .ifd extension to be used in IntuiFace. No dll or other files are required. Here we explain step by step how to describe a REST-based API.

    Once you have created this .ifd (IntuiFace Descriptor) file:

    • create a folder with your Web Service name and copy the .ifd inside it
    • copy this folder to C:/Users/{UserName}/Documents/IntuiFace/Interface Assets/ and then restart Composer. By doing so your Interface Asset will become available in the Select an interface panel (see image below) across all of your projects.

    IA-Panel.jpg

    If your new interface does not appear in Composer, check Composer's log file:

    • C:\ProgramData\IntuiLab\IntuiFace5\Composer\Logs\Trace.log for IntuiFace version 5

    • C:\ProgramData\IntuiLab\IntuiFace\Composer\Logs\Trace.log for IntuiFace version 6 and above.

    This file contains useful information that may help you troubleshoot the formatting of your ifd file.

    In this article, we will use the Rotten Tomatoes REST API, a freely accessible provider of movie information.
    You can download the descriptor we are using as a sample for this article.

    Useful tools

    IntuiFace's interface descriptor files use the JSON (JavaScript Object Notation) data interchange format. Here are links to some excellent tools that will help to ensure the consistency of your JSON-based descriptor files:

    • to edit your .ifd (JSON) file
    • to generate JSON schemas: http://jsonschema.net/
      • NOTE: Be sure to deselect "Force required" in the General parameters section. It adds an unnecessary field to your schema.

    • to check if your .ifd file is valid: http://jsonlint.com/
    • to monitor the data going in & out of your computer: Fiddler
    • if your API doesn't provide dynamic documentation like RottenTomatoes, we recommend you use the Postman HTTP client to test your services

    NOTE: Never edit your .ifd files while Composer is running. If you wish to make changes to a .ifd file, exit out of Composer first.

    Process for creating an IntuiFace Descriptor File for your REST Web Service

    Here is the overall process we recommend when you want to create your own Interface Descriptor for a REST Web Service:

    1. In your prefered editor, prepare a skeleton of the descriptor containing the sections described below (General Properties, Schemas, Resources & Methods). For a quick start, copy-and-paste an existing descriptor, delete the unwanted content and replace the mandatory properties.
    2. Using your Web Service API documentation & JSON Schema, generate the schemas of the response objects you will have to manipulate.
    3. Update the Resources & Methods section in your editor. Don't forget to add the "isInterfaceAsset" = true property in the proper place (explained later in this article)
    4. Validate your descriptor using JSONLint
    5. Copy your descriptor file to C:/Users/{UserName}/Documents/IntuiFace/Interface Assets/{YourServiceName}/ to test it

    rest-skeleton.jpg

    General properties of the descriptor

    First, we need to specify the overall properties of the API, including its name, description, used protocol and base URLs for REST requests.

    {
       "kind" : "discovery#restDescription",
        "discoveryVersion" : "v1",
        "id" : "rottentomatoes:v1",
        "name" : "rottentomatoes",
        "version" : "v1",
        "title" : "Rotten Tomatoes movies API",
        "description" : "This API enables access to Rotten Tomatoes' wealth of movie information, allowing anyone to build applications and widgets enriched with Rotten Tomatoes data.",
        "documentationLink" : "http://developer.rottentomatoes.com/docs",
        "protocol" : "rest",
        "baseUrl" : "http://api.rottentomatoes.com/api/public/v1.0/",
        "basePath" : "/api/public/v1.0/",
        "rootUrl" : "http://api.rottentomatoes.com/",
        "servicePath" : "api/public/v1.0/",
        "requestDelay" : 250,
    
    Protocol: this property defines the type of response awaited from the Web Service. It can be
    • rest or rest_json: if the Web Service answers with JSON content
    • rest_xml: if the Web Service answers with XML content.

    We have added a requestDelay property to avoid sending too many requests to the Web service. You can change or remove this value depending on the limitations of your API.

    In many cases, APIs have common parameters used across all requests, like an API key to identify the user of the service. This type of parameter is added to the parameters section of the descriptor:

    "parameters" :
    {
        "apiKey" :
        {
            "type" : "string",
            "title" : "API key",
            "description" : "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required!",
            "location" : "query",
            "required" : true,
            "hidden" : true,
            "default" : "Insert a default API key value here"
        }
    }
    
    The apiKey parameter is required for every request, so "required" is set to true. In IntuiFace, a request can be sent only if all of its required parameters have a value.

    The "hidden" property prevents the display of a parameter and its value in Composer's Properties panel.

    Notes

    • If your Web Service requires “alt=json” as a parameter, add it to the global parameters of the descriptor. It will be applied to all of the methods you are going to define below.
    • By default, the body of a Web Service request will be compressed. If your service provider doesn’t support body compression, add "If.zipCompression" = false in the general properties of your interface asset. (e.g.: Philips Hue)

    Defining Schemas

    We can now describe data types. Types are listed in the schemas section of the ifd file. First, let's examine the JSON body structure returned by the Rotten Tomatoes service named BoxOffice:

    {
                "id": "123",
                "title": "Movie Title",
                "year": 2013,
                "mpaa_rating": "mpaa rating",
                "runtime": 123,
                "critics_consensus": "critics summary",
                "release_dates": {
                    "theater": "2013-05-16"
                },
                "ratings": {
                    "critics_rating": "Certified Fresh",
                    "critics_score": 86,
                    "audience_rating": "Upright",
                    "audience_score": 89
                },
                "synopsis": "Synopsis of the movie",
                "posters": {
                    "thumbnail": "URL of picture for mobile",
                    "profile": "URL of profile picture",
                    "detailed": "URL of detailed image",
                    "original": "URL of original high-res image"
                },
                "abridged_cast": [
                    {
                        "name": "Actor name",
                        "id": "123",
                        "characters": [
                            "Character name"
                        ]
                    }
                ],
                "alternate_ids": {
                    "imdb": "1408101"
                },
                "links": {
                    "self": "link to Rotten Tomato wweb page",
                    "alternate": "link for mobile",
                    "cast": "link to cast web page",
                    "clips": "link to clip web page",
                    "reviews": "link to review web page",
                    "similar": "link to similar movies web page"
                }
            }
    
    We have to create a schema associated with this structure, identifying all of the properties we want to be accessible in Composer. For each property, you need to indicate its type, title, description (and other properties if needed). See below for how a Movie is described in the ifd file:
    "Movie" : {
        "type" : "object",
        "id" : "Movie",
        "properties" : {
            "id" : {
                "type" : "string",
                "title" : "Id",
                "description": "Identifier of the movie."
            },
            "posters" : {
                "type" : "object",
                "title" : "Posters"
                "description" : "Poster of the movie in different resolutions."
                "properties" : {
                    "thumbnail" : {
                        "type" : "string",
                        "title": "Thumbnail",
                        "description" : "URL of low-res image for mobile."
                    },
                    "detailed" : {
                        "type" : "string",
                        "title": "Detailed",
                        "description": "URL of detailed image."
                    }
                }
            },
    "synopsis" : { "type" : "string", "title": "Synopsis" }, "title" : { "type" : "string", "title": "Title" } } }

    Don't worry, you don't have to write this on your own. You can use JSON Schema to help you. Copy your JSON body into the right panel and click Generate Schema. In the Review tab you will find the result to copy into your .ifd file.


    REST-jsonschema.jpg

    Services may return a list of Movie instances. In this case, you must add to the schema an array that handles a list of movies:

    "Movies" : {
        "type" : "object",
        "id" : "Movies",
        "properties" : {
            "movies" : {
                "type" : "array",
                "title": "Movies",
                "description": "List of movies."
                "items" : {
                    "$ref" : "Movie"
                }
            }
        }
    }
    

    All supported types and formats are listed in the Google Discovery documentation

    Important hints

    • Be careful: when asking a Web Service to return a list of objects, you may have two different kinds of answers
      • if the result starts with a {, you have an object which will probably have a property of type array (like in our example above, the response is an object with a movies array property)
      • if the result starts with a [, you have the array itself as a response. In our previous sample, we would have written it like this:
    "Movies" : {
        "type" : "array",
        "title": "Movies",
        "description": "List of movies."
        "items" : {
            "$ref" : "Movie"
        }
    }
    

    Warning: JSON Schema may confuse an array with a big object containing a lot of properties

    • Appropriate values for $ref vs. type
      • $ref references an object schema, define in the same descriptor in the schemas section
      • type denotes a basic type (number, string, bool, etc...) including any and null

    Defining Resources & Methods

    We have just described the data structure. Now we have to describe the services (aka. methods). This is done in the resources section of the file. We will use two services from the Rotten Tomatoes API : Box Office and Movies Info.

    More info about Resources & Schemas on Google Discovery documentation

    Box Office is an http GET method with two parameters: country and limit.
    The main parameter apiKey will automatically be applied as described above in the parameters section of the descriptor.
    Here is what the request would look like if called in a Web browser: http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=******************

    "resources" : {
            "movies" : {
                "methods" : {
                    "GetBoxOffice" : {
                        "id" : "rottentomatoes.lists.movies.box_office",
                        "isInterfaceAsset":"true",
                        "path" : "lists/movies/box_office.json",
                        "httpMethod" : "GET",
                        "description" : "Displays top box office earning movies, sorted by most recent weekend gross ticket sales.",
                        "parameters" : {
                            "limit" : {
                                "type" : "string",
                                "description" : "Limits the number of movies returned.",
                                "location" : "query",
                                "title": "Limit",
                                "default" : "16"
                            },
                            "country" : {
                                "type" : "string",
                                "description" : "Provides localized data for the selected country (ISO 3166-1 alpha-2) if available. Otherwise, returns US data.",
                                "required" : true,
                                "title": "Country",
                                "location" : "query"
                            }
                        },
                        "parameterOrder" : ["country"],
                        "response" : {
                            "$ref" : "Movies"
                        }
                    }
                }
            }
        }
    

    The path of the method is very important. It is combined with the baseUrl property (see the beginning of the descriptor file as described above) to form the final URL of the request.

    The isInterfaceAsset property value for this method is set to true. This means it will be available in IntuiFace Composer in the Interface Assets panel. The API can now be used as an Asset. Its parameters will be displayed as asset properties and when the value of those properties change, the REST service is called.

    Basic rule for the isInterfaceAsset property

    • for a GET, set "isInterfaceAsset" = true as a property of the method
    • for a PUT/POST, set "isInterfaceAsset" = true for the resource. See this article for more details.
    "GetMovieInfo" : {
        "id" : "rottentomatoes.movies.id",
        "isInterfaceAsset":"true",
        "path" : "movies/{id}.json",
        "httpMethod" : "GET",
        "description" : "Detailed information on a specific movie specified by Id.",
        "parameters" : {
            "id" : {
                "type" : "string",
                "description" : "The movie Id",
                "location" : "path",
                "default" : "770672122",
                "title": "Movie id",
                "required" : true
            }                  
        },                 
        "response" : {
            "$ref" : "Movie"
        }
    }
    

    This second example has a parameter named id which is part of the URL of the request (and not an argument of the query). Thus the path parameter includes the variable id - movies/{id}.json - and the location for the id parameter is set to "path" instead of "query".

    If you want more information about resources/methods, here is the Google documentation

    We have now generated an Interface Asset that can be added to any IntuiFace Experience. Remember, copy your new ifd file to C:/Users/{UserName}/Documents/IntuiFace/Interface Assets/{YourServiceName}.

    Adding headers to your HTTP request.

    You can add headers to an HTTP request by specifying "location": "header" for any parameter to add in the request header.

    "parameters": {
       "Content-Type": {
          type": "string",
          "title": "Content-Type",
          "location": "header",
          "default": "application/json",
          "readonly": false,
          "hidden": false
       }
    }
    

    Sample descriptors

    The following are references to REST-based Interface Assets created by IntuiLab and used either in Composer or in some of our samples. Don't hesitate to use them as a starting point to create your own!

    If you have some cool REST Web Services to share, please start a discussion to submit them!