REST API

Available in 8.1.1 and later, Cascade CMS REST API is a lightweight API for interfacing with Cascade's Web Services.

What is REST?

Formally, REST describes a way for a client to interact with web resources from a server using a set of stateless operations accessed via URIs.

Though the Cascade CMS v1 REST APi does not exactly follow RESTful API conventions, it is similar enough to be called so. The supported methods are "GET" and "POST". The name of the operation should be included in the URL. The request and response are in JSON format that resembles format of SOAP objects from Cascade CMS's Web Services.

Future version of the API may adhere more closely to REST.

Symbols in this document

{identifier}

Either:

  • End of URL string for POST or GET requests: {type}/{id} - for example folder/2b2fd9bc7f0000010044b22e65131cd3
  • End of URL string for POST or GET requests: {type}/{siteName}/{path} - for example: page/www.example.com/news/2003/best-of-show
  • Identifier can also be provided in body in JSON format for POST requests only - for example:
'identifier': {
 'type': 'page',
 'path': {
   'siteId': '2b2fd9a67f0000010044b22e4f6b0859',
   'path': 'news/2003/about'
}
}

Notice that providing a site id for identifier is not possible in URL string.

 

{auth}

Either:

  • Request parameters “u” and “p” for username and password. For example:

u=john.smith&p=john123

  • Authentication can also be provided in body in JSON format for POST requests only - for example:
'authentication': {
 'username': 'john.smith',
 'password': 'john123'
}

 

{wsdl}

JSON structure defined in Cascade instance’s WSDL file, which can be viewed by appending “/ws/services/AssetOperationService?wsdl” to Cascade’s URL in the web browser. For example: http://localhost:8080/ws/services/AssetOperationService?wsdl.

To read the WSDL file for given parameter, first search for a <complexType> tag with given “name” parameter. For example, “moveParameters” definition in WSDL can be found by searching for <complexType name=”moveParameters”>. In that case, the result will be:

<sequence>
  <element maxOccurs="1" minOccurs="1" name="destinationContainerIdentifier" nillable="false" type="impl:identifier"/>
  <element maxOccurs="1" minOccurs="1" name="doWorkflow" nillable="false" type="xsd:boolean"/>
  <element maxOccurs="1" minOccurs="1" name="newName" nillable="false" type="xsd:string"/>
</sequence>

 

If type is of “impl:...”, it means that there is another <complextType> or <simpleType> tag with given name, for example <complexType name=”identifier”>. This has its own structure:

<sequence>
<!-- When editing and selected asset is recycled, it is recommended to preserve this relationship by providing selected asset's id
in case if the selected asset gets restored from the recycle bin.
One is REQUIRED -->
<element maxOccurs="1" minOccurs="0" name="id" type="xsd:string"/>
<!-- Path works only for non-recycled assets -->
<element maxOccurs="1" minOccurs="0" name="path" type="impl:path"/>
<element maxOccurs="1" minOccurs="1" name="type" type="impl:entityTypeString"/>
<!-- NOT REQUIRED: For reading purposes only. Ignored when editing, copying etc. -->
<element maxOccurs="1" minOccurs="0" name="recycled" type="xsd:boolean"/>
</sequence>

 

Value 0 in “minOccurs” means that the property is optional. As a result, an example JSON for moveParameters could look like this:

'moveParameters': {
 'destinationContainerIdentifier': {
   'id': '2b2fea0f7f0000010044b22e35685d26',
   'type': 'folder'
 },
 'doWorkflow': 'false',
 'newName': 'index2'
}

 

or like this:

'moveParameters': {
 'destinationContainerIdentifier': {
   'path': {
     'path': '/news',
     'siteName': 'www.example.com'
   },
   'type': 'folder'
 },
 'doWorkflow': 'false',
 'newName': 'index2'
}

 

Hint: The “asset” property is quite complex. An easy way to understand its structure is by simply performing a “read” operation on an existing asset in the system. If you would like to “create” an asset (a page for instance), it would be useful to “read” a similar asset first to see the proper structure of “asset” property. The same object can even be reused for “create” operation with just tweaked parameters. Similarly, the easiest way to edit an asset is by reading it first and reusing the read “asset” object. 

 

Operations

Read

/api/v1/read/{identifier}?{auth}

example:

http://localhost:8080/api/v1/read/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

Delete

/api/v1/delete/{identifier}?{auth}

example:

http://localhost:8080/api/v1/delete/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

Create

/api/v1/create?{auth}

  • Include “asset” in message body based on {wsdl}
