Web API Documentation


The API currently has a single entry point. All requests are done though the entry point and can vary by route or verb.

The entry point prefix is: “/api/v1/assets/”

The accepted verbs are:

• GET
• POST
• PATCH
• DELETE

Authorization

An access token is required to access the web API endpoints. Each request will require a bearer token using the “Authorization” header.

An access token can be requested as follows: 

POST /token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded

grant_type=password&username={username}&password={password}&client_id={clientID}&client_secret={clientSecret}

The response should provide a JSON object which contains the access token and some other information.

A refresh token (which is provided when an access token is requested) can be exchanged for an access token through the same endpoint. A request to exchange a refresh token for an access token is as follows:
POST /token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&client_id={clientID}&client_secret={clientSecret}

This request’s response is equivalent to the response received when an access token is requested using the “password” grant type.

GETs

Most GET requests (with the exception of “/search”) allow for filtering of assets using a combination of query string parameters. 
The allowed query string parameters are:

• filter – a filter query which determines which assets are returned
• page – the page number to retrieve, when using paging
• pageSize – the number of items to display per page, when using paging
• pageTimestamp – the freshness of pages, when using paging
• limit – the number of items to retrieve when not using paging
• sort – the properties to sort by
• select – the custom properties to select

Filter

The filter query parameter allows for complex logical queries. The conditions can have multiple nested ANDs and ORs. The filter parameter uses prefix notation style syntax. Therefore, each logical operator (AND/OR) must be followed by exactly two conditions. 

The conditions can be of two types:
1. Logical Condition (AND/OR)
2. Filter Condition (STR/DATE/NUM)

A filter condition allows a number of filter functions, depending on the type of filter condition (e.g. a string will not allow a greater than). 

The allowed functions are:

1. Eq – Equals (string, date, numeric)
2. EqCs  - Equals Case Sensitive (string, date, numeric)
3. NotEq – Not Equals (string, date, numeric)
4. Cont – Contains (string)
5. ContCs – Contains Case Sensitive (string)
6. Lt – Larger Than  (date, numeric)
7. Lte – Larger Than or Equal (date, numeric)
8. Gt – Greater Than (date, numeric)
9. Gte – Greater Than or Equal (date, numeric)
10. NotNull – Not Null (string, date, numeric)
11. NotCont – Does not Contain (string)

Please note that the filter condition itself is not case sensitive.

The filter functions accept a property and a value as parameters. Please note that a core property requires a “core.” prefix. 

An example simple condition is the following:

str.eq(myCustomStringProperty, myValue) 

In order to query an asset by its pointer ID, the following query would be used:

str.eq(core.pointerID, {pointerID})

Sometimes more complex queries are required and more than one property needs to be queried at once:

and str.eq(core.type, {type}) str.eq(core.subtype, {subtype}) – this query will return all assets of which type and subtype match

GET Aliases
There are a number of aliases which allow assets to be retrieved using a very simple URL format. 

The allowed aliases are:

• /api/v1/assets/{pointerID} == str.eq(core.pointerID, {pointerID})
• /api/v1/assets/type/{type}/{*subtype} == and str.eq(core.type, {type}) str.eq(core.subtype, {subtype})
• /api/v1/assets/name/{name} == str.eq(core.name, {name})
• /api/v1/assets/parent/{parentPointerID} == str.eq(core.parentPointerID, {parentPointerID})

A GET request can be issued as follows:

GET /api/v1/assets/type/user HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The response of a GET request will always be an array of assets (with the exception of get by pointer ID).

As described above, most requests will allow paging and other filter properties to be set. An example of a paged request is as follows:

GET /api/v1/assets/type/user?page=1&pageSize=5 HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The above request will retrieve the first page, which will contain 5 items. A paged request also allows for consistent paging. Consistent paging excludes any items added after a specific date. The parameter “PageTimestamp” can be added to the request for consistent paging. This date needs to be specified in RFC 1123 or ISO 8601 formats. 

A sample request with consistent paging:

GET /api/v1/assets/type/user?page=1&pageSize=5&pageTimestamp=2016-06-01T06:22:59.638Z HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

In order to make the response easier to parse (and minimize the size), the select parameter can be used. 
The following request only returns the “name” parameter in the string custom properties. However, multiple properties can be selected by comma separating the properties. The properties need to be prefixed with their type (i.e. “str”, “num” and “date”). 

GET /api/v1/assets/type/user?select=str.name HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

Please note that the select parameter can only be used for custom properties while all core properties will always be returned.

