Mura Demystified: The JSON API

There are three fundamental toolsets at the the heart of Mura CMS:

Mura ORM: This is the object-oriented, auto-wiring core of the CMS, the engine under the hood that gives developers direct access to the foundational heart of Mura

JSON API: The JSON API is a REST-friendly remote API that allows developers to connect to Mura via a standardized API. By-convention URLs can be used to return feeds, content, or interact with the core application

Mura JS: This is a Javascript-based engine similar in concept to jQuery, designed specifically for Mura CMS, that exposes a huge fraction of Mura's server-side functionality to Javascript developers

We have documented and blogged about Mura ORM for quite some time, but up until now haven't really discussed either the JSON API or Mura JS in very much depth. That, my friends, is about to change!

I'm going to write a series of blogs that take a look at the JSON API, Mura JS and how developers can use these to develop rich Javascript-based applications that live inside Mura display objects, within plugins or even remotely on external websites. The series will conclude with exciting new developments coming in future versions of Mura CMS ... but more on that later.

Step One: A look a the JSON API

I'm going to start this series with a top-down look at the JSON API. There's a lot to explore here, so I won't be going much farther than that. 

The JSON API is, as mentioned above, a REST-friendly way of interacting with Mura CMS. To start off, lets take a look at a very simple example:

http://www.getmura.com/index.cfm/_api/json/v1/getmura2/

This URL references the base endpoint of the JSON API. All calls to the api are standards-based, modeled upon REST:

This format will allow for future-safe development, where new versions and formats may be accessed by modifying the url calls.

If you clicked on the above link, you may have seen something like this:

{
    "data": {
        "entityname": "entityname",
        "links": {
            "self": "http://www.getmura.com/index.cfm/_api/json/v1/default"
        },
        "items": [{
                "entityname": "category",
                "links": {
                    "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/category",
                    "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/category/properties"
                }
            },
            {
                "entityname": "comment",
                "links": {
                    "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/comment",
                    "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/comment/properties"
                }
            },
            {
                "entityname": "content",
                "links": {
                    "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/content",
                    "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/content/properties"
                }
            },
            {
                "entityname": "contentCategoryAssign",
                "links": {
                    "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/contentCategoryAssign",
                    "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/contentCategoryAssign/properties"
                }
            },
            {
                "entityname": "site",
                "links": {
                    "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/site",
                    "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/site/properties"
                }
            }
        ]
    },
    "params": {
        "entityname": "entityname",
        "siteid": "default"
    },
    "method": "findAll",
    "apiversion": "v1"
}

Since I haven't passed the API any parameters, Mura has returned a base description of what is available to us. This self-describing nature is much appreciated, as it provides a lot of context and queues during development.

In the above example, there are several different data containers which are generally universal in any Mura JSON API call:

data: this object will contain any data returned by the request. Commonly it will contain the name of the entity being queried, any self-describing links that can provide more information, and a list of related items

params: these are the parameters taken from the url request

method: this is the method that Mura used to respond to the request

api version: the version of the API that is managing the request

In the above example you see a list of items that can likewise be interacted with. For instance if you look specifically at the "content" entity:

{
    "entityname": "content",
    "links": {
        "endpoint": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/content",
        "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/content/properties"
    }
}

... you can see there are two self-described options available, endpoint and properties. For something like content, which is the Mura ORM object related to content pages, the endpoint response will be similar to a feed with no filters applied:

{
    "data": {
        "endindex": 0,
        "startindex": 0,
        "entityname": "content",
        "totalpages": 0,
        "totalitems": 0,
        "links": {
            "entities": "http://www.getmura.com/index.cfm/_api/json/v1/default",
            "self": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/?&entityname=content&siteid=default&method=findall&pageIndex=0",
            "properties": "http://www.getmura.com/index.cfm/_api/json/v1/getmura2/content/properties"
        },
        "itemsperpage": 20,
        "items": [],
        "pageindex": 0
    },
    "params": {
        "entityname": "content",
        "siteid": "default"
    },
    "method": "findAll",
    "apiversion": "v1"
}

