Content Server REST API - Quick Start Guide
originally posted May 2019 | 🕐️ 8 minute read
Introduction
This article will explain how to use and extend the REST API. It should be read in conjunction with the Content Server 16.2 API Reference.
The REST API (as its name may imply) is a web API implementation using the HTTP protocol and REST principles. While Content Server already has APIs accessible by the web (WebNode, WebServices), this one is lighter and easier to use.
The REST API layer is very thin, with csNode (a wrapper for LLNode) driving most of the requests. Therefore, almost no modification is needed at the REST API layer; unless it needs to do something that csNode does not provide. Since csNode is such a large component, please refer to the document entitled CSNODE Quick Start Guide.
This document assumes the reader has knowledge of the Builder (10.0.x) and/or the Content Server IDE (10.5.x) and basic knowledge of REST.
The REST API has a convenience method to create mappings. Currently, the Content Server IDE implementation is a multi-step process.
Overview
Below is a high-level diagram showing the workflow of the REST API. Aside from a handful of resources, the bulk of the REST API is a series of mappings. Each REST URL is linked to a particular function in a given resource. The main resource, CSNodes, is a lightweight resource that communicates with csNode. Any action in csNode can be executed from the REST API with no modification to the CSNodes resource (a mapping may be required to expose that functionality).
Using the REST API
The REST API can be consumed in a variety of ways, so the examples will be generic (you may need to do additional steps for a given client).
Using a REST client (browser add-on) will allow you interact with the API without having to write additional code (for testing purposes). You will need to define a few headers for this to work.
Form Header:
name: Content-Type value: application/x-www-form-urlencoded OR application/multpart/fom-data
PUSH or PUT tend to use the application/multipart/form-data content-type
Authentication Header (the value can be obtained from an Auth call):
name: OTCSTICKET value:
Each REST call is a URL, in the format:
http(s)://<machine name>/<CS service name>/<CS CGI>/api/v1/<resource name>
The examples in this document will be a relative path to the Content Server CGI. Values in angle brackets (<>) are placeholders and not literal values.
This document will only describe a handful of calls, for more information see the documentation in Swagger.
Troubleshooting
Make sure you use the correct HTTP verb for a given URL.
If the verb is PUT or POST, make sure the form header is active, otherwise the contents of the body will not be parsed properly. The request may return 200 but the state will remain unchanged.
Make sure the authentication header is active and contains a valid OTCSTICKET, otherwise you will get a 401 error. The auth call is the only exception.
To specify multiple values for the same parameter, repeat the parameter. For example:
api/v1/nodes/<id>/nodes?where_type=0&where_type=144
Please note that the parameters in the Body
portion of the call are not actually of the form parameter1=<value1>;parameter2=<value2>
etc. In practice they actually appear as parameter1=value1;parameter2=value2
.
Auth
This resource only has a single call, which allows a user to authenticate with Content Server.
Method: POST URL: api/v1/auth Body: username=<username>;password=<password>
A successful response should return a ticket, which can be used to populate the authentication header (without the quotation marks). You will not be able to access any other resources without a valid OTCSTICKET.
Nodes
The bulk of the REST API's are located in this resource which leverages csNode.
Get
This call will get metadata for the specified node ID.
Method: GET URL: api/v1/nodes/<id>
The return values may include:
- data: property values
- definitions: definitions for each property value
- definitions_order: suggested ordering for each property
- definitions_map: relationship between definitions
- definitions_base: names of common properties across subtypes
- type: the subtype of the given node ID
- type_name: the display name of the subtype
- type_info: characteristics of the subtype
- available_actions: supported actions for the subtype
- available_roles: supported roles for the subtype
- addable_types: supported child subtypes
In data, if a given property is an identifier and has been given a persona in csNode (node, member, user, group, storage_provider), extended information can be returned.
Method: GET URL: api/v1/nodes/<id>?expand=<persona>
Browse
This call will return information about the children for the specified node ID. This can be called without parameters, defaulting to page 1, limit 25 and sort asc_name.
Method: GET URL: api/v1/nodes/<id>/nodes
The return values may include:
- data: property values for each child
- definitions: definitions for each property value
- limit: maximum number of items to return [Integer]
- page: current page number [Integer]
- page_total: total number of pages
- total_count: total number of items
- range_min: offset (min)
- range_max: offset (max)
- sort: column name used in sort [String], in the format [asc][desc]_{column name}
- where_name: name filter [String]
- where_type: subtype filter [Integer]
- where_facet: facet filter [String], in the format {facet id}:{facet value}
To alter the browse results, change one or more of the following parameters: limit, page, sort, where_name, where_type, where_facet.
Method: GET URL: api/v1/nodes/<id>/nodes?page=<page number>&where_type=<subtype>
In data, if a given property is an identifier and has been given a persona in csNode (node, member, user, group, storage_provider), extended information can be returned.
Method: GET URL: api/v1/nodes/<id>/nodes?expand=<persona>
Troubleshooting
Currently, where_type and where_facet cannot be used together.
To specify “all containers” in the where_type filter, use -1.
Create
This call will create an item using the specified parameters.
Method: POST URL: api/v1/nodes Body: type=<subtype>;parent_id=<parent ID>; name=< name>
The method will return:
- id: the ID of the newly created item
Troubleshooting
When creating documents, if your REST client supports file uploads, make sure the name of the field is “file” (and not “fileUpload” or something else). If your REST client does not support file uploads, you will need to specify additional information in the body:
file=<full pathname>; file_content_type=<mime type>;file_filename=<filename>
Update
This call will update the properties for the specified node ID.
Method: PUT URL: api/v1/nodes/<id> Body: name=<name>;description=<description>
This method does not return anything.
Delete
This call will delete an item for the specified node ID.
Method: DELETE URL: api/v1/nodes/<id>
This method does not return anything.
Volumes
This resource can be used to access a root volume based on its subtype as opposed to is node ID (which can differ across Content Server instances). Some examples of a root volume include the Enterprise Workspace (141) and the current users Personal Workspace (142).
Get
This call will get metadata for the specified subtype.
Method: GET URL: api/v1/volumes/<subtype>
See the Nodes - Get section for the return values and additional information.
Browse
This call will return information about the children for the specified subtype.
Method: GET URL: api/v1/volumes/<id>/nodes
See the Nodes - Browse section for the return values and additional information.
Versions
This sub-resource can be used to work with document versions.
Get
This will get the metadata for all versions of a document.
Method: Get URL: api/v1/nodes/<id>/versions
It can also be used to return metadata for a specific version.
Method: Get URL: api/v1/nodes/<id>/versions/<version number>
The return values may include:
- data: property values
- definitions: definitions for each property value
Get Content
This will get the content for the specified version.
Method: GET URL: api/v1/nodes/<id>/versions/<version number>/content
It can also be used to get the content for the current version.
Method: GET URL: api/v1/nodes/<id>/content
Troubleshooting
If the filename is not resolved properly, you may need to specify it after content in the URL line.
api/v1/nodes/<id>/content/<filename>
Add Version
This will add a new version to the specified document.
Method: POST URL: api/v1/nodes/<id>/versions Body: name=<name>
Troubleshooting
If your REST client supports file uploads, make sure the name of the field is “file” (and not “fileUpload” or something else). If your REST client does not support file uploads, you will need to specify additional information in the body:
file=<full pathname>; file_content_type=<mime type>;file_filename=<filename>
Delete Version
This will delete a version for the specified node ID and version number.
Method: DELETE URL: api/v1/nodes/<id>/versions/<version number>
This method does not return anything.
Update Version
This method will update metadata for the specified nodeID and version number.
Method: PUT URL: api/v1/nodes/<id>/versions/<version number> Body: description=<description>
This method does not return anything.
Extending the REST API
This section assumes you already have an existing and working LLNode. This section will also divide the process of exposing an LLNode into smaller steps for better understanding easier debugging.
Common Properties
Every LLNode has a common set of properties (name, description, create date, etc.).
- Follow the steps in Extending csNode - Common Properties in the CSNode Quick Start Guide.
You should now be able to retrieve common metadata about your node from a REST client using the GET method:
/api/v1/nodes/<id>
Custom Properties
You can skip this section if your LLNode does not have subtype specific properties.
- Follow the steps in Extending csNode - Custom Properties in the CSNode Quick Start Guide.
You should now be able to retrieve common and custom properties from a REST client using the GET method:
api/v1/nodes/<id>
Common Actions
Your LLNode should be able to use several pre-defined actions, eliminating the need to write any code.
- Follow the steps in Extending csNode - Common Actions in the CSNode Quick Start Guide.
You should now be able to perform these actions against your node from a REST client. Consult the REST API documentation for the syntax of these actions.
Modifying Actions
You can skip this section if your LLNode does not have any custom properties.
- Follow the steps in Extending csNode - Modifying Actions in the CSNode Quick Start Guide.
You should now be able to perform these actions against your node from a REST client. Consult the REST API documentation for the syntax for these actions.
Custom Actions
You can skip this section if your LLNode does not have any custom functionality.
- Follow the steps in Extending csNode - Custom Actions in the CSNode Quick Start Guide.
- Orphan RESTAPI:Root:RESTAPIMap into your ospace and give it a name.
- Overwrite and run the SetMap function (see Appendix A).
- Build your ospace and restart Builder (may not be required in the Content Server IDE).
You should now be able to perform this action against your node via a REST client.
Troubleshooting
Check that the action has been registered properly:
RESTAPI:Subsystems:RestAPISubsystem:.fMappings
Set a breakpoint in the REST API to see what is being sent in as parameters:
RESTAPI:Root:RestAPI.Dispatch
Roles
You can skip this section if your LLNode does not have any shared functionality across multiple subtypes.
- Follow the steps in Extending csNode - Roles in the CSNode Quick Start Guide.
- Orphan RESTAPI:Root:RESTAPIMap into your ospace (if you haven't already done so) and give it a name.
- Overwrite and run the SetMap function (see Appendix A).
- Build your ospace and restart Builder (may not be required in the Content Server IDE).
You should now be able to perform these actions against your node via a REST client.
Troubleshooting
Check that the actions were registered properly:
RESTAPI:Subsystems:RestAPISubsystem:<temp>.fMappings
Set a breakpoint in the REST API to see what is being sent in as parameters:
RESTAPI:Root:RestAPI.Dispatch
Comments
-
Appendix A: Mappings
The bulk of the REST API is a series of mappings. Each mapping consists of a signature and related function. For example:
"GET | api/v1/nodes/{1}", "csnodes|ActionGetValuesAndDefinitions|id|{1}"
For more examples see:
RESTIMPL:RESTAPIMap:nodes.SetMap
Signature
Each signature is made up from an HTTP method and a URL separated by a pipe. The signature must be unique across the system, so care should be taken to avoid naming collisions.
Method
The HTTP method must be one of the following: GET, POST, PUT, DELETE.
- GET: use this when you want to retrieve data from the system
- POST: use this when you want to add data to the system (node, version, etc.) or when calling an action
- PUT: use this when you want to modify the metadata of an item
- DELETE: use this when you want to delete an item from the system
Having only 4 verbs to work with in a system as complex as Content Server seems unbalanced but there does not need to be a 1:1 relationship between a CS action and a REST URL. There are three ways to modify data via REST: state transfer, convenience and actions.
The underlying principle of REST is state transfer, so this is the preferred way to update data. For example, although Content Server has a rename action, renaming an item via REST is done by updating the name property of a node.
While most things can be updated using state, there may times when you may want to make things more convenient for the developer. For example, to reserve or unreserve a document, the developer would need to modify reserved, reserved_date and reserved_user_id.
The reserve action could be simplified as follows (assuming the current date and current user):
PUT | api/v1/nodes/{1}/reservation
The un-reserve action could be simplified as follows:
DELETE | api/v1/nodes/{1}/reservation
On rare occasions, those 4 verbs are just not enough, such as the copy action (this is where REST gets muddy). Actions can be specified in the URL using the following format:
POST | api/v1/nodes/{1}?action=<action>
This should only be used as a last resort.
NOTE: this has not been implemented and will be available in a future update.
URL
The signature must start with the word api, followed by the version and resource (separated by a slash). The resource may have an optional ID ({1}). Sub-resources are allowed after the resource but only if the resource has an ID. Likewise, sub-resources are allowed after a sub-resource but only if the preceding sub-resource has an ID. For example:
api/<version>/<resource> api/<version>/<resource>/{1} api/<version>/<resource>/{1}/<sub-resource> api/<version>/<resource>/{1}/<sub-resource>/{2} api/<version>/<resource>/{1}/<sub-resource>/{2}/<sub-resource> api/<version>/<resource>/{1}/<sub-resource>/{2}/<sub-resource>/{3} api/<version>/<resource>/{1}/<sub-resource>/{2}/<sub-resource>/{3}/<sub-resource>
Each ID placeholder must be sequential (starting with 1) and be wrapped in curly brackets.
Each resource will likely point to a real physical resource (although it doesn't have to). Each sub-resource is a sub-resource in name only.
The most common resource is csnodes (which is basically a pass-thru to csNode). If the function calls the csnodes resource, the URL should reference the nodes resource.
The names used for resources and sub-resources must be a noun (not a verb).
Function
Each function is made up of a resource and a function name followed by zero or more parameters (key/value pairs) all separated with pipes. For example:
<resource>|<function>|<param1>|<value1>|<param2>|<value2>
The resource must be a child of the following object:
RESTAPI:Root:RestAPI
The function has to exist within the specified resource.
The most common resource is csnodes, which has two main functions: ActionExecute (POST, PUT, DELETE) and ActionGetValuesAndDefinitions (GET). The later function is static and only has id as a parameter. The former is more dynamic but requires the id and action parameters.
If you created a custom action in csNode (eg. DoSomething), the mapped function would look like:
csnodes|ActionExecute|id|{1}|action|DoSomething
If you created an action (eg. DoSomething) that was attached to a role (eg. MyRole), the mapped function would look like:
csnodes|ActionExecute|id|{1}|action|MyRole-DoSomething ?
Appendix B: CS IDE “setup” Scripts
- Make a copy of the os file that will be modified.
- From the Module Explorer tab, double-click the desired “setup” script.
- Modify the script and save (memory only).
- Right-click on the same “setup” script in the Module Explorer tab and select Run Script.
- From the OScript Explorer tab, select the related os file.
- From the menu, select Source | Overwrite Object Source, click OK when prompted. Unfortunately, the process changes everything in the os file (including tabs).
- Make a copy of the new os file and merge with the old file using a diff tool.
- Copy the resolved code back into the Content Server IDE.
In some cases, it may be easier to edit some of these features by hand rather than running the “setup” scripts.
0
Categories
- All Categories
- 122 Developer Announcements
- 53 Articles
- 151 General Questions
- 147 Thrust Services
- 56 OpenText Hackathon
- 37 Developer Tools
- 20.6K Analytics
- 4.2K AppWorks
- 9K Extended ECM
- 918 Cloud Fax and Notifications
- 84 Digital Asset Management
- 9.4K Documentum
- 31 eDOCS
- 184 Exstream
- 39.8K TeamSite
- 1.7K Web Experience Management
- 7 XM Fax
- Follow Categories