Introduction

The Assets API allows you to interact with our system programmatically from your own application. Using the API you interact with Resources such as:

  • Record
  • Classification, RecordClassification
  • Field, FieldDefinition
  • File, FileVersion, FilePreview, AdditionalFile
  • Image, Watermark
  • Language
  • MaintenanceJob
  • etc.

The API follows some aspects of hypermedia-driven web APIs, like using linked/embedded resources in the returned resource representation. Each resource can be accessed directly through its URI but it can also be accessed as an embedded sub-resource in its parent resource, like collection resource for example.

To read a resource, a standard HTTP GET request is used. The request can include some optional parameters which allow you to control how much of the information should be included/excluded in the returned resource, depending on how much information is needed.

To update a resource, a standard HTTP PUT request is used. Here, you can also specify the amount of data to be changed in the resource by not specifying in your request those resource properties which you don't want to change. Only the values of resource properties, which are specified in your request, are changed/updated.

To create a new resource, a standard HTTP POST request is performed on the appropriate collection of such resources. For example, if you would like to create a new record, you would perform an HTTP POST request on a record collection. If you don't specify some of the optional resource properties in your request, the default values will be used.

To delete a resource, a standard HTTP DELETE request is used. Based on your access rights, you might be denied the request to delete a resource.

If you want to know more about how to find your way around the API, see Navigating the API

Getting started

REST API configuration

After deployment of the ADAM REST API, you should also configure the ADAM structures that are used by the REST API.

This configuration will, among other things, create a .rest_SettingsWhitelist system setting. If you want to work with ADAM settings via the REST API, this setting should be provisioned by an ADAM administrator, as described in the setting resource documentation. However, the whitelist does not affect users from the ADAM Administrator and Operator user groups: they have access to all their ADAM settings, irrespective of the whitelist.

To do the configuration:

  1. Authenticate, using the credentials of an ADAM administrator account on the ADAM registration that you want to initialize, and use the token to connect to the setup endpoint.
  2. Perform an HTTP POST request on the /setup endpoint. This POST request should have an empty body.

Note: If you have more than one ADAM registration, you have to repeat this request for each of the ADAM registrations.

POST /setup HTTP/1.1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
API-VERSION: 1

The command above will upgrade your REST API system structures to the up-to-date state. However, such upgrade depends on other components of the system and previous upgrades. You may face a situation when configuration call passes successfully, but there is still an issue e.g. when uploading files. If you see such issues, these are the possible actions to fix them:

  1. First, try rebuilding an Enterprise Search index and/or ensure synchronization is started. Consult ADAM Administrator Guide or Enterprise Search Administration on how to do this.
  2. If step 1 doesn't solve the issue, you can try to repair your REST API structures by performing a forced configuration call. It differes from regular configuration call by an added request body containing a forceRebuild flag. Of course, you should also add the content-type header.

Note: this form of configuration request is an emergency action that is not normally needed. All the missing items needed by REST API will be recreated. This means that as the result of this command you may get useless objects in your system if you previously renamed them manually.

POST /setup HTTP/1.1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
API-VERSION: 1
Content-Type: application/json
{ "forceRebuild": true }

Navigating the API

The ADAM REST API supports two different ways of consuming and navigating the API:

HAL/JSON hypermedia

Once a resource is retrieved, your client can bookmark the URI in its cache. The existing relation names will not change over time, but new relations can be introduced.

Links in the returned resource representation help you to navigate the API, just by following those links. Using this approach helps create API clients/servers that do not depend too much on each other and can be developed in an independent way, as long as both the client and the server have a common understanding of media types used in the communication. For example, you can start using the API by going to the root URI of the API and discover all the resources you can access. From that point on, you can follow links and explore the resources existing throughout the API. You can use the "select" keys, present in most of the resources, which provide you with information about which sub-resources can be embedded in that resource. This way you can retrieve the exact information needed in a single request, which helps you optimize the chattiness of the API for your specific use case.

Plain JSON consumption

Next to using the HAL/JSON hypermedia API, clients can also consume the API using plain JSON. This is a simpler but less robust approach, since it lacks discoverability and requires upfront knowledge of the URI's for all the endpoints that the client will need. For pure JSON clients, we provide an exhaustive list of the endpoints available in the API.

Current version

A required request header parameter, which specifies which version of the API the request will refer to:

API-Version: 1

There are some exceptions to this requirement, like the root resource and the "supported versions" resource. These resources are version-agnostic, meaning they will always display the same result, no matter which "API-Version" parameter has been specified (if any). Also, they will never change what exists, but can add new information to ensure backwards-compatibility. The reason for this exception is a requirement to provide consumers with a way to discover the list of existing and supported API versions before they start using it. If these resources were also version-aware, consumers wouldn't have a way to discover the proper values that can be specified in the "API-Version" parameter.

For the complete list of exceptions, refer to the Endpoint header requirements section.

Media types

The ADAM REST API supports the following media types:

  • Response media types:

    • application/hal+json (default)
    • application/json
  • Request media types:

    • application/json (default)

Tutorials & examples

Examples

The following examples show you how you can use the ADAM REST API to perform common tasks in ADAM.

Basic concepts

Selecting

The selecting feature is used in the ADAM REST API to support the dynamic nature of the ADAM resources and to provide the API consumers with a way to select a custom granularity level for the resource representation they want to retrieve from ADAM. It helps consumers retrieve more information using a single request.

By default, when a resource is requested, it is usually returned using a minimal representation, which contains as little data as possible (for example, all of the sub-resources of the requested resource are not returned in this minimal representation). If needed, a consumer can extend this resource representation by selecting more data to be included, using the "select" header parameter.

The general format of the select parameter is: "Select-{Resource}: SubResource1,SubResource2,SubResource3, ..." where the value is a comma-separated list of subresources to be included in the resulting resource representation. It specifies that the returned resource's representation also contain its subresources, beside the basic/minimal data, which is always returned. For example, to request a list of records, with their classifications and files included with each returned record resource, a consumer typically performs a request like this:

GET /records HTTP/1.1
accept: application/hal+json
select-record: classifications, files

It is also possible to further select the sub-resource's additional attributes in the same request. For example, if a consumer likes to select the children for each classification returned with each record, it is done in this way:

GET /records HTTP/1.1
accept: application/hal+json
select-record: classifications, files
select-classification: children

The returned records collection resource contains records, each of which has the embedded files collection resource and the classifications collection resource with each classification's children collection embedded in the classification resource. All of this has been accomplished in a single request.

There is a possible recursion issue in this particular case, since the "children" sub-resource is also a collection of classifications, each of which can have "children" as a sub-resource, too, which could lead to an unexpected data overflow. To avoid this, a limit was introduced to return only the first level of recursive sub-resources.

Sub-resources

In case sub-resources are returned as linked resources of another parent resource, all of those sub-resources will have an additional attribute named "select-key". This parameter indicates that the sub-resource can be selected (embedded) in the parent resource representation. The value of the "select-key" parameter can be used as a value of the "select-<parent-resource>" parameter. For example, to get a record:

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json

We can see there are numerous linked resources available for that record, which can be selected (embedded) in the returned record representation, using the specified "select-key" parameter:

{
	"_links": {
		"self": {
			"href": "/record/250d22a231ed4f0ba9afa49900b0252e"
		},
		"fields": {
			"href": "/record/250d22a231ed4f0ba9afa49900b0252e/fields",
                    "select-key": "fields"
		},
		"files": {
			"href": "/record/250d22a231ed4f0ba9afa49900b0252e/files",
                    "select-key": "files"
		},
		...
	},
	"id": "250d22a231ed4f0ba9afa49900b0252e",
	"createdOn": "2015-05-15T10:41:19.51Z",
	"modifiedOn": "2015-06-12T11:13:15.433Z",
	"tag": null
}

