Basic Jahia REST API

Quick introduction

Jahia provides a REST API, mostly for rendering, but some other services are available as well such: login, logout, content creation & updating and searching.

Examples

You can find an example of some REST API calls in the file modules/test/rest/jqueryfind.html. To test this file, make sure you start & configure your Jahia, and then point your browser to the following URL :

http://localhost:8080/modules/test/rest/jqueryfind.html

Login

URL : /cms/login

Method : POST

Parameters :

Name Mandatory Description
username yes The username of the user that you want to login
password yes The user's password
redirectActive no If set to "true" or not set, the login servlet
will redirect to the home page after successful
authentication. If you are using AJAX calls
you should set this to "false".
doLogin yes Should always be set to "true" otherwise login
will not work
redirect no Allows you to specify another URL to redirect
after successful login

Logout

URL : /cms/logout

Method : POST

Name Mandatory Description
redirectActive no If set to "true" or not set, the login servlet
will redirect to the home page after successful
authentication. If you are using AJAX calls
you should set this to "false".
redirect no Allows you to specify another URL to redirect
after successful login

TBD

Render

The render servlet can either be used to render content by accessing it with a GET method, or can also be used to add content to different workspaces by using a POST method and special parameters. You can also delete content using DELETE method, or update content using POST or PUT.

HTTP Get Request

HTTP Post Request

URL : /cms/render/WORKSPACE/LANGUAGE/CONTENT_PATH

Method : POST

Request headers : see response format section below.