The results can also be sorted by specific properties using the “sort” parameter in the query string. The sorting properties can be comma separated and an attribute can be appended to each property (space separated) to indicate the sorting direction. The allowed attributes are “asc” and “desc”.  The following request sorts the results by the asset’s created date in descending order (last created first):

GET /api/v1/assets/type/user?sort=core.createdDate desc HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The main core properties have been given aliases, which makes the requests easier and more readable. The following aliases are allowed for core properties:

• ID
• Name
• Type
• Subtype
• CreatedDate
• ModifiedDate
• PointerID
• ParentPointerID
• BranchID

The sort properties need to be prefixed with their type (e.g. “str”, “date”, “num” and “core”). However, the properties will be defaulted to “core” and therefore the core prefix is not strictly required.  The following URLs are equivalent:

/api/v1/assets/type/user?sort=core.createdDate desc
/api/v1/assets/type/user?sort=createdDate desc

The sort direction is also defaulted to ascending and therefore the “asc” attribute can be omitted. 

When not using paging, the results can be limited by using the “limit” parameter. This is equivalent to the pageSize parameter however it is semantically more accurate when paging is not used. 

A request using the limit parameter to retrieve the first item only:

GET /api/v1/assets/type/user?limit=1 HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The parameters can be combined together as required to create more specific queries. For example, the latest asset (last created asset), can be retrieved by combining the created date and the limit parameters. 

GET /api/v1/assets/type/user?limit=1&sort=createdDate desc HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The above request retrieves the last created asset of type user. Please note that this is using an alias which allows the retrieval of an asset type without writing the full query. The following request URLs are equivalent:

/api/v1/assets/type/user?limit=1&sort=createdDate desc
/api/v1/assets?filter=str.eq(core.type, user)&limit=1&sort=createdDate desc

GET by Pointer ID

Although most aliases are only used for readability, a request for a specific asset by its pointer ID allows for a few extra headers to make the requests / responses more useful. 

A request for an asset by its pointer ID:

GET /api/v1/assets/{pointerID} HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

Therefore in the next request for the same asset, the “If-None-Match” header can be used, specifying the e-tag value. The response will be the asset JSON if the asset has been modified, however, if the asset has not been modified since, the response will be a 304 – Not Modified status and therefore the client can safely use the asset and assume it is the latest version. 

The following request returns a 304 – Not Modified:

GET /api/v1/assets/{pointerID} HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}
If-None-Match: {e-tag}

The “get by pointer ID” endpoint accepts an “If-Modified-Since” header. This header can be used in combination with the “If-None-Match” (see e-tags) header. When an “*” is specified in the “If-None-Match” header, the “If-Modified-Since” header is checked. This header accepts an RFC 1123 date and will retrieve the cached version if the asset hasn’t been modified since a specific date. 

A request using the If-Modified-Since header:

GET /api/v1/assets/{pointerID} HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}
If-None-Match: *
If-Modified-Since: {date} (e.g. Mon, 20 Jun 2016 10:28:33 GMT)

Search Query

The REST API also allows for a free text search. This request defers from other GETs in that it only accepts a single parameter (query). 

GET /api/v1/assets/search?query={querytext} HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

GET Responses (includes search endpoint response)

All GET requests return a JSON representation of an array of assets. This is with the exception of the “GetByPointerID” endpoint which returns a single asset object in JSON rather than an array. Each asset will contain the default core properties, which are the following:

• name – the name of the asset 
• pointerID – the unique asset ID (this does not differ in asset versions)
• parentPointerID – the parent asset unique ID (this determines the position of the asset in the tree)
• Type – the type of asset (used to classify the asset)
• Subtype – the subtype of the asset (used to classify the asset)
• createdDate – the asset creation date
• modifiedDate – the last modified date 
• versionID – the ID representing the specific asset version retrieved (this is the ID used for concurrency checks in the “If-None-Match” header when a PATCH is applied to an asset)
• branchID – the ID representing the branch from which the asset was retrieved

Each asset also has three “dictionary” properties which contain the custom properties, grouped by their type. The dictionary types are the following:

• strings – the custom string properties as key value pairs
• Numerics – the custom numeric properties as key value pairs
• Dates – the custom date properties as key value pairs

Sample asset results query server response:

sample-assets.jpg

used for caching and for concurrency checks when updating an asset. 

E-Tag →W/"574ed4303c1e2a8680c48afb"