To request a record resource, with, for example, all the fields selected, look at the "fields" linked resource for the " select-key" parameter with the value " fields". This value means that you can include this sub-resource within the record resource just by specifying: " select-record: fields", when requesting the record next time, like this:

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json
select-record: fields

This time you will get the fields embedded within the record resource instead of just returning a linked resource. This way you can dynamically change the amount of information returned for the same resource requested.

For a more detailed example, see: Reading a record

Attributes

Next to the sub-resources, some resource attributes can also be selected (included or excluded from the requested resource representation). If not selected, these attributes will NOT be returned by default. This will be clearly indicated in the description of the property on the resource page.

The listed attributes were either rarely used or the calculation of their value was too expensive to be included in the default representation of a resource, consequently, it was decided to hide these attributes unless a consumer specifically selects them.

Explicit fields selection

When selecting the fields of a record, classification, user or file, it can be useful to select only certain fields, instead of having them all included in the returned resource. For example, to select fields of a record:

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json
select-record: fields

This selects all the fields on that record. To filter out specific fields (or field groups), you can use additional header parameters that provide such filtering, like " select-record-fields" and " select-record-fieldgroups". The value for these parameters is a comma-separated list of fields/fieldgroups. Fields and field groups can be specified using their Ids (in the form of a GUID) or their names. Since the field/fieldgroup names can contain random text, it is advised to properly encode them using the "Percent-Encoding" so that they can safely pass over the network to the API server. Also take into account that the "comma" character needs to be escaped because it has a special meaning in the HTTP header values. This is an example of the selected fields' filtering feature:

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json
select-record: fields
select-record-fields: 295B1779-A381-4018-BE1D-B29E3458B41C, MyField, DummyField
select-record-fieldgroups: TestFieldGroup, CDE8E0C4-CD7E-47BC-93D3-0F54C7109FB6, FooBarGroup

In the previous example there was no need to use the percent-encoding, but let's consider an example where escaping is required.The field " My,Field,With,Commas" contains a "comma" character in its name. To escape it properly, because in HTTP the header values represent the list of comma-separated values, and to avoid selecting fields with these names: My", " Field", " With" and " Commas", you need to percent-encode the field name so that the request reads as follows:

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json
select-record: fields
select-record-fields: My%2CField%2CWith%2CCommas

This request will result in one field only, named " My,Field,With,Commas".

References in field values

For single and multiline text fields where the AllowReferences in field definition set to true in the field definition, you can return the resolved value of the reference instead of the explicit field value. Specify the " select-field" header with the value " references":

GET /record/250d22a231ed4f0ba9afa49900b0252e HTTP/1.1
accept: application/hal+json
select-field: references

Advanced selecting and preventing recursion

The REST API will intelligently decide on whether or not to select a resource. Selecting is done based on the resource type. However, the number of times a resource is selected, is limited to prevent recursion. Without that limitation, querying for instance a user with "Select-User: CreatedBy" can lead to a recursive embedding loop where the selection is endlessy re-applied to the embedded resource.

To remedy this, the API will preform selections in such a way that any resource type cannot occur more than two times in the path leading from the topmost resource to the leaves. For instance:

GET /user/{id} HTTP/1.1
select-user: createdby

will return the user, and embed the createdby. The select-user: createdby will no longer be applied to the embedded createdby user, even though this too is a user resource. Similarly:

GET /classification/{id} HTTP/1.1
select-classification: parent, children

will return the specified classification, and embed its parents and children. However, the children of the parent and the parent of the children will not be embedded. This also applies to deeper levels of nesting:

GET /user/{id} HTTP/1.1
select-user: fields
select-field: definition
select-fielddefinition: createdby

will return the following 'tree' of embedded resources:

user
	.field
		.definition
			.createdby
	.field
		.definition
			.createdby

After the second occurrence of the createdby the embedding will stop, because the API will detect that createdby is of type user, which also appears higher up in the embedding tree.

Embedding/following relations that result in missing data

When a relation points to either of the following:

  • an image with HasImage=false
  • a null value, e.g. when a record’s MasterFile has no files
  • an obsolete value, e.g. CreatedBy/ModifiedBy that points to a user who was removed from the database

Then clicking that type of link will have the API by default return a 404 NotFound error containing a meaningful error message. Selecting that type of link will by default have the propertyname: null embedded in the output.

Filtering

A filter expression can be passed in the request with the filter parameter. It can be specified as a query string or a header parameter. The parameter is only taken into account on collections of resources.

A filter expression is a single-line ADAM search expression without parameters or any additional options. See simple search examples for more details.

Warning: Searching for records/classifications using a search expression is done in 2 steps: first ElasticSearch is queried to get a list of matching IDs, then those IDs are used to query the ADAM database.
If any of the search results is deleted between step 1 and 2, the TotalCount value will be out of sync with the real count of search results.

Sorting

A sort expression can be passed in the request with the sort parameter. It can be specified in the query string or as a header. The parameter is only taken into account on collections of resources. See simple search examples for more details.

Paging

Although there are pre-built pagination links via relations such as: " first", " prev", " next" and " last", you can also control the page number and the number of items per page if you provide the " page" and/or " pageSize" parameters. These parameters can be passed as a query string or header parameters. For performance reasons, the " pageSize" parameter has a limit of 1000. When omitted, it defaults to 50. See simple search examples for more details.

Relations

The following registered relations are used: " self", " first", " prev", " next" and " last" (as specified in the Web Linking RFC). Other custom relations are added per resource to allow intuitive navigation of the Rest API.

Note that not all entities, which are exposed as resources through the Rest API, are returned as relations if referenced by another entity. For small and static collections, such as languages, the client application should fetch and cache the list of resources at startup and then map the Ids to resources on the client-side. These resources are not returned as relations but as plain GUIDs.

Localization

Fields and labels can be requested in specific languages using the languages header parameter. This parameter can be a single language Id, a comma-separated list of language IDs or an asterisk ("*") that represents all languages. If omitted, this parameter will return the current user's default language.

Exception handling

When unexpected exceptions occur, the ADAM REST API will feed this back to the API consumer via an HTTP error response containing an exception object as body. The HTTP response code will correspond to the type of exception that occurred:

  • HTTP 4xx response codes indicate specific error conditions (validation errors, malformatted requests, access denied, resource not available...)
  • HTTP 500 internal server error is returned for all other exceptions

The error object returned can contain the following properties:

Property Description
exceptionMessage A description of what went wrong. Depending on the exception this can be a technical or a more user-friendly message.
exceptionType The full type name of the exception. This can be used in automatic error handling or to reinstantiate the exception on the client.
stackTrace Can contain the full stack trace of the exception for debugging purposes.
innerException Can contain the inner exception for debugging purposes.

The verbosity of this exception object is controlled by the <customErrors /> settings element. By default the full object is only returned for callers from the same host as where the server is located. At low verbosity, the stackTrace and innerException properties are omitted.

Downloading files

When downloading a file using a link returned by an Order or a URI property of an Image resource, the file name is not always known upfront. This can be the case, e.g. when a resize action is applied during the ordering of an object, because that action changes the file name.

Download URI will contain a security token set to expire

  • after 30 hours, if default File store is configured to use disk as a storage.
  • not sooner than the value of the setting .minimumAvailableTimeForPreviews (for /additionalfile, /image/preview and /image/thumbnail endpoints) or .minimumAvailableTimeForOrders (for download orders) (See the DAM Operations help for more information), if the default File store is configured to use Azure blob storage.

The download URI can return

  • file content
  • a redirect to the proper file location in case CDN is enabled. It then responds with the http status code "MovedPermanently" (301) or "Redirect" (302)".

It is possible to specify CDN location by setting the value of the optional Location-Alias header. Used values:

  • us1 - for South America, Antarctica, North America, Central America, Caribbean
  • eu2 - for Europe, Africa, Middle East
  • au1 - for Australia, Pacific, Asia (except China)
  • cn1 - for China