Name Mandatory Description
jcrNodeType yes Define the type of node you want to create.
jcrNodeName no If defined we will create a node with this name (or use it as a
prefix for the name. If not define you can call :
/cms/render/WORKSPACE/LANGUAGE/CONTENT_PATH/*
To create a subnode at the specified path using the nodetype for
name.
jcrNewNodeOutputFormat no Define at which format the newly created node will be returned, HTML
by default, JSON is another possible value, or any type of output
you have define in your templates.
jcrRedirectTo no If defined will redirect to the specified URL instead of the newly
created node.
jcrMethodToCall no For HTML form to override the method called, this allow to delete
content with a simple POST form instead of send a DELETE HTTP request
jcrAutoCheckin no Allow to force versioning of the newly created content.
jcrTargetDirectory no If you have multipart form, this will be the
location where the content is uploaded
jcrVersion no If "true" activate the versionning on the posted content
(works only for files)
jcr:mixinTypes no Allow you to set a mixin on the new node

AJAX requests

All AJAX JSON requests should have the following headers set :

accept: application/json x-requested-with : XMLHttpRequest

The second header should be set for you when accessing the API through a browser, but if you are using the REST API through an HttpClient call or even another external client software (such as a mobile device for example), be sure that both these headers are set, otherwise it will default to HTML feedback.

File uploads

In the case of a file upload, when using AJAX requests (by setting the headers as described in the previous section), you actually have to perform two requests. The first request will be a multipart form upload and will save either in the current users' "files" directory, or if the "targetDirectory" property was set it will store the uploaded files there. The response is a JSON object with a "uuids" array property that contains string of the identifiers of all the created file nodes in the repository.

The second request can then use the UUIDs returned by the first AJAX request to set references to the new file nodes.

If a file already exists at the upload target, it will be updated, and if versioning is activated (see the version parameter above), it will create a new version before updating the file.

Response format

In the case of a regular POST method, the default response format is HTML. This format may be changed to JSON by setting up the appropriate request headers (see below).

In the case of HTML we will render the newly created or updated node with its default template (unless you have specified a different template using the newNodeOutputFormat parameter).

In order to change the response format to JSON, you must set the following headers : "accept" = "application/json" and "x-requested-with" = "XMLHttpRequest".

Example

Post Example
<form action="<c:url value='${url.base}${currentNode.path}/*'/>" method="post">
    <input type="hidden" name="jcrNodeType" value="jnt:post"/>
    <input type="hidden" name="jcrRedirectTo" value="<c:url value='${url.base}${renderContext.mainResource.node.path}'/>"/>
    <%-- Define the output format for the newly created node by default html or by jcrRedirectTo--%>
    <input type="hidden" name="jcrNewNodeOutputFormat" value="html"/>
    <fieldset>
        <p class="field">
            <input value="<c:if test="${not empty currentNode.children}"> Re:</c:if>${currentNode.propertiesAsString['threadSubject']}" type="text" size="35" id="forum_site" name="jcr:title"
                tabindex="1"/>
        </p>

        <p class="field">
            <textarea rows="7" cols="35" id="jahia-forum-thread-${currentNode.UUID}" name="content" tabindex="2"></textarea>
        </p>

        <p class="forum_button">
            <input type="reset" value="Reset" class="button" tabindex="3"/>

            <input type="submit" value="Submit" class="button" tabindex="4"/>
        </p>
    </fieldset>
</form>

This will create a new comments in a thread of a forum. And after submission we want to redisplay the curren thread, this is why we used the jcrRedirectTo parameter.

Delete Example
    <form action="<c:url value='${url.base}${currentNode.path}'/>" method="post"
          id="jahia-forum-post-delete-${currentNode.UUID}">
        <input type="hidden" name="jcrRedirectTo" value="<c:url value='${url.base}${renderContext.mainResource.node.path}'/>"/>
            <%-- Define the output format for the newly created node by default html or by jcrRedirectTo--%>
        <input type="hidden" name="jcrNewNodeOutputFormat" value="html"/>
        <input type="hidden" name="jcrMethodToCall" value="delete"/>
    </form>

    <a title="<fmt:message key='delete.post'/>" href="#"
    onclick="document.getElementById('jahia-forum-post-delete-${currentNode.UUID}').submit();"><span><fmt:message key="delete.post"/></span>

This example shows how to write a simple form to delete a content with a simple link.

Find

The find servlet can be used to query content inside the Jahia JCR repository. It provides a lightweight but very powerful interface to retrieve content anywhere inside the content repository. Please note that if you need to search for users or groups, you should use the findPrincipal servlet instead, since it integrates with external principal repositories such as LDAP.

URL : /cms/find/WORKSPACE/LANGUAGE

Method : POST or GET

Parameters :

Name Mandatory Description
query yes The JCR query to execute. You can reference request parameters in your
query by using the following syntax : $paramName which will look for
a request parameter called "paramName"
language no The JCR language used in the query, for example "JCR-SQL2" or "xpath"
Defaults to "JCR-SQL2"
limit no The maximum number of results to return.
Defaults to 0 that does not limit the results.
offset no The 0-index based offset to start results with.
Defaults to 0.
depthLimit no The depth of the result tree. If not set it defaults to "1". If you
have deep content tree hierarchies you might want to limit result
depth to avoid performance issues.
escapeColon no If set to true, the ':' in the node property name will be replaced
'_'.
Defaults to false.
propertyMatchRexexp no The value you specify here will be used to match properties in the
result set, and will build a matchingProperties JSON list that will
let you known which properties have matched. This is especially useful
when using fulltext search, since the JCR doesn't indicate which
property has matched the criteria. The value you specify must comply
with the JDK Pattern Regexp syntax.
removeDuplicatePropValues no If activated, it will filter the matched properties (that were
matched using the propertyMatchRegexp above parameter) to make sure
only one node per property value is returned. This is useful when
building unique list of property values for auto-completion.
Defaults to false.

Example

HTTP GET Request (formatted for legibility) :
 http://localhost:8080/cms/find/default/en
 ?q=t
 &limit=10
 &query=%2Fjcr%3Aroot%2Fsites%2FmySite%2Ftags%2F%2Felement(*%2C+jnt%3Atag)%5Bjcr%3Acontains(.%2C'%7B%24q%7D*')%5D%2F%40j%3Anodename
 &language=xpath
 &escapeColon=false
 &propertyMatchRegexp=%7B%24q%7D.*
 &removeDuplicatePropValues=false

In the above example, the values are encoded so that makes a bit harder to read. Here are the unencoded values :

 query = /jcr:root/sites/mySite/tags//element(*, jnt:tag)[jcr:contains(.,'{$q}*')]/@j:nodename
 propertyMatchRegexp = {$q}.*

One important thing is to now the $q marker that will actually be replaced with the value of the "q" request parameter specified in the request. This makes it easy to integrate with JQuery plugins that might use specific named request parameters.

HTTP Response :
Content-Length:1721
Content-Type:application/json;charset=UTF-8
Date:Fri, 26 Feb 2010 13:31:38 GMT
Server:Apache-Coyote/1.1
[
        {
                "jcr:score": "1366",
                "node": {
                        "index": 1,
                        "jcr:createdBy": "root",
                        "jcr:baseVersion": "/repository/default/jcr:system/jcr:versionStorage/5b/92/d7/5b92d76a-ee40-4b17-87e6-911a38db2ddb/jcr:rootVersion",
                        "jcr:versionHistory": "/repository/default/jcr:system/jcr:versionStorage/5b/92/d7/5b92d76a-ee40-4b17-87e6-911a38db2ddb",
                        "depth": 4,
                        "jcr:lastModifiedBy": "root",
                        "primaryNodeType": "jnt:tag",
                        "j:nodename": "tag1",
                        "j:originWS": "default",
                        "jcr:isCheckedOut": "true",
                        "jcr:lastModified": "2010-02-26T12:14:14.502+01:00",
                        "matchingProperties": [
                                "j:nodename",
                                "jcr:isCheckedOut"
                        ],
                        "jcr:created": "2010-02-26T12:14:14.397+01:00",
                        "j:fullpath": "/sites/mySite/tags/tag1",
                        "jcr:uuid": "5b92d76a-ee40-4b17-87e6-911a38db2ddb",
                        "jcr:primaryType": "jnt:tag",
                        "identifier": "5b92d76a-ee40-4b17-87e6-911a38db2ddb",
                        "path": "/sites/mySite/tags/tag1"
                },
                "j:nodename": "tag1",
                "jcr:path": "/sites/mySite/tags/tag1"
        },
        {
                "jcr:score": "1366",
                "node": {
                        "index": 1,
                        "jcr:createdBy": "root",
                        "jcr:baseVersion": "/repository/default/jcr:system/jcr:versionStorage/ab/63/bb/ab63bb78-8708-48aa-a040-82eee22ae5d7/jcr:rootVersion",
                        "jcr:versionHistory": "/repository/default/jcr:system/jcr:versionStorage/ab/63/bb/ab63bb78-8708-48aa-a040-82eee22ae5d7",
                        "depth": 4,
                        "jcr:lastModifiedBy": "root",
                        "primaryNodeType": "jnt:tag",
                        "j:nodename": "tag2",
                        "j:originWS": "default",
                        "jcr:isCheckedOut": "true",
                        "jcr:lastModified": "2010-02-26T12:14:18.570+01:00",
                        "matchingProperties": [
                                "j:nodename",
                                "jcr:isCheckedOut"
                        ],
                        "jcr:created": "2010-02-26T12:14:18.477+01:00",
                        "j:fullpath": "/sites/mySite/tags/tag2",
                        "jcr:uuid": "ab63bb78-8708-48aa-a040-82eee22ae5d7",
                        "jcr:primaryType": "jnt:tag",
                        "identifier": "ab63bb78-8708-48aa-a040-82eee22ae5d7",
                        "path": "/sites/mySite/tags/tag2"
                },
                "j:nodename": "tag2",
                "jcr:path": "/sites/mySite/tags/tag2"
        }
]

In the above JSON response, it is important to node the following properties :

  • jcr:score indicates the score of the result
  • node contains all the node information, including the matchProperties array that indicates which properties have matched the propertyMatchingRegexp parameter.

Find users or groups

This servlet is dedicated to searching for users or groups, with the particularity of being able to search in external principal repositories connected with Jahia, such as an LDAP repository. Note that the query and result formats are quite different to the default find servlet, because they are not representing JCR nodes but principal data structures.

URL : /cms/findPrincipal

Method : POST or GET

Parameters :

Name Mandatory Description
principalType yes The type of principal you wish to query for. The accepted values are
"users" or "groups"
a request parameter called "paramName"
siteKey yes (if
searching for
groups
If you have set the principalType parameter to "groups", you will be
required to specify a value for the siteKey parameter, which is the
site in which you want to search for the groups.
wildcardTerm no If this parameter is specified, it will be used to search for the
value specified in any principal property. If you prefer to search
for specific properties, you must specify them separately in the HTTP
request parameters. You can use the $paramName syntax to reference
other request parameters. For example $q will be replaced by the
value of a parameter called "q" if it is found. If it is not found the
marker will not be replaced.
propertyMatchRexexp no The value you specify here will be used to match properties in the
result set, and will build a matchingProperties JSON list that will
let you known which properties have matched. This is especially useful
when using fulltext search, since the JCR doesn't indicate which
property has matched the criteria. The value you specify must comply
with the JDK Pattern Regexp syntax.
removeDuplicatePropValues no If activated, it will filter the matched properties (that were
matched using the propertyMatchRegexp above parameter) to make sure
only one node per property value is returned. This is useful when
building unique list of property values for auto-completion.
Defaults to false.
includeCriteriaNames no A comma seperated list of parameter names that should be used to
create the criterias for the search.
any other parameter name no If you specify another other parameter other than the above reserved
ones, the servlet will interpret them as property names that have to
to be search for the specified values.
You can use the $paramName syntax to reference
other request parameters. For example $q will be replaced by the
value of a parameter called "q" if it is found. If it is not found the
marker will not be replaced. By default the servlet will use all the
other found parameter names, which might not be what you expect. You
should use the includeCriteriaNames to specify which criteria should
be used

Example

HTTP GET Request (formatted for legibility)
http://localhost:8080/cms/findPrincipal?principalType=users&wildcardTerm=steve
HTTP Response
[
        {
                "userProperties": "{j:published=true, j:nodename=sjobs, j:originWS=default, jcr:createdBy= system , j:external=false, j:firstName=Steve, jcr:primaryType=jnt:user, j:lastPublished=2010-06-16T16:13:34.094+02:00, j:email=, j:password=943+/myvMchk4TM1T11nKHx2u7g=, j:lastName=Jobs, jcr:baseVersion=164174a4-1ba0-4e3b-8143-119c9546be6c, j:lastPublishedBy= system root, jcr:created=2010-06-16T16:13:33.698+02:00, jcr:versionHistory=d17e5352-4909-48ef-94ef-e5957f741512, jcr:uuid=662cdfed-e674-4dff-85ee-dadb19243f5e, j:fullpath=/users/sjobs, jcr:isCheckedOut=true, j:checkinDate=2010-06-16T16:13:34.094+02:00, jcr:lastModified=2010-06-16T16:14:01.670+02:00, jcr:lastModifiedBy= system , j:organization=}",
                "homepageID": -1,
                "username": "sjobs",
                "providerName": "jcr",
                "userKey": "{jcr}sjobs",
                "root": false,
                "external": false,
                "name": "sjobs",
                "class": "class org.jahia.services.usermanager.jcr.JCRUser",
                "properties": {
                        "j:firstName": "Steve",
                        "jcr:created": "2010-06-16T16:13:33.698+02:00",
                        "j:external": "false",
                        "j:originWS": "default",
                        "j:published": "true",
                        "jcr:lastModified": "2010-06-16T16:14:01.670+02:00",
                        "j:lastPublishedBy": " system root",
                        "j:checkinDate": "2010-06-16T16:13:34.094+02:00",
                        "jcr:createdBy": " system ",
                        "j:nodename": "sjobs",
                        "jcr:versionHistory": "d17e5352-4909-48ef-94ef-e5957f741512",
                        "jcr:lastModifiedBy": " system ",
                        "jcr:uuid": "662cdfed-e674-4dff-85ee-dadb19243f5e",
                        "preferredLanguage": "en", 
                        "jcr:baseVersion": "164174a4-1ba0-4e3b-8143-119c9546be6c",
                        "j:lastName": "Jobs",
                        "jcr:isCheckedOut": "true",
                        "j:password": "943+/myvMchk4TM1T11nKHx2u7g=",
                        "j:lastPublished": "2010-06-16T16:13:34.094+02:00",
                        "j:organization": "",
                        "jcr:primaryType": "jnt:user",
                        "j:fullpath": "/users/sjobs",
                        "j:email": ""
                },
                "identifier": "662cdfed-e674-4dff-85ee-dadb19243f5e",
                "passwordReadOnly": false
        }
]

Debugging

In order to help with the debugging with AJAX REST requests, you can use built-in inspection tools such as :

- Safari's 4.0 Web Inspector (especially the resources and script tabs)

- Firefox's Firebug plugin

- any other equivalents