http://localhost:8080/api/v1/create?u=hill&p=hill
{
 'asset': {
   'page': {
     'name': 'test',
     'parentFolderPath': '/',
     'siteName': 'www.example.com',
     'contentTypeId': 'b9bc37270a00016b00899e533ba18fe5',
     'xhtml': '<div>Content</div>',
     'metadata': {
       'title': 'Page title'
     }
   }
 }  
}

 

Edit

/api/v1/edit?{auth}

  • Include “asset” in message body based on {wsdl}

example:

http://localhost:8080/api/v1/edit?u=hill&p=hill 
{
 'asset': {
   'page': {
     'id': 'b9b0a96c0a00016b00899e5325baab29',
     'contentTypeId': 'b9bc37270a00016b00899e533ba18fe5',
     'xhtml': '<div>Content</div>',
     'metadata': {
       'title': 'Page title'
     }
   }
 }  
}

 

Move

/api/v1/move/{identifier}?{auth}

  • Include “moveParameters” in message body based on {wsdl}
  • Optionally include “workflowConfiguration” in message body based on {wsdl}

 

Publish

/api/v1/publish/{identifier}?{auth}

  • Optionally include “publishInformation” in message body based on {wsdl}. Its “identifier” property is not necessary if it was provided in URL.

example:

http://localhost:8080/api/v1/publish/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

Search

/api/v1/search?{auth}

  • Include “searchInformation” in message body based on {wsdl}

 

ReadAccessRights

/api/v1/readAccessRights/{identifier}?{auth}

example:

http://localhost:8080/api/v1/readAccessRights/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

EditAccessRights

/api/v1/editAccessRights/{identifier}?{auth}

  • Include “accessRightsInformation” in message body based on {wsdl}. Its “identifier” property is not necessary if it was provided in URL.

 

ReadWorkflowSettings

/api/v1/readWorkflowSettings/{identifier}?{auth}

example:

http://localhost:8080/api/v1/readWorkflowSettings/folder/www.example.com/news?u=hill&p=hill

 

EditWorkflowSettings

/api/v1/editWorkflowSettings/{identifier}?{auth}

  • Optionally include “workflowSettings” in message body based on {wsdl}. Its “identifier” property is not necessary if it was provided in URL. If “workflowSettings” is not provided, the folder will have all workflow definitions removed and workflow will not be required or inherited.
  • Optionally include “applyInheritWorkflowsToChildren” with “true” or “false” value (false by default)
  • Optionally include “applyRequireWorkflowToChildren” with “true” or “false” value (false by default)

example:

http://localhost:8080/api/v1/editWorkflowSettings/folder/www.example.com/news?u=hill&p=hill

 

ListSubscribers

/api/v1/listSubscribers/{identifier}?{auth}

example:

http://localhost:8080/api/v1/listSubscribers/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

ListMessages

/api/v1/listMessages?{auth}

example:

http://localhost:8080/api/v1/listMessages?u=hill&p=hill

 

MarkMessage

/api/v1/markMessage/{identifier}?{auth}

  • Include “markType” in message body with value “read” or “unread”

example:

http://localhost:8080/api/v1/markMessage/message/21903a3d7f000001554c369f276691eb?u=hill&p=hill
{
 'markType': 'read'
}

 

DeleteMessage

/api/v1/deleteMessage/{identifier}?{auth}

example:

http://localhost:8080/api/v1/deleteMessage/message/21903a3d7f000001554c369f276691eb?u=hill&p=hill

 

SendMessage (deprecated)

/api/v1/sendMessage?{auth}

  • Include “message” in message body based on {wsdl}

 

CheckOut

/api/v1/checkOut/{identifier}?{auth}

example:

http://localhost:8080/api/v1/checkOut/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

CheckIn

/api/v1/checkIn/{identifier}?{auth}

  • Optionally include string “comments” in message body

example:

http://localhost:8080/api/v1/checkIn/page/www.example.com/news/2003/best-of-show?u=hill&p=hill
{
 message: 'Checking in content'
}

 

Copy

/api/v1/copy/{identifier}?{auth}

  • Include “copyParameters” in message body based on {wsdl}
  • Optionally include “workflowConfiguration” in message body based on {wsdl}

 

SiteCopy

/api/v1/siteCopy?{auth}

  • Include string “originalSiteId” or “originalSiteName” in message body
  • Include string “newSiteName” in message Body

example:

http://localhost:8080/api/v1/siteCopy?u=hill&p=hill
{
 originalSiteName: 'www.example.com',
 newSiteName: 'new-site'
}

 

ListSites

/api/v1/listSites?{auth}

example:

http://localhost:8080/api/v1/listSites?u=hill&p=hill

 

ReadAudits

/api/v1/readAudits/{identifier}?{auth}

  • Optionally include “auditParameters” in message body based on {wsdl}. Its “identifier” property is not necessary if it was provided in URL.

