Content Server REST API - Quick Start Guide

Options
SDay
SDay E
edited August 27, 2021 in Articles #1

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.).

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. Follow the steps in Extending csNode - Custom Actions in the CSNode Quick Start Guide.
  2. Orphan RESTAPI:Root:RESTAPIMap into your ospace and give it a name.
  3. Overwrite and run the SetMap function (see Appendix A).
  4. 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.

  1. Follow the steps in Extending csNode - Roles in the CSNode Quick Start Guide.
  2. Orphan RESTAPI:Root:RESTAPIMap into your ospace (if you haven't already done so) and give it a name.
  3. Overwrite and run the SetMap function (see Appendix A).
  4. 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

  • Karen Weir
    Options

    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

    1. Make a copy of the os file that will be modified.
    2. From the Module Explorer tab, double-click the desired “setup” script.
    3. Modify the script and save (memory only).
    4. Right-click on the same “setup” script in the Module Explorer tab and select Run Script.
    5. From the OScript Explorer tab, select the related os file.
    6. From the menu, select Source | Overwrite Object Source, click OK when prompted. Unfortunately, the process changes everything in the os file (including tabs).
    7. Make a copy of the new os file and merge with the old file using a diff tool.
    8. 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.