For reference, the Content-Disposition header is added to the response, and contains the file name, e.g. Content-Disposition: attachment; filename="fname.ext"

For more information, see: section 19.5.1 or RFC 2616.

Usage

Authentication

The ADAM REST API supports 2 modes of authentication: Bearer and Token-based authentication.

There are several endpoints in the ADAM REST API that do not require authentication. You can find them in the Endpoint Requirements section.

Bearer authentication

ADAM REST API supports the Bearer authentication scheme, used with OAuth 2.0. When using Bearer token authentication, the client making a call to an endpoint requiring authentication needs to add an  Authorization HTTP header providing Bearer token, obtained from Marketing Operations. Within the bearer authentication scheme, JWT security tokens are used to authenticate users.

To use the Bearer authentication, your REST client first needs to obtain a JWT (JSON Web Token) from the Marketing Operations REST API.

Here is an example of a valid JWT security token created by the Marketing Operations REST API: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVSUQiOiIxIiwiQ0lEIjoiMSIsIkRCIjoiMiIsIkRvbWFpbklkIjoiMSIsIkxJRCI6IjEiLCJUSUQiOiI0MyIsIkdNIjoiMjEwMywyMTA0LDIxMDUiLCJVc2VyUmlnaHRzIjoiNjk1LDY4NSw2NjUsMTAyLDEiLCJVVCI6IjEiLCJBVCI6IjAiLCJkYW0tdWlkIjoiZTc1ZGM5OGUtMzIyOS00NDAxLTk0YjctZDZhYzlkMzk0ODk2IiwiZGFtLWxvZ2luIjoiYWhlYXRoIiwiZGFtLXRlbmFudCI6ImxhYi0xMjMiLCJjbGllbnRfaWQiOiJhZGFtIiwiaXNzIjoic2VsZiIsImF1ZCI6Imh0dHBzOi8vbGFiMTIzLmFwcmltby5jb20vIiwiZXhwIjoxNTA4MjExMjI5LCJuYmYiOjE1MDgxNDY0Mjl9

Here is that same token base64-decoded:

{
      "typ": "JWT",
      "alg": "HS256"
}
.
{
      "UID": "1",
      "CID": "1",
      "DB": "2",
      "DomainId": "1",
      "LID": "1",
      "TID": "43",
      "GM": "2103,2104,2105",
      "UserRights": "695,685,665,102,1",
      "UT": "1",
      "AT": "0",
      "dam-uid": "e75dc98e-3229-4401-94b7-d6ac9d394896",
      "dam-login": "aheath",
      "dam-tenant": "lab-123",
      "client_id": "adam",
      "iss": "self",
      "aud": "https://lab123.aprimo.com/",
      "exp": 1508211229,
      "nbf": 1508146429
}
.
[signature]

Once a user is successfully authenticated to Marketing Operations, the obtained JWT token can then be used to access all of the authorized REST API resources.

GET /records  HTTP/1.1
Authorization: Bearer eyJ0e...(base64-encoded JWT security token)...jrzpAg
200 OK
<content>
Complete example

Below is a full example on how to authenticate with the ADAM REST API using a Marketing Operations token.

GET /records  HTTP/1.1
401 Unauthorized
WWW-Authenticate: Bearer, Token
POST [CustomerURL]/api/oauth/create-native-token HTTP/1.1
Client-id: adam
Content-type: application/json
Authorization: Basic Sm9obkRvZTpmb29iYXI=
200 OK
<tokens>
GET /records  HTTP/1.1
Authorization: Bearer eyJ0e...(base64-encoded JWT security token)...jrzpAg
200 OK
<content>

Token-based authentication

For token-based authentication, the client must have authenticated successfully with ADAM and therefore have an active ADAM session.

In token-based authentication, the token is a Base64-encoded ADAM session identifier, followed by a colon and a registration name (e.g. <session_id>:<registration_name>). The token will be valid as long as the ADAM session associated with it is valid (this validity is determined by the ADAM settings). If you already have an ADAM session identifier from a previous request or from a different application, you can use that to authenticate using token-based authentication.

To authenticate using a token, you have to add an  Authorization HTTP header containing word ' Token' followed by empty space and actual token:

GET /records HTTP/1.1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
200 OK
<content>

Endpoint header requirements

The following table gives an overview of which header fields are required for all endpoints:

Endpoint API-VERSION Accept Authorization User-Agent Registration
/ (root) Ignored Required Ignored Required Ignored
/supportedVersions Ignored Required Ignored Required Ignored
/download Ignored Ignored Ignored Required Ignored
/docs Ignored Ignored Ignored Ignored Ignored
/setup Ignored Ignored Required Ignored Ignored
all other endpoints Required Required Required Required Ignored

Editing resources

ADAM REST API, among other features, supports editing of resources. In order to create a new resource, you need to perform a POST request on a collection to which you want to add a new resource. Performing a PUT request updates an existing resource and issuing a DELETE request deletes an existing resource. You need to have appropriate privileges in order to perform these requests.

In most cases, you can reuse the response (in application/json format) of the read operation to provide that response as a request body for the edit requests.

Also, in most cases, setting a resource's property to null resets its value (like "tag" for example).

For changing the nested collections, you can use addOrUpdate and remove sections in the collections request, which contain id's of elements which have to be added/updated (removed) in (from) nested collections.

Each resource contains the "Examples" section on its documentation page, which provides more info on how to properly perform editing requests on that resource.

Uploading files

Note: Uploading files using the rest api endpoint is now deprecated and no longer part of this documentation.

Files should be uploaded through the upload service. The upload service is a dedicated service made for uploading files only. Each file that you upload through the upload service can be added to a record. Do note that each uploaded file should be used only once. After the uploaded file has been used by this API a cleanup service will remove the upload from the storage location. The upload service implements 2 approaches to upload files. One for the small files (smaller than 20 MB) and the other one for big files (larger than 20 MB).

Uploading files below 20 MB

Uploading a file through the Aprimo Upload Service is done in the following way:

POST https://upload.aprimo.com/uploads HTTP/1.1

".RoleExecuteMaintenanceJobs" and ".RoleViewMaintenanceJobs" privileges are required for users that want to process uploaded files through this API, due to the internal implementation.

Right now only multipart form-data content-type is supported. This means that you cannot simply POST binary stream to /uploads endpoint. Instead, you produce proper multipart form-data request. However, multipart form-data is the default format for modern HTTP clients, so crafting such a request should not be a problem. The multipart form-data request looks similar to this:

POST https://upload.aprimo.com/uploads HTTP/1.1
Content-Length: 244947
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Content-Type: multipart/form-data; boundary=----BoundaryzZaqkP0Sxn4p9XFF
Accept: */*
------BoundaryzZaqkP0Sxn4p9XFF
Content-Disposition: form-data; name="file1"; filename="Logo_flame.png"
Content-Type: image/png
[binary content]

Currently only one file per request is supported, even though the format allows the multi-upload.

When successful, either a HTTP 200 OK response is returned, or a HTTP 202 Accepted response. If the response is 200 OK, it contains a file upload token which can then be used in e.g. the edit record file request.

{
	"token":"NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ=" 
}

Uploading files above 20 MB - in segments

  1. Prepare file segments to upload.
  2. Set up the upload
  3. Upload each segment
  4. Commit the upload
  5. Cancel the upload
1. Prepare the file segments to upload

This is the responsibility of the consumer of the API. This depends on the technology in which the client program is written.

2. Set up the upload

This is meant to notify the server that an upload flow is initiated by the client.

POST https://upload.aprimo.com/uploads/segments HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Accept: */*
Content-Type: application/json
{
	"filename":"photo.png",
}

When successful, the response will have HTTP Response Code 200 OK and will contain a URI which can be used to upload the file segments in the next step.