example:

http://localhost:8080/api/v1/readAudits/user/hill?u=hill&p=hill

 

ReadWorkflowInformation

/api/v1/readWorkflowInformation/{identifier}?{auth}

example:

http://localhost:8080/api/v1/readWorkflowInformation/page/www.example.com/news/2003/best-of-show?u=hill&p=hill

 

PerformWorkflowTransition

/api/v1/performWorkflowTransition?{auth}

  • Include “workflowTransitionInformation” in message body based on {wsdl}

 

ReadPreferences

/api/v1/readPreferences?{auth}

example:

http://localhost:8080/api/v1/readPreferences?u=hill&p=hill

 

EditPreference

/api/v1/editPreference?{auth}

  • Include “preference” in message body based on {wsdl}

example:

http://localhost:8080/api/v1/editPreference?u=hill&p=hill
{
 'preference': {
   'name': 'system_pref_global_area_external_link_check_on_publish',
   'value': 'on'
 }
}

 

Differences between SOAP and REST API in Cascade CMS

The REST API's request and response structure is quite similar to the existing SOAP web services' request and response structure. The obvious difference is that SOAP web services use XML to communicate while REST uses JSON. However, there are few more subtle differences:
  • When using REST API there is no need for any additional library to handle requests. As long as the specific language can handle JSON and sending requests through the network, that language can use REST API. This opens doors for easy usage of REST API in Javascript and .NET (.NET has a SOAP library but it is hard to set up and it runs into problems), while in PHP there is no need to enable the PHP SOAP module.
  • To use web services through SOAP with SSL (URLs with "https://"), additional settings are required in Apache to allow Cascade to connect to itself through SSL so that it can load the WSDL file. No such settings are necessary when using REST API, which reduces the burden on the server administrators.
  • There are a few differences between the XML SOAP envelope vs JSON. For instance, null values are returned in XML with xsi:nil="true" attribute while in JSON the null values are simply not there. Another difference is that arrays are wrapped in elements in XML, which then can be interpreted differently by different language specific libraries, while in REST API, the JSON response has plain arrays with elements in them.
  • SOAP accepts authentication only in the request body. Using REST API it is allowed to pass authentication to the URL. This is secure for the network over SSL - the credentials will be encrypted so that nobody can intercept the network connection and get the credentials. However, there is a chance that the server itself has logging enabled that stores accessed URLs. At that time, the server administrator could access the logs and see the password. To be 100% sure that the credentials cannot be seen by anyone (even the server administrator), you can pass credentials in the POST request's body. Even the "read" operation is allowed to be executed using POST request.
  • An average REST API operation has been reported to take about 30% longer time to execute. This might improve in the future.

 

Language specific examples

Below you can find example usage of the API.

Javascript (with jQuery)

This changes title of a page “news/2003/best-of-show” in site “example.com” by performing a “read” operation first, changing title and then performing “edit” operation:

$.get("http://localhost:8080/api/v1/read/page/example.com/news/2003/best-of-show?u=hill&p=hill", function(data) {
 if (data.success) {
   data.asset.page.metadata.title = 'New title';
   $.post("http://localhost:8080/api/v1/edit?u=hill&p=hill", JSON.stringify({
     'asset': data.asset
   }), function(data) {
     if (data.success)
       console.log('Success');
     else
       console.log('Error occurred when issuing an edit: ' + data.message);
   }, 'json');
 } else {
   console.log('Error occurred when issuing a read: ' + data.message);
 }
}, 'json');

 

PHP

GET operations are very simple. For instance, this reads a role with id “1”:

$reply = json_decode(file_get_contents('http://localhost:8080/api/v1/read/role/1?u=admin&p=admin'));
print_r($reply);

 

POST operations are also simple with this utility function to be able to easily convert data between PHP array and JSON:

function apiOperation($url, $params)
{
   return json_decode(file_get_contents($url, false, stream_context_create(array('http' => array('method'  => 'POST','content' => json_encode($params))))));
}

 

Here is a PHP example similar to the Javascript example above:

$reply = json_decode(file_get_contents('http://localhost:8080/api/v1/read/page/example.com/news/2003/best-of-show?u=hill&p=hill'));

if ($reply->success)
{
   $reply->asset->page->metadata->title="A new title";
   $reply = apiOperation('http://localhost:8080/api/v1/edit?u=hill&p=hill', array ('asset' => $reply->asset));
   if ($reply->success)
       echo "Success.";
   else
       echo "Error occurred when issuing an edit: " . $reply->message;
}
else
   echo "Error occurred when issuing a read: " . $reply->message;