The e-tag can be used in the next request (of the same type) to make sure the client has the latest version of the asset. The E-Tag can be added to a request as an “If-None-Match” header, the server will compare the value of this header to the e-tag produced by the response and determine whether the client requires a new response. If the response is determined to be identical, a 304-Not Modified status is returned. When requesting a single asset through the “GetByPointerID” asset, the version ID is used as the e-tag, therefore if assets are requested in a multi-asset request (e.g. get by type), the version ID of the asset can be used in the “If-None-Match” header for a get by pointer ID request or “If-Match” for a concurrency check in a PATCH request.

if non match.png

POSTs

The API also allows POST requests. The API makes use of the POST verb to add a new asset or to publish a draft version of an asset. 

In order to add a new asset, the root API URL is used, along with the POST verb and the asset object as JSON in the body. An example request to add a new asset:

POST /api/v1/assets{*publish=true} HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer {accessToken}

{ name: “{asset name}”, type: “{asset type}”, subtype: “{asset subtype}” } 

The minimum fields required are the name, type and subtype. However, any other properties which can be set are allowed. A Boolean parameter can be passed in the URL, indicating whether to create a published or a draft asset. The default value for this Boolean flag is true.

The response of an add request is a JSON object representing the newly added asset. This contains the automatically set properties, such as the pointer ID, the version ID etc. If the asset was added successfully, a 201 – Created status is returned. 

Publishing a Draft

When an asset is in draft state, the API allows for publishing of the asset by calling the “publish-version” endpoint. This request differs from most of the API’s request as it uses the version ID, rather than the pointer ID to reference the asset. This is necessary since multiple draft versions can exist at any point, and the API must determine which draft version of the asset to publish. 

POST /api/v1/assets/publish-version/{versionID}/{*forcePublish=true} HTTP/1.1
Accept: application/json
Authorization: Bearer {accessToken}

The above request, publishes a draft version of an asset. The optional “forcePublish” Boolean, which can be added as the final parameter in the URL, determines whether an asset version should be re-published if it is already the published version. The default value for this Boolean is true. 

If the request is successful, a 204 – No Content is returned.  

Archiving an Asset

An asset can be archived, which stops it from being accessible through a GET request. In order to archive an asset, the following request can be used:

POST /api/v1/assets/archive/{pointerID} HTTP/1.1
Authorization: Bearer {accessToken}

PATCH

In order to update an asset, the PATCH verb is allowed. This allows for properties to be added, removed, replaced, moved or copied. The request needs to be specified in the RFC 6902 format, however the “test” operation is not implemented. 

This format has four main components:

• Op – operation to perform
• Path – the path related to the operation
• Value – required for certain types of operations (add, replace)
• From Path – required for certain types of operations (copy, move)

A sample request to add a new string property to an asset:

PATCH /api/v1/assets/{pointerID}/{*publish=true} HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer {accessToken}

[{ op: “add”,  path: “/strings/{propertyName}”,  value: “{value}” }]

Please note that the request allows for an array of operations. The operations are performed in the sequence defined in the array. 

The PATCH also allows header values to be defined to mitigate concurrency issues. The “If-Match” header can be used (by specifying the e-tag value of an asset). This makes sure that the update operation is only performed if the asset version ID on which the update is performed is the asset version the client is expecting to update. 

A request using the “If-Match” header:

PATCH /api/v1/assets/{pointerID}/{*publish=true} HTTP/1.1
If-Match: {etag}
Content-Type: application/json
Authorization: Bearer {accessToken}

[{ op: “add”, path: “/strings/{propertyName}”, value: “{value}” }]

In order to target the core properties, a “/” is used in the “path” property. However, please note that the core properties do not allow all operations to be performed, this is because some properties cannot be modified or moved. 

Allowed operations on core properties:
• replace
• copy

Allowed core properties on which replace is allowed:
• name
• type
• subtype
• parentPointerID

When a PATCH request is successful, the request returns a 204 – No Content status. An E-Tag header is also returned which allows for the specific version to be published later (if the false Boolean flag was part of the request). If the “If-Match” header doesn’t match the current published version ID, a 409 – Conflict status is returned and an error message defined in the body text.

Please note that a PUT request is not allowed. All updates should be achieved using the PATCH verb as described above.

DELETEs

The API contains one endpoint which allows for the soft delete of an asset. The default behaviour of the delete is to recycle the asset. This is a framework 8 feature which allows the asset to be restored from the recycle bin.

In order to recycle an asset, the following request can be used:

DELETE /api/v1/assets/{pointerID} HTTP/1.1
Authorization: Bearer {accessToken}

The DELETE request will return a 204 – No Content status if it was successful. If the asset was already deleted, a 404 – Not Found might be returned as the API will fail to retrieve the asset