{
	"uri":"/uploads/segments/NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ%3d"
}
3. Upload each segment

In this step, each segment of the file will be uploaded to the URI provided returned in the response in the previous step.

The name of the file provided in the upload form is not important.

The client needs to specify the index of the uploaded segment as a query string parameter.

The index of the segment is ZERO based

There should be one segment with index=0 and there should be no gaps between indexes.

POST https://upload.aprimo.com/uploads/segments/NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ%3d?index=0 HTTP/1.1
Content-Length: 24947
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Content-Type: multipart/form-data; boundary=----BoundaryzZaqkP0Sxn4p9XFF
Accept: */*
------BoundaryzZaqkP0Sxn4p9XFF
Content-Disposition: form-data; name="segment0"; filename="Logo_flame.png.segment0"
Content-Type: image/png
[binary content]

This step needs to be repeated for every segment of the file. It is possible to upload different file segments in parallel requests.

When successful, the response will have HTTP Response Code 202 Accepted.

4. Commit the upload

After all the segments have been uploaded, the upload flow can be committed.

The client needs to provide the total number of segments which have been uploaded and the name of the original file.

POST https://upload.aprimo.com/uploads/segments/NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ%3d/commit HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Accept: */*
Content-Type: application/json
{
	"filename":"photo.png",
	"segmentcount":"4"
}

In this step validation will occur which will make sure that all the file segments have been uploaded to the server.

In case all the file segments are present, the file will be re-assembled from fragments and will persist on the server.

When successful, a HTTP 200 OK response is returned. If the response is 200 OK, it contains a file upload token which can then be used in e.g. the edit record file request.

{
	"token":"NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ=" 
}
5. Cancel the upload

An upload flow can be cancelled at any moment after its setup was executed.

DELETE https://upload.aprimo.com/uploads/segments/NzVmMDY5YTA4MGU1NDBhMDkyY2FmYzQ3YzQwMzNjMmQ%3d HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Accept: */*

When successful, the response will have HTTP Response Code 204 No Content.

Clearing the uploads

If you upload files and don't use them, you can remove each one of the uploaded files using a DELETE request, e.g. during a clean-up:

DELETE /uploads/<uploadedFileToken>

Record inheritance

Record inheritance is a way to link records together, so that one record inherits fields over from another record. The inheriting record is called the child record, the record where data is inherited from is called the parent record.

When a record is linked to a parent record for inheritance, it will automatically inherit all inheritance-enabled fields and their values from that parent. Every time the field value in the parent record is updated, the values of inherited fields in all linked child records are automatically updated as well. Unless the field value was changed in the child record, overriding the inherited field value. Doing this will suspend inheritance: the field value will no longer be updated when it is changed in the parent record.

An overridden field could be reset again: this means reactivating the field inheritance and overwriting the local field value with the value from the parent record again.

Setting up inheritances

To set up inheritance for a certain field from one record to another is done in two separate areas:

  • - Inheritance has to be enabled on the field definition
  • - An inheritance link has to be set up between the parent and the child record

  • Enabling inheritance on a field definition

    Enabling inheritance is done in the field definition, either via ADAM System > Field definitions, by selecting the checkbox This field is inheritable, or by setting its isInheritable property to “true” via .NET API.

  • Setting up inheritance between a parent and a child record

    To link two records together to start inheritance, you set the parentId property on the child record to the Id of the record that will serve as parent.

    See Set/Update parent on child record

Get field definition inheritance status

The inheritance status of a field definition is stored in the isInheritable property:

GET /fielddefinition/{fielddefinition id}
API-version:1
accept:application/json
					
Output:
{
	"minimumLength": 0,
	"maximumLength": 3800,
	"regularExpression": "",
	"allowReferences": false,
	"label": "InheritedText",
	"dataType": "MultiLineText",
	"scope": "RecordContentClassDependent",
	"scopeCategory": "Record",
	"indexed": true,
	"languageMode": "Multiple",
	"memberships": [
		"40cd3ee808e54c528ec850a372e4de1c"
	],
	"searchIndexRebuildRequired": false,
	"enabledLanguages": [
		"c2bd4f9bbb954bcb80c31e924c9c26dc",
		"cc18138b0a0f41cf9b86a6f200a44766"
	],
	"id": "1f7b7b7a38a946218ba0a6f200a46337",
	"name": "InheritedText",
	"isRequired": false,
	"isReadOnly": false,
	"isUniqueIdentifier": false,
	"inlineStyle": "",
	"sortIndex": 16,
	"tag": null,
	"createdOn": "2017-01-05T09:58:12.83Z",
	"modifiedOn": "2017-01-05T09:58:31.007Z",
	"createdBy": null,
	"modifiedBy": null,
                        "isInheritable": true
}
					

There are a number of properties on records that are related to record inheritance:

Property Description
hasChildren (Boolean) Indicates if the record has inheriting child records.
parentId The Id of the linked parent record, if this record inherits over from another record.
ancestors A collection of all ancestors (parents and parents-of-parents) of this record, if any.
children A collection of all inheriting children of this record, if any.

The inheritance status of a field in a child record can be seen in the inheritanceState property of that field. This property tells you whether a field is inherited, overridden or none, which means that this is a non-inherited field.

See link on how to get the field inheritance status.

Set/Update parent on child record

Setting/updating the parent on a child record is done using the parentId property. In case you want to clear the parent of the record, assign null to a parentId property. After parent is removed, child record keeps Overridden field values.

An example:

PUT /record/{record id}
API-version:1
Content-Type:application/json
						
Body:
{
	"parentId": "{parent record id}",
}
						

Get field inheritance status

For each individual field of a (child) record you can see the inheritance status:

  • - None: this field is not inherited
  • - Inherited: the field value is inherited over from the parent record
  • - Overridden: the field is set for inheritance, but the value was changed on the child record, overriding the inherited value
GET /record/{record id}
API-version:1
accept:application/json
select-record:fields
					
Ouput:
{
	"id": "{record id}",
	"fields": {
		"items": [
		{
			"definition": null,
			"dataType": "SingleLineText",
			"fieldName": "DisplayTitle",
			"label": "DisplayTitle",
			"id": "1e73720b2b5844a49edca6f200a42ce9",
			"localizedValues": [
			{
				"value": "Child Record3",
				"languageId": "00000000000000000000000000000000",
				"readOnly": false,
				"modifiedOn": "2017-01-06T12:25:02.09Z"
			}
			],
                        "inheritanceState": "None"
		},
		{
			"definition": null,
			"dataType": "OptionList",
			"fieldName": "InheritedOptionList",
			"label": "InheritedOptionList",
			"id": "f890485d521c456ca3efa6f200a488ff",
			"localizedValues": [
			{
				"values": [
					"c876395be1b6416d9504a6f200a48902"
				],
				"languageId": "c2bd4f9bbb954bcb80c31e924c9c26dc",
				"readOnly": false,
				"modifiedOn": "2017-01-06T12:50:49.19Z"
			}
			],
                        "inheritanceState": "Inherited"
		},
		{
			"definition": null,
			"dataType": "MultiLineText",
			"fieldName": "InheritedText",
			"label": "InheritedText",
			"id": "1f7b7b7a38a946218ba0a6f200a46337",
			"localizedValues": [
			{
				"value": "NEW text in English qwe",
				"languageId": "c2bd4f9bbb954bcb80c31e924c9c26dc",
				"readOnly": false,
				"modifiedOn": "2017-01-06T12:50:45.233Z"
			}
			],
                        "inheritanceState": "Overridden"
		},
		]
	},
	"files": null,
	"preview": null,
	"thumbnail": null,
	"masterFile": null,
	"masterFileLatestVersion": null,
	"classifications": null,
	"contentType": "Record",
	"tag": null,
	"parentId": "{parent record id}",
	"parent": null,
	"ancestors": null,
	"hasChildren": null,
	"children": null,
	"modifiedOn": "2017-01-06T12:50:45.233Z",
	"modifiedBy": null,
	"createdOn": "2017-01-06T12:24:47.88Z",
	"createdBy": null
}
						