You might be now wondering, where is all the content then? Aha, well, I imagine you have been simultaneously wondering, "um, what about permissions/security?" Well, herein lies the answer to both questions! You don't see any content items (which would be, obviously, inside the items [] array) because you are not logged in. This point is very important: all requests to the JSON API are made within the permission architecture of Mura CMS. In other words, if you don't have permission to see or interact with a thing, you won't be able to see or interact with it.

Also, if you had been logged in (and, depending upon our permissions) the original endpoint API call performed at the top of the page would have also listed a great many other objects like user and group to interact with. 

Once logged in, you would see a list of items that look something like this:

{
    "items": [{
        "path": "00000000000000000000000000000000001,EF9F38D5-CE1F-3B40-C653CAF7BA388BAD,9B9D8F90-CB1B-8223-D573E063F87401E3",
        "menutitle": "An Example Page",
        "active": 1,
        "links": {
            "all": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content",
            "site": "http://getmura.com/index.cfm/_api/json/v1/getmura2/site",
            "properties": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/properties",
            "categoryassignments": "http://getmura.com/index.cfm/_api/json/v1/getmura2/contentCategoryAssign?contenthistid=9BA0CDD0-DBA7-0ECF-3438FC5B3EC94E83",
            "stats": "http://getmura.com/index.cfm/_api/json/v1/getmura2/stats/9B9D8F90-CB1B-8223-D573E063F87401E3",
            "relatedcontent": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/9B9D8F90-CB1B-8223-D573E063F87401E3/relatedcontent",
            "comments": "http://getmura.com/index.cfm/_api/json/v1/getmura2/comment?contentid=9B9D8F90-CB1B-8223-D573E063F87401E3",
            "self": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/9B9D8F90-CB1B-8223-D573E063F87401E3",
            "kids": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content?parentid=9B9D8F90-CB1B-8223-D573E063F87401E3",
            "rendered": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/_path/a-page/an-example-page",
            "parent": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/EF9F38D5-CE1F-3B40-C653CAF7BA388BAD",
            "crumbs": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/9B9D8F90-CB1B-8223-D573E063F87401E3/crumbs",
            "entities": "http://getmura.com/index.cfm/_api/json/v1/default",
            "history": "http://getmura.com/index.cfm/_api/json/v1/getmura2/content/9B9D8F90-CB1B-8223-D573E063F87401E3/history"
        },
        "url": "http://getmura.com/index.cfm/a-page/an-example-page/",
        "display": 1,
        "contenthistid": "9BA0CDD0-DBA7-0ECF-3438FC5B3EC94E83",
        "summary": "",
        "images": {},
        "assocurl": "http://getmura.com/index.cfm/a-page/an-example-page/",
        "id": "9B9D8F90-CB1B-8223-D573E063F87401E3",
        "type": "Page",
        "filename": "a-page/an-example-page",
        "displaystart": "",
        "contentid": "9B9D8F90-CB1B-8223-D573E063F87401E3",
        "subtype": "Default",
        "remoteurl": "",
        "changesetid": "",
        "moduleid": "00000000000000000000000000000000000",
        "siteid": "default",
        "remoteid": "",
        "parentid": "EF9F38D5-CE1F-3B40-C653CAF7BA388BAD",
        "displaystop": "",
        "title": "An Example Page",
        "approved": 1,
        "isnew": 0,
        "tags": "",
        "entityname": "contentnav"
    }]
}

(the above page doesn't actually exist on the Mura CMS site, BTW)

You can see that, once you dive down deep enough, you will find a treasure trove of self-described links that give us access to all sorts of information. You can see the content page's category assignments and comments, see a list of kids aka pages below this page, get a JSON-formatted version of the rendered page and a lot more.

Again, these requests follow a standard by-convention format:

This is probably a good place to stop for now, as it gives you a lot to explore. In the next blog, I'll take a look at how you can work more interactively with the JSON API via feeds, iterators, and using the by-convention CRUD (create, read, update, delete) functionality. Next I'll put this to work in a few practical examples, and then I will open the book wide on Mura JS. Hopefully you found this a helpful introduction into the Mura JSON API and its possibilities.