Reading a record with embedded HasChildren property

The HasChildren property simply indicates whether or not this record is a parent record in record inheritance.

GET /record/{record id}
API-version:1
accept:application/json
select-record:hasChildren
						
Output:
{
	"id": "{record id}",
	"fields": null,
	"files": null,
	"preview": null,
	"thumbnail": null,
	"masterFile": null,
	"masterFileLatestVersion": null,
	"classifications": null,
	"contentType": ""Record"",
	"tag"": null, 
	"parentId": null,
	"parent": null,
	"ancestors": null,
                        "hasChildren": true,
	"children": null,
	"modifiedOn": "2017-01-05T10:02:15.507Z",
	"modifiedBy": null,
	"createdOn": "2017-01-05T10:01:23.04Z",
	"createdBy": null
}
					

Reading a record with embedded Parent

Reading record with parent record information included.

GET /record/{record id}
API-version:1
accept:application/json
						
Output:
{
  "id": "{record id}",
  "fields": null,
  "files": null,
  "preview": null,
  "thumbnail": null,
  "masterFile": null,
  "masterFileLatestVersion": null,
  "classifications": null,
  "contentType": "Record",
  "tag": null,
  "parentId": "{parent record id}",
  "parent": {
    "id": "{parent record id}",
    "fields": null,
    "files": null,
    "preview": null,
    "thumbnail": null,
    "masterFile": null,
    "masterFileLatestVersion": null,
    "classifications": null,
    "contentType": "Record",
    "tag": null,
    "parentId": null,
    "parent": null,
    "ancestors": null,
    "hasChildren": null,
    "children": null,
    "modifiedOn": "2017-01-05T10:02:15.507Z",
    "modifiedBy": null,
    "createdOn": "2017-01-05T10:01:23.04Z",
    "createdBy": null
  },
  "ancestors": null,
  "hasChildren": null,
  "children": null,
  "modifiedOn": "2017-01-06T09:43:54.407Z",
  "modifiedBy": null,
  "createdOn": "2017-01-05T10:02:26.073Z",
  "createdBy": null
}
					

Reading a record with embedded Children

The Children property returns a collection of all inheriting child records of this parent record, if any.

GET /record/{record id}
API-version:1
accept:application/json
select-record:Children
					
Output:
{
	"id": "{record id}",
	"fields": null,
	"files": null,
	"preview": null,
	"thumbnail": null,
	"masterFile": null,
	"masterFileLatestVersion": null,
	"classifications": null,
	"contentType": "Record",
	"tag": null,
	"parentId": null,
	"parent": null,
	"ancestors": null,
	"hasChildren": null,
	"children": {
		"items": [
		{
			"id": "{child record id}",
			"fields": null,
			"files": null,
			"preview": null,
			"thumbnail": null,
			"masterFile": null,
			"masterFileLatestVersion": null,
			"classifications": null,
			"contentType": "Record",
			"tag": null,
			"parentId": "{record id}",
			"parent": null,
			"ancestors": null,
			"hasChildren": null,
			"children": null,
			"modifiedOn": "2017-01-06T09:43:54.407Z",
			"modifiedBy": null,
			"createdOn": "2017-01-05T10:02:26.073Z",
			"createdBy": null
		},
		{
			"id": "{child record id}",
			"fields": null,
			"files": null,
			"preview": null,
			"thumbnail": null,
			"masterFile": null,
			"masterFileLatestVersion": null,
			"classifications": null,
			"contentType": "Record",
			"tag": null,
			"parentId": "{record id}",
			"parent": null,
			"ancestors": null,
			"hasChildren": null,
			"children": null,
			"modifiedOn": "2017-01-05T10:04:34.027Z",
			"modifiedBy": null,
			"createdOn": "2017-01-05T10:03:54.007Z",
			"createdBy": null
		}
		]
	},
	"modifiedOn": "2017-01-05T10:02:15.507Z",
	"modifiedBy": null,
	"createdOn": "2017-01-05T10:01:23.04Z",
	"createdBy": null
} 
						

Reading a record with embedded Ancestors

The Ancestors property returns a collection of all ancestors (parent and parents-of-parents) records of this child record, if any.

GET /record/{record id}
API-version:1
accept:application/json
select-record:ancestors
						
Output:
{
	"id": "{record id}",
	"fields": null,
	"files": null,
	"preview": null,
	"thumbnail": null,
	"masterFile": null,
	"masterFileLatestVersion": null,
	"classifications": null,
	"contentType": "Record",
	"tag": null,
	"parentId": null,
	"parent": null,
	"ancestors": null,
	"hasChildren": null,
	"ancestors": {
		"items": [
		{
			"id": "{ancestor record id}",
			"fields": null,
			"files": null,
			"preview": null,
			"thumbnail": null,
			"masterFile": null,
			"masterFileLatestVersion": null,
			"classifications": null,
			"contentType": "Record",
			"tag": null,
			"parentId": "{record id}",
			"parent": null,
			"ancestors": null,
			"hasChildren": null,
			"children": null,
			"modifiedOn": "2017-01-06T09:43:54.407Z",
			"modifiedBy": null,
			"createdOn": "2017-01-05T10:02:26.073Z",
			"createdBy": null
		},
		{
			"id": "{ancestor record id}",
			"fields": null,
			"files": null,
			"preview": null,
			"thumbnail": null,
			"masterFile": null,
			"masterFileLatestVersion": null,
			"classifications": null,
			"contentType": "Record",
			"tag": null,
			"parentId": "{record id}",
			"parent": null,
			"ancestors": null,
			"hasChildren": null,
			"children": null,
			"modifiedOn": "2017-01-05T10:04:34.027Z",
			"modifiedBy": null,
			"createdOn": "2017-01-05T10:03:54.007Z",
			"createdBy": null
		}
		]
	},
	"modifiedOn": "2017-01-05T10:02:15.507Z",
	"modifiedBy": null,
	"createdOn": "2017-01-05T10:01:23.04Z",
	"createdBy": null
}
						

Override/Update inherited field

Updating the value of an inherited field is different from updating a normal field. When updating the value of an inherited field it’s important to also update the inheritance status of the field: if you update a field that is in status Inherited, you also have to change the inheritanceState property to Overridden.

PUT /record/{record id}
API-version:1
accept:application/json
Content-Type:application/json
select-Record:fields
					
Body:
{
	"fields": {
		"addOrUpdate": [
        {
			"id": "57d307a0-0ee4-4c94-bbac-a6f800d2646d",
			"inheritanceState" : "Overridden",
    		"localizedValues": [
			{
				"languageId": "c2bd4f9bbb954bcb80c31e924c9c26dc",
				"value": "NEW text in English"
			}
			] 
		}
		]
	}
}
					

Reset Overridden field

There is also a possibility to reset Overridden field back to Inherited. Send PUT request to updated overridden field with MISSING or EMPTY LocalizedValues and field inheritanceState = Inherited.

PUT /record/{record id}
API-version:1
accept:application/json
Content-Type:application/json
							
Body :
{
	"fields": {
		"addOrUpdate": [
		{
			"id": "{id}",
			"inheritanceState" : "Inherited"
		}
		]
	}
}
							
Or
{
	"fields": {
		"addOrUpdate": [
		{
			"id": "{id}",
			"inheritanceState" : "Inherited", 
			"localizedValues":[]
		}
		]
	}
}
							

Advanced searching

Basic search functionality is provided by the filter parameter that can be passed in requests to the top-level collection endpoints. See the Examples: Searching section for details.

For more complex search queries on records, the ADAM REST API provides the top-level /search endpoint. Advanced searching is done in the following way:

POST /search/records HTTP/1.1

The body of the request is in the following format:

{
	"searchExpression":
	{
		"disabledKeywords": null,
		"supportWildcards": false,
		"defaultLogicalOperator": "AND",
		"languages": ["c2bd4f9bbb954bcb80c31e924c9c26dc"],
		"expression": "CreatedOn < 2015-09-29T12:24:22.287Z",
		"parameters": [],
		"namedParameters": {},
		"subExpressions": null
	},
	"facets": [
		{
			"name": "price",
			"type": "numericFieldRange",
			"fieldId": "b7a3a79f-f403-4af3-9f4c-a3cd0069b2c4",
			"rangeStart": 0,
			"rangeEnd": 1000,
			"spans": [1, 2]
		}
	],
	"logRequest": true
}

The result for the above query has the following structure:

{
	"facets": [
		{
			"name": "price",
			"values": [
				{
					"key": {
						"from": 0,
						"to": 1
					},
					"count": 645
				},
				{
					"key": {
						"from": 1,
						"to": 3
					},
					"count": 2945
				},
				...
			]
		}
	],
	"page": 1,
	"pageSize": 50,
	"totalCount": 38610,
	"items": [ ... ]
}

Some remarks:

  • Searching for records/classifications using a search expression is done in 2 steps: first ElasticSearch is queried to get a list of matching IDs, then those IDs are used to query the ADAM database.
    If any of the search results is deleted between step 1 and 2, the TotalCount value will be out of sync with the real count of search results.
    If a property or field value of those objects is changed between step 1 and 2, the retrieved facet count related to that property or field will be out of sync with the real count.
  • Facet values with a count of 0 are omitted from the reply, even if they are directly specified, e.g. as explicit values. If the consuming application needs to display facet values with a count of 0, it should keep track of them internally.

The search request has the following parameters:

Parameter Description
searchExpression An advanced search expression. See below for the detailed list of search expression parameters.
facets An array of facet definitions, when specified, the search response will contain the number of hits matching each facet. See the Facets section below for more details.
logRequest LogRequest is an optional parameter used for logging advanced search expressions in the ADAM Enterprise Search Log. If the value is not set or if it's set to false, then the REST API will not perform search expression logging. When set to true the REST API will log the search query including its result information.
NOTE: search logging stores the “origin” parameter and it is read by REST API from REFERER header.
If it's not specified in the request from the custom applications/services, the REST API will use the USER-AGENT header to fill the "origin". The "origin" may be used to distinguish several search sources within the same application or several applications/services.
NOTE: Search logging is also controlled by the .enterpriseSearchActionsToLog and .enterpriseSearchLogDetail settings in ADAM. See the ADAM Administrator Guide for more information.

Search expression parameters

Parameter Description
expression The actual search expression, may optionally contain named or unnamed parameters. You can specify either an expression or subExpressions as parameter of a search expression, but not both.
parameters An array of values that will fill in the question marks in the expression query.
namedParameters A collection of key value pairs holding the values for the named parameters prefixed with an @ sign in the query.
disabledKeywords Allows you to disable specific keywords in the query. You can choose one or more of the options listed below:
  • And
  • At
  • Contains
  • Dot
  • Equals
  • GreaterThan
  • GreaterThanOrEqual
  • In
  • LessThan
  • LessThanOrEqual
  • MinusSign
  • None
  • Not
  • NotEquals
  • Or
  • PlusSign
  • QuestionMark
supportWildcards Indicates whether an asterisk (*) in a value is considered to be a wildcard ( true) or whether it is considered to be part of the value. Also applies to question marks (?) in quoted strings: when the supportWildcards flag is set, the question marks will match any single character.
defaultLogicalOperator Boolean operator that is automatically added to the search query when a Boolean operator is missing. The logical operator can be AND or OR, the default value is AND.
languages Allows restriction of the search to a list of one or more language Ids. If omitted, all language Ids are taken into account.
subExpressions An optional collection of sub-expression. If specified, only records will be returned that will match all of the sub-expressions (logical AND). You can specify either an expression or subExpressions as parameter of a search expression, but not both.

Facets

All facets have these parameters in common:

Parameter Required Description
name yes A textual identifier for this facet, used only by the client to correlate requests with responses.
type yes Type of the facet, depending on facet type different parameters, combinations of parameters and parameter types are possible. The possible facet types are:
  • classification
  • createdBy
  • createdOn
  • dateFieldRange
  • dateTimeFieldRange
  • fileType
  • modifiedBy
  • modifiedOn
  • numericField
  • numericFieldRange
  • optionListField
  • textField
  • textListField
  • timeFieldRange
filters no Filters allow you to limit the hits returned without affecting facets. If filters are specified, the aggregated counts in the facets remain the same. However, only records that match the filter criteria specified in the facet are returned. The parameter type of the filters depends on the facet type, but is always the same type as the explicitValues or explicitRanges parameter.
NOTE: In the below examples, filters are sometimes specified as an example, but not always. All facets, however, accept filters.

The number of facets that can be returned per request is limited. This limitation is stored in the setting .enterpriseSearchMaxNumberOfFacetsPerRequest. If the administrator configured more than the allowed number of facets, the list of facets will be truncated. This means that the search engine will only include the first n facets from the list (n being the setting value), and all others will be ignored. The list of ignored facet names are later on listed in the search response, in the property TruncatedFacets. See search response resource for more information on its properties.

The following facet types are supported:

  • ClassificationFacet
    {
    	"name": "brand",
    	"type": "classification",
    	"facetRootId": "BCAEDD3B-DA09-4DED-817D-D92D335158AF",
    	"options": ["FacetRoot", "Children"],
    	"directLinkedOnly": true,
    	"maximumFacetValues": 20,
    	"filters": []
    }
    
    or
    {
    	"name": "brand",
    	"type": "classification",
    	"explicitValues": ["BCAEDD3B-DA09-4DED-817D-D92D335158AF", "20099504-462F-408F-A5F8-51CB140A7A43"],
    	"directLinkedOnly": true,
    	"filters": ["BCAEDD3B-DA09-4DED-817D-D92D335158AF"]
    }
    
    Parameter Required Description
    facetRootId no The classification Id used to determine which classifications will be faceted on, in combination with the options parameter. You must specify either explicitValues or facetRootId.
    options no These options specify how the facetRootId is used to determine which classifications are faceted on. This must be a combination of FacetRoot, Children, Descendants or All:

    • FacetRoot: include the facet root classification as facet value.
    • Children: include the facet root classifications children as facet values.
    • Descendants: include all the facet root classifications descendants as facet values.
    • All: include the facet root classification and all its descendants as facet values.

    Defaults to FacetRoot.
    directLinkedOnly no Determines if facet counts only take records into account that are directly linked to the facet classification, or also records that are linked to children or descendants of the facet classification.
    explicitValues no A list of Ids, when specified, only shows facets corresponding to the specified classifications. You must specify either explicitValues or classificationId.
    maximumFacetValues no Maximum number of facet values.
  • CreatedByFacet
    {
    	"name": "creator",
    	"type": "createdBy",
    	"explicitValues": [ "BCAEDD3B-DA09-4DED-817D-D92D335158AF", "20099504-462F-408F-A5F8-51CB140A7A43" ],
    	"maximumFacetValues": 12,
    	"filters": [ "20099504-462F-408F-A5F8-51CB140A7A43" ]
    }
    
    Parameter Required Description
    explicitValues no A list of Ids. When specified, only shows facets corresponding to the specified users. When not specified, all users are taken into account.
    maximumFacetValues no Maximum number of facet values returned.
  • CreatedOnFacet
    {
    	"name": "date of creation",
    	"type": "createdOn",
    	"rangeStart": "2014-05-15T10:41:19.51Z",
    	"rangeEnd": "2015-05-15T10:41:19.51Z",
    	"spans": [
    		{
    			"dateTimeUnit": "days",
    			"value": 7
    		},
    		{
    			"dateTimeUnit": "months",
    			"value": 1
    		}
    	],
    	"boundaries": ["Lower", "Upper"],
    	"filters": [
    		{
    			"rangeStart": "2014-05-01T10:41:19.51Z",
    			"rangeEnd": "2014-05-15T10:41:19.51Z"
    		},
    		{
    			"rangeStart": "2014-05-15T10:41:19.51Z",
    			"rangeEnd": "2014-05-31T10:41:19.51Z"
    		}
    	]
    }
    
    or
    {
    	"name": "date of creation",
    	"type": "createdOn",
    	"explicitRanges": [
    		{
    			rangeStart: "2014-05-01T10:41:19.51Z",
    			rangeEnd: "2014-05-15T10:41:19.51Z"
    		},
    		{
    			rangeStart: "2014-05-15T10:41:19.51Z",
    			rangeEnd: "2014-05-31T10:41:19.51Z"
    		}
    	],
    	"boundaries": ["Lower", "Upper"],
    	"filters": []
    }
    
    Parameter Required Description
    rangeStart no Start date and time of the range to take into account. Cannot be specified if explicitRanges is specified.
    rangeEnd no End date and time of the range to take into account. Cannot be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Spans are objects that have a number property value, and a dateUnit that can be one of years, months, days, hours, minutes or seconds. Cannot be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that coincide with range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.
  • DateFieldRangeFacet
    {
    	"name": "productionDate",
    	"type": "dateFieldRange",
    	"fieldId": "E63E2645-BC54-4D64-AEE6-FC5458DB6AAE",
    	"rangeStart": "2014-05-15T00:00:00.00Z",
    	"rangeEnd": "2015-05-15T00:00:00.00Z",
    	"spans": [
    		{
    			"dateUnit": "days",
    			"value": 7
    		},
    		{
    			"dateUnit": "months",
    			"value": 1
    		}
    	],
    	"boundaries": ["Lower", "Upper"],
    	"filters": []
    }
    
    or
    {
    	"name": "productionDate",
    	"type": "dateFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"explicitRanges": [
    		{
    			"rangeStart": "2014-05-01T00:00:00.00Z",
    			"rangeEnd": "2014-05-15T00:00:00.00Z"
    		},
    		{
    			"rangeStart": "2014-05-15T00:00:00.00Z",
    			"rangeEnd": "2014-05-31T00:00:00.00Z"
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	],
    	"filters": [
    		{
    			"rangeStart": "2014-05-15T00:00:00.00Z",
    			"rangeEnd": "2014-05-31T00:00:00.00Z"
    		}
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    rangeStart no Start date of the range to take into account. Cannot be specified if explicitRanges is specified.
    rangeEnd no End date of the range to take into account. Cannot be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Spans are objects that have a number property value, and a dateUnit that can be one of years, months or days. Cannot be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that fall on range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.
  • DateTimeFieldRangeFacet
    {
    	"name": "productionDateTime",
    	"type": "dateTimeFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"rangeStart": "2014-05-15T10:41:19.51Z",
    	"rangeEnd": "2015-05-15T10:41:19.51Z",
    	"spans": [
    		{
    			"dateTimeUnit": "hours",
    			"value": 4
    		},
    		{
    			"dateTimeUnit": "days",
    			"value": 1
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	],
    	"filters": []
    }
    
    or
    {
    	"name": "productionDateTime",
    	"type": "dateTimeFieldRange",
    	"explicitRanges": [
    		{
    			"rangeStart": "2014-05-01T10:41:19.51Z",
    			"rangeEnd": "2014-05-15T10:41:19.51Z"
    		},
    		{
    			"rangeStart": "2014-05-15T10:41:19.51Z",
    			"rangeEnd": "2014-05-31T10:41:19.51Z"
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	],
    	"filters": []
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    rangeStart no Start date and time of the range to take into account. Cannot be specified if explicitRanges is specified.
    rangeEnd no End date and time of the range to take into account. Cannot be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Spans are objects that have a number property value, and a dateTimeUnit that can be one of years, months, days, hours, minutes or seconds. Cannot be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that fall on range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.
  • FileTypeFacet
    {
    	"name": "type of file",
    	"type": "fileType",
    	"explicitValues": [
    		"BCAEDD3B-DA09-4DED-817D-D92D335158AF",
    		"20099504-462F-408F-A5F8-51CB140A7A43"
    	],
    	"maximumFacetValues": 9,
    	"filters": [
    		"20099504-462F-408F-A5F8-51CB140A7A43"
    	]
    }
    
    Parameter Required Description
    explicitValues no A list of Ids, when specified, only shows facets corresponding to the specified file types. When not specified, all file types are taken into account.
    maximumFacetValues no Maximum number of facet values returned.
  • ModifiedByFacet
    {
    	"name": "modifier",
    	"type": "modifiedBy",
    	"explicitValues": [
    		"BCAEDD3B-DA09-4DED-817D-D92D335158AF",
    		"20099504-462F-408F-A5F8-51CB140A7A43"
    	],
    	"maximumFacetValues": 9,
    	"filters": [
    		"BCAEDD3B-DA09-4DED-817D-D92D335158AF"
    	]
    }
    
    Parameter Required Description
    explicitValues no A list of Ids. When specified, only shows facets corresponding to the specified users. When not specified, all users are taken into account.
    maximumFacetValues no Maximum number of facet values returned.
  • ModifiedOnFacet
    {
    	"name": "date of modification",
    	"type": "modifiedOn",
    	"rangeStart": "2014-05-15T10:41:19.51Z",
    	"rangeEnd": "2015-05-15T10:41:19.51Z",
    	"spans": [
    		{
    			"dateTimeUnit": "days",
    			"value": 7
    		},
    		{
    			"dateTimeUnit": "months",
    			"value": 1
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	]
    }
    
    or
    {
    	"name": "date of modification",
    	"type": "modifiedOn",
    	"explicitRanges": [
    		{
    			"rangeStart": "2014-05-01T10:41:19.51Z",
    			"rangeEnd": "2014-05-15T10:41:19.51Z"
    		},
    		{
    			"rangeStart": "2014-05-15T10:41:19.51Z",
    			"rangeEnd": "2014-05-31T10:41:19.51Z"
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	]
    }
    
    Parameter Required Description
    rangeStart no Start date and time of the range to take into account. Can not be specified if explicitRanges is specified.
    rangeEnd no End date and time of the range to take into account. Can not be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Spans are objects that have a number property value, and a dateUnit that can be one of years, months, days, hours, minutes or seconds. Can not be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that fall on range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.
  • NumericFieldFacet
    {
    	"name": "price",
    	"type": "numericField",
    	"fieldId": "EE85EBFD-E46E-44DF-AE44-90A6A4FEC9D7",
    	"explicitValues": [
    		10,
    		99.9,
    		12,
    		27
    	],
    	"maximumFacetValues": 9,
    	"filters": [
    		10,
    		12
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    explicitValues no A list of Ids, when specified, only shows facets corresponding to the specified values. When not specified, all occurring values are returned.
    maximumFacetValues no Maximum number of facet values returned.
  • NumericFieldRangeFacet
    {
    	"name": "priceRange",
    	"type": "numericFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"rangeStart": 100,
    	"rangeEnd": 999,
    	"spans": [
    		5,
    		5,
    		10
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	],
    	"filters": []
    }
    or
    {
    	"name": "priceRange",
    	"type": "numericFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"explicitRanges": [
    		{
    			"rangeStart": 5,
    			"rangeEnd": 25
    		},
    		{
    			"rangeStart": 26,
    			"rangeEnd": 50
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    rangeStart no Start of the range to take into account. Cannot be specified if explicitRanges is specified.
    rangeEnd no End of the range to take into account. Cannot be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Cannot be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that fall on range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.
  • OptionListFieldFacet
    {
    	"name": "choice",
    	"type": "optionListField",
    	"fieldId": "40A5C3E5-518A-4368-823D-CD289723F78F",
    	"explicitValues": [
    		"BCAEDD3B-DA09-4DED-817D-D92D335158AF",
    		"20099504-462F-408F-A5F8-51CB140A7A43"
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    explicitValues no A list of Ids. When specified, only shows facets corresponding to the specified option collection items. If not specified, all option collection items are included.
    maximumFacetValues no Maximum number of facet values returned.
  • TextFieldFacet
    {
    	"name": "color",
    	"type": "textField",
    	"fieldId": "40A5C3E5-518A-4368-823D-CD289723F78F",
    	"explicitValues": [
    		"green",
    		"yellow",
    		"blue"
    	],
    	"caseSensitive": false,
    	"filters": [
    		"yellow"
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    explicitValues no A list of strings. When specified, only returns facet values for these strings. If not specified, all occurring strings are returned.
    maximumFacetValues no Maximum number of facet values returned.
    caseSensitive no Whether or not strings that only differ in case are aggregated into the same facet.
  • TextListFieldFacet
    {
    	"name": "status",
    	"type": "textListField",
    	"fieldId": "CDB72463-2056-4A2D-8903-54D7A1DBBBD0",
    	"explicitValues": [
    		"available",
    		"out of stock"
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    explicitValues no A list of string values. When specified, only shows facets corresponding to the specified option collection items. If not specified, all option collection items are included.
    maximumFacetValues no Maximum number of facet values returned.
  • TimeFieldRangeFacet
    {
    	"name": "productionTime",
    	"type": "timeFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"rangeStart": "10:41:19",
    	"rangeEnd": "18:41:19",
    	"spans": [
    		"00:15:00",
    		"00:30:00",
    		"01:00:00"
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	]
    }
    
    or
    {
    	"name": "productionTime",
    	"type": "timeFieldRange",
    	"fieldId": "53092CEF-A15C-42EE-AA89-369D9A0E1E1B",
    	"explicitRanges": [
    		{
    			"rangeStart": "10:41:00",
    			"rangeEnd": "14:40:59"
    		},
    		{
    			"rangeStart": "14:41:00",
    			"rangeEnd": "18:41:00"
    		}
    	],
    	"boundaries": [
    		"Lower",
    		"Upper"
    	]
    }
    
    Parameter Required Description
    fieldId yes The Id of the field this facet should operate on.
    rangeStart no Start time of the range to take into account. Cannot be specified if explicitRanges is specified.
    rangeEnd no End time of the range to take into account. Cannot be specified if explicitRanges is specified.
    spans no Allows for the explicit specification of spans to divide the facet in. If the range specified is larger than the sum of all spans, the last span will be repeated to cover the entire range. Spans are also expressed as times. Cannot be specified if explicitRanges is specified. If spans are specified, rangeStart and rangeEnd are mandatory.
    explicitRanges no Allows for the explicit specification of ranges to include in the facet. If explicitRanges are specified, you cannot specify rangeStart, rangeEnd or spans.
    boundaries no Specifies how to include hits that fall on range or span boundaries. Can be a combination of Lower, Upper, All, Edge or None. Defaults to None.

Suggestions

The REST API exposes ADAM's Enterprise Search support for record suggestions via the /search/records/suggestions endpoint. Issue a POST request with the following body:

POST /search/records/suggestions HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Accept: */*
Content-Type: application/json
{
	"input": "TRY",
	"languageids": [
		"c2bd4f9b-bb95-4bcb-80c3-1e924c9c26dc"
	],
	"fieldids": [
		"72de5be85e4b453e867ea3cd0069b0f4"
	],
	"fuzziness": 1,
	"numberOfSuggestions": 10
}

This suggestions request object contains the following properties:

Property Required Description
input yes A string that serves as input for the suggestions. This typically corresponds to e.g. partially entered user input.
languageIds yes A list of Ids of the languages that should be taken into account for the suggestions search.
fieldIds yes A list of IDs of the fields that should be taken into account for the suggestion search. Note that your ADAM installation must be configured so that these fields are included in the suggestion search engine indexing, by including them in the .enterpriseSearchSuggestionConfiguration system setting.
fuzziness no A number specifying the fuzziness of the suggestion search. Must be between 0.0 and 2.0. This fuzziness can be interpreted as a Levenshtein Edit Distance — the number of one character changes that need to be made to one string to make it the same as another string.
numberOfSuggestions no The maximum number of suggestions returned. The default value is 5.

The suggestions response contains a list of suggestions per input language:

[
	{
		"languageId": "c2bd4f9bbb954bcb80c31e924c9c26dc",
		"suggestions": [
			{
				"text": "TRYGG",
				"score": 17.31806755065918
			},
			{
				"text": "EKBY VALTER/ EKBY TRYGGVE",
				"score": 8.439911842346191
			}
		]
	}
]

Each suggestion contains the matched text and a score estimating how well the input was matched.

Statistics

For diagnostic purposes, the REST API can perform and report some performance measurements, such as timing statistics of requests and some breakdown of these timings. This functionality is exposed via the /statistics endpoint.

NOTE that this a feature intended for support & debugging purposes only; it is subject to change and should not be used in normal operation of the API. Not all detailed output will be meaningful without internal knowledge of the REST API.

Toggling statistics gathering

Enabling or disabling the collection of statistics can be done via a PUT to the statistics endpoint. By default the gathering of statistics is disabled.

PUT /statistics HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) ...
api-version: 1
Authorization: Token Y2ZkZDdjZTc2NDdmNDBlOWE5NDI2ZDhjNjY2MDRhMTU6QURBTU5FVA==
Accept: */*
Content-Type: application/json
{
	"enabled": "true"
}

Retrieving statistics

To retrieve the gathered statistics, perform a HTTP GET request to the /statistics endpoint. Statistics are structured as a call tree, aggregated at the top level per request type:

{
	"get classification/{classificationId}": {
		"identifier": "get classification/{classificationId}",
		"children":{
			"classificationByIdQuery":{
				"identifier": "ClassificationByIdQuery",
				"children": null,
				"occurences": 1,
				"minDuration": 955,
				"maxDuration": 955,
				"average": 955
			},
			"mappingRequest<Classification, ClassificationResource>":{
				"identifier": "MappingRequest<Classification, ClassificationResource>",
				"children":{"classificationChildrenByParentIdQuery":{
					"identifier": "ClassificationChildrenByParentIdQuery",
					"children": null,
					"occurences": 1,
					...
				},
				"occurences": 1,
				"minDuration": 158,
				"maxDuration": 158,
				"average": 158
			}
		},
		"occurences": 1,
		"minDuration": 1293,
		"maxDuration": 1293,
		"average": 1293
	}
}

Clearing statistics

Clearing the running statistics is also possible, by performing a HTTP DELETE on the /statistics endpoint.

System Administration

Log message Event IDs

Event ID Description
1001 General exception. Log message should be checked for the complete exception stack trace.
1002 An API client provided a unsupported content type value in the request header. Only 'application/json' is supported.
1003 Method the API client used is not supported. Supported HTTP methods are endpoint specific and can be one of the following: GET, POST, PUT, PATCH, DELETE
1005 A problem with the authentication happened. Log message should be checked for a detailed message and exception stack trace.
1006 ADAM REST API service couldn't be started. Log message should be checked for more details and the detailed exception stack trace.
1007 Record file has been checked out for edit.
1008 Record file has been reverted to the non-checkout-out state.
1009 Record file has been uploaded.
1010 All the record file segments have been uploaded.
1011 Record file has been checked in and new version of a file is added.
1012 Raw request / response message with full body, headers and additional details.
1013 Application starting, stopping and similar events.

Note that other event IDs might be present in your eventlog, propagated from ADAM through REST.

Resources