# Alemba API Programmers’ Guide

## API structure <a href="#api" id="api"></a>

Additionally, a number of logical entities have been added that allow similar entities to be grouped together.  The hierarchical structure allows sub-entities to inherit common properties, allowing for consistent meaning and behavior.

The structure is indicated in the Alemba API Entity Details Pane in the API explorer.

## Languages

The API is platform independent - it can be accessed from any kind of web client, using a range of languages. The API Explorer provides language neutral examples of the structures sent and received as part of a web request/response, for each action, for each entity.

## Authentication

The API uses standard oAuth 2.0 authentication, via /alemba.web/oauth/login.

The authentication workflow issues a short-lived (10 minutes) Access Token and a longer-lived (24 hours) Refresh Token on Login. The Access Token is used for authentication on the REST API. The Refresh Token is used to renew the Access Token and therefore maintain the session. The Refresh Token allocates a ASM Core Session and consumes a licence.

The process is illustrated as follows, flowing from the top downwards.

<figure><img src="/files/AK6hSfSq8asvzEg4o5MX" alt=""><figcaption></figcaption></figure>

When the Refresh Token is used to renew an Access Token, a new Refresh Token is also issued, and the ASM Core Session is extended. The used Refresh Token becomes invalid and should be discarded. Clients should store the new Refresh Token for subsequent usage. If the ASM Core Session expires or is removed, the Refresh Token will become invalid. If the Refresh Token expires, the ASM Core Session is terminated.

The single use Refresh Token and short lived Access Token ensures that compromised tokens quickly become invalid - protecting the security of individual users, and preventing unauthorized Access Token reuse.

The Access Token must be presented in the Authorization header of the HTTP request:

```
Authorization: Bearer <Access Token>
```

Note that the Authorization service supports the following oAuth 2.0 Grant Types:

* authorization\_code – Authenticate using Single Sign On (SSO), for Windows authentication and SAML
* client\_credentials – Authenticate using integrated security for anonymous access to the API, not full access
* password – Authenticate using a username and password
* refresh\_token – Authenticate using an existing Refresh Token

### Logging in

#### UserName and Password

Below is an example of the code used to login with a username and password.

For more information on client ids, see Configuring Authentication for the Alemba API.

```
function passwordLogin() {
var args = {
client_id: "clientid",
grant_type: "password",
scope: "scope",
password: "username",
username: "password"
var xhr = $.ajax({
url: 'alemba.web/oauth/login',
type: "POST",
data: args,
contentType: 'application/x-www-form-urlencoded'
});
xhr.done(onGrantSuccess).fail(function (err) { return onGrantFailure(err, "password"); });
return xhr;
}
```

#### Access Token

Or, to refresh your access token:

```
function refreshTokenLogin(refreshToken) {
var args = {
client_id: "clientid",grant_type: "refresh_token",scope: "scope",refresh_token: refreshToken
};
var xhr = $.ajax({
url: 'alemba.web/oauth/login',
type: 'POST',
data: args,contentType: 'application/x-www-form-urlencoded'
});
xhr.done(onGrantSuccess).fail(function (err) {
if (err.status == 401) {
}
else {
onGrantFailure(err, "refresh_token");
}
});
return xhr;
}
```

{% hint style="warning" %}
**scope** should be set to **session-type:Analyst** or **session-type:User**. It is case sensitive.
{% endhint %}

### Login Responses

For successful Logins the response will be:

```
{
expires_in: number, // number of seconds until access_token expiry
access_token: string, // token used for data access
refresh_token: string, // token used for access_token renewal
scope: string, // The actual scope of the token
}​
```

{% hint style="info" %}
Note that there is a new refresh\_token in the response. The old one will no longer work and must be discarded. It is acceptable to renew your access\_token before it is due to expire, but you must not do so with every request.
{% endhint %}

#### Login Response Errors

If the authorization request is not successful, clients can expect to receive a suitable HTTP response code and JSON formatted data containing an error code.

The response data may also include error\_description, which gives the developer a clue as to the precise cause of the failure.

```

{
error: string, // one of the oauth 2.0 error codes
error_description: string, // a description of the error if applicable
}
```

In these cases, the response is deliberately vague so as to protect the integrity of the authorization server.

| HTTP Status Code | Error Code      | Reasons                                                           |
| ---------------- | --------------- | ----------------------------------------------------------------- |
| 401              | invalid\_client | The client\_id is incorrect or the client is not enabled          |
| ​400             | invalid\_grant  | The credentials are not correct, the user is not allowed to login |

If you receive a 401 response, it is because your access token has expired, and you must refresh it using the refresh token. If you receive a 401 response when using a refresh token, you must login again with username and password.

### Logging out

You can logout as follows:

```
function logout() {
var deferred = $.Deferred();
var args = {
token: exports.grant.refresh_token
};
var xhr = $.ajax({
url: 'alemba.web/oauth/logout',
type: "POST",
data: args,
contentType: 'application/x-www-form-urlencoded',
headers: {
"Authorization": "Bearer " + exports.grant.access_token
}
});
xhr.done(function () {
//Logout success
deferred.resolve();
}).fail(function (err) {
switch (err.status) {
case 404:
deferred.resolve();
break;
case 400:
deferred.reject("Invalid token");
break;
case 401:
refreshTokenLogin(exports.grant.refresh_token).done(function () {
//We've successfully refreshed the access token
//Now we can try to invalidate the refresh token again
logout().done(function () {
deferred.resolve();
}).fail(function (err) {
//Logout is still not working.
//The session may still be active and may still be consuming a license.
//The session can be terminated by an administrator from logon control, so this error should be reported
deferred.reject(err);
});
}).fail(function () {
//If you cant log in its because the refresh token has expired.
//This can be considered a successful logout
deferred.resolve();
});
break;
case 403: //Not allowed, probably because the refresh token is not related to the access token
default:
deferred.reject(err.responseJSON.Message);
break;
}
});
return deferred.promise();
}​
```

### Logout Responses

Logout will give one of the following responses:

<table><thead><tr><th width="184">Response</th><th>Meaning</th></tr></thead><tbody><tr><td>200</td><td>Logged out successfully</td></tr><tr><td>400</td><td>Token invalid or missing</td></tr><tr><td>401</td><td>Not authorized because it’s not been possible to validate your ownership of the refresh token. In this case you must refresh the access token and try again</td></tr><tr><td>403</td><td>That refresh token doesn’t belong to you</td></tr><tr><td>404</td><td>The refresh token is valid but has already been removed. Maybe you logged in elsewhere</td></tr></tbody></table>

## Base RESTful API methods

The following HTTP verbs are used by the API to perform the listed actions.

<table><thead><tr><th width="213">Create</th><th>POST</th></tr></thead><tbody><tr><td>Read</td><td>GET</td></tr><tr><td>Update</td><td>PUT</td></tr><tr><td>Delete</td><td><p>DELETE</p><p></p></td></tr></tbody></table>

{% hint style="info" %}
The API supports delete where it is appropriate, including delete for attachments and person images (avatars)
{% endhint %}

## A Programmatically Discoverable API

The API can be used to return information about itself, in the form of hypermedia – machine readable descriptions and links to further similar information, allowing a developer to progressively explore the breadth and depth of the API for themselves. What is more, these descriptions are used by the API itself, guaranteeing that this “documentation” is always current.

### Root Level Information on API Scope

For example, to discover root level information on the scope of the API, invoke

```
http://localhost/alemba.api/api?$metadata&$options
```

Note that this response will also be returned for any request which does not specify a resource, for example:

```
GET http://localhost/alemba.api
GET http://localhost/alemba.api/api
GET http://localhost/alemba.api/api/v1
```

### ​Metadata

The metadata will be returned in JSON format and will contain links to the metadata for top level entities exposed by the API, for example:

```
{
"_links": {
"Approval": [
{
"_self": "api:v1/approval/$metadata"
}
],
"Call": [
{
"_self": "api:v1/call/$metadata"
}
],
...
},
"description": "A description of the API, the links at this level and the ResourceDescriptor response type."
}
```

​All metadata responses may include the following properties:

<table data-header-hidden><thead><tr><th width="217"></th><th></th></tr></thead><tbody><tr><td>children</td><td><p>An array of descendant types for the current response</p><p><strong>Call may list children including Incident</strong></p><p>The metadata for each child only includes "_self"</p></td></tr><tr><td>description</td><td>A description of the current metadata response</td></tr><tr><td>name</td><td>The name of the entity that is the subject of the metadata response</td></tr><tr><td>properties</td><td>An array of property descriptions for the subject entity. These properties provide the minimum information required to understand the data model and basic constraints.</td></tr></tbody></table>

Each entry in the array may include the following properties:

<table data-header-hidden><thead><tr><th width="219"></th><th></th></tr></thead><tbody><tr><td>name</td><td>The name of the entity property</td></tr><tr><td>displayName</td><td>The default display name of the property. This could be used in table column headers or form fields</td></tr><tr><td>type</td><td>A description of the data type of this property. The type property is a complex type which has the following properties:</td></tr><tr><td>displayTypes</td><td>The suggested display types for this property</td></tr><tr><td>dataType</td><td>The type of data this property represents</td></tr><tr><td>class</td><td>The kind of property</td></tr><tr><td>description</td><td>A description of the purpose of the property</td></tr><tr><td>usage</td><td>Internal when the property is used for internal business logic, otherwise Public</td></tr><tr><td>isKey</td><td>The property represents the unique identifier (primary key) for the entity</td></tr><tr><td>noSearch</td><td>When true, this property is not supported in searches</td></tr><tr><td>defaultValue</td><td>An indication of the default value for this property</td></tr><tr><td>length</td><td>The maximum length of this field. Text fields only</td></tr><tr><td>uppercase</td><td><p>When true, this indicates that the Text value will be capitalized.</p><p>Non capitalized input may cause validation errors in a future release.</p></td></tr><tr><td>status</td><td>Indicates the current release status of the subject entity. "Alpha", "Beta", "GA"</td></tr><tr><td>_actions</td><td>A hash map of action name and an array of action metadata</td></tr><tr><td>_context</td><td>A reference to the entity metadata of a record or of the metadata of the parent of the subject entity</td></tr><tr><td>_links</td><td>A hash map of name and an array of link metadata. These links must be requested using the http verb GET</td></tr><tr><td>_self</td><td>A reference to the current response link and action metadata will always include a link to _self and will often include an "href" property</td></tr></tbody></table>

| displayTypes | The suggested display types for this property                                                                                                          |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| dataType     | The type of data this property represents                                                                                                              |
| class        | The kind of property                                                                                                                                   |
| description  | A description of the purpose of the property                                                                                                           |
| usage        | Internal when the property is used for internal business logic, otherwise Public                                                                       |
| isKey        | The property represents the unique identifier (primary key) for the entity                                                                             |
| noSearch     | When true, this property is not supported in searches                                                                                                  |
| defaultValue | An indication of the default value for this property                                                                                                   |
| length       | The maximum length of this field. Text fields only                                                                                                     |
| uppercase    | <p>When true, this indicates that the Text value will be capitalized.</p><p>Non capitalized input may cause validation errors in a future release.</p> |
| status       | Indicates the current release status of the subject entity. "Alpha", "Beta", "GA"                                                                      |
| \_actions    | A hash map of action name and an array of action metadata                                                                                              |
| \_context    | A reference to the entity metadata of a record or of the metadata of the parent of the subject entity                                                  |
| \_links      | A hash map of name and an array of link metadata. These links must be requested using the http verb GET                                                |
| \_self       | A reference to the current response link and action metadata will always include a link to \_self and will often include an "href" property            |

### HREF Templated

The "href" may be templated, as denoted by the syntax {id}. The templated values must be replaced by the client.

```
{id} in "api:v1/call/{id}" should be replaced with the Ref of a call.
```

{id} always indicates the primary key field for the target entity. All other entity properties may also be referenced in the template. e.g. {Partition} where Partition is the name of the property in the entity referenced by "\_context".

"\_context" and "\_self" will always define a medialink to an API resource. For brevity, the links are prefixed with "api:"

Clients should replace this prefix with the actual API base url

{% code overflow="wrap" %}

```
Given an api base url of http://web-server/core-system/alemba.api/api, api:v1/call/$metadata should be interpreted as http://web-server/core-system/alemba.api/api/v1/call/$metadata
```

{% endcode %}

All API medialinks can be invoked using the $options suffix.

These links can then be followed to explore further details about the entity, what it is and what it can do.

All API entities support simple and predictable RESTful actions.

```
"api:v1/call" supports GET for searching and POST for create
"api:v1/call/1​" supports PUT for update and GET to get that instance of a call.
```

## Discovering the entity actions

Many entities also support more complex actions, such as forward.

These actions are typically accessed using "**api:v1/call/1/forward**"

Details of the required inputs and supported HTTP method can be found in the metadata for that action.

For example the Call Create action metadata can be accessed with

**<http://localhost/alemba.api/api/call/$create?$options>**

This metadata gives you info about the Create action, including a list of mandatory and optional properties and parameters. $create in the above example can be substituted with any action that is supported by the Call entity.

What is more, you can use the same principles not just as an aid to programming, but at runtime too. The metadata that is returned about a specific object contains links for the list of actions for that object instance in its current state. (An exception is the Search action, which will only return links to the relevant Get action for each record.) For example you will only see the Reopen action if a Call is in a closed state.

### Searching <a href="#searchin" id="searchin"></a>

The Rest API supports expressive searching of most entities

The query parameters and syntax applies to all Search actions for all entities.​

To start, it is possible to simple request a resource using HTTP GET.

**​GET api:v1/call**

This will return a reference to all accessible calls in JSON format

```
{
"results": [
{
"_context": "api:v1/call/$metadata",
"_self": "api:v1/call/3"
},
{
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
],
"_self": "api:v1/call?$top=2147483647",
"__count": 275
}
```

The response contains the following properties

* "results": This is an array of search results. Each result will always include a \_context url (so you know what it is) and a \_self url (so you know how to get that item).
* ​"\_self": This is a url refering to the current response​

Notice that the \_self url includes a query string parameter

```
$top=2147483647​
```

The search actually ran without any row limit. It will try to return every row (accessible to the current session).

This query string parameter is added to the response as a hint.

## Paging

The Rest API supports flexible paging of search results.

### $top

**$top** accepts a positive signed integer value (Int32) and is used to define a row count.

```
// SGET api:v1/call​?$top=30
```

This will limit the response to the top 30 records. If you don’t explicitly specify the row count, then it will default to $top=100.

### **$orderby**&#x20;

**$orderby** accepts a comma separated list of property names and optional sort direction (see $select for more details on property names) and is used to define the order of the results​

```
GET api:v1/call​?$orderby=Ref​
```

​This will return all Calls ordered by Ref

By default the orderby clause will be applied in ascending order, but this can be overridden

```
//GET api:v1/call​?$orderby=Ref​ asc
```

​​​This will return all Calls ordered by Ref in ascending order

```
GET api:v1/call​?$orderby=Ref​ desc
```

This will return all Calls ordered by Ref​ in descending order

### **$skip**&#x20;

**$skip** accepts a positive signed integer value (Int32) and is used to define a number of rows to skip

`GET api:v1/call​?$top=30`

This will limit the response to the top 30 records

and `GET api:v1/call​?$skip=30&$top=30`

This will skip the first 30 records and return the next 30 (ie rows 31 to 60)

These parameters can be combined (in any order) to control page size and contents

`GET api:v1/call​?$top=30&$skip=30&$orderby=Ref​ desc`

This will return the top 30 Calls ordered by Ref in descending order

### $count

The API also supports **counting**, which can be used to calculate the total number of pages

**$count** must be set to true and is used to instruct the api to return a count only

```
GET api:v1/call​?$count=true
```

This will return a text/plain response containing a number which represents the total number of rows.

### **$inlinecount**

Alternatively, **$inlinecount** can be used to have the count be returned with a set of results

```
GET api:v1/call​?$top=30&$inlinecount=true
{
"results": [
{
"_context": "api:v1/call/$metadata",
"_self": "api:v1/call/3"
},
{
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
],
"_self": "api:v1/call?$top=2147483647",
"__count": 275
}
```

Note that "\_\_count" is included in the response body.​

### ​Paging Best Practice

Use of these paging features is critical for individual client and application wide performance and should be utilized by all API consumers for all searches.

Even where it is assumed that there are only a handful of records.

Using **$inlinecount** results in two executions of the database query; one to get the count; and one to get the result set. Therefore it is important that this parameter is not added to every request.​

## Selecting columns​

The Rest API supports configurable column selection in search results.

### **$select**&#x20;

**$select** accepts a comma separated list of property paths to include in the search results

```
// SGET api:v1/call​?$select=Ref,Description​
```

​This instructs the API to include Ref and Description in the search results​

```
{
"results": [
{
"Ref": 3,
"Description": "Microsoft Windows 2000 needs to be installed across all client machines.",
"_context": "api:v1/call/$metadata",
"_self": "api:v1/call/3"
},
{
"Ref": 4,
"Description": "Cannot access intranet.",
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
],
"_self": "api:v1/call?$select=Ref,Description&$top=2147483647"
}
```

{% hint style="info" %}
**Note that as well as retrieving properties from the entity, you can directly retrieve properties from related entities**. This is extremely powerful.&#x20;

In the Classic WCF API, you would first need to get the raw foreign key ref from the main entity and then do a lookup on the related one, or you would have to write your own custom query, including joining objects and ensuring that the related object is not locked.&#x20;

The RESTful API is built on an underlying schema that takes care of these complexities and allows you to get the data you need in the simplest possible way.
{% endhint %}

In fact you can traverse the entity relationships as far as you need, so getting a call priority’s name can be achieved with:

```
GET api:v1/call​?$select=Ref,Description​​,Priority.Name
{
"Ref": 4,
"Description": "Cannot access intranet."​,
"Priority": {
"Name": "Priority 3",
"_context": "api:v1/call-priority/$metadata",
"_self": "api:v1/call-priority/3"
},
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
```

#### Linked Fields from Linked Relations

Notice that the linked entity includes metadata links.  This also applies to linked fields from linked relations.

```
GET api:v1/call​?$select=Ref,Description​​,Service.Location.Name
```

​Returns

```
{
"Ref": 4,
"Description": "Cannot access intranet.",
"Service": {
"Location": {
"Name": "San Francisco",
"_context": "api:v1/location/$metadata",
"_self": "api:v1/location/9"
},
"_context": "api:v1/service/$metadata",
"_self": "api:v1/service/1"
},
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
```

Property paths in $select can be aliased using a prefix to simplify the response

```
GET api:v1/call​?$select=Ref,Description​​,LocationName:Service.Location.Name​
{
"Ref": 4,
"Description": "Cannot access intranet.",
"LocationName": "San Francisco",
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
```

$select will also accept named Extension Augmenters

```
GET api:v1/call​?$select=Ref,@AssignmentState
```

This will add the computed assignment state to the response ​​

```
{
"Ref": 4,
"AssignmentState": "Assigned to Me",
"_context": "api:v1/incident/$metadata",
"_self": "api:v1/incident/4"
}
```

To help with orientation during development, $select will also accept \*. This will return all properties for the entity.

```
$select=*
```

#### Best Practice $select=\*

$select=\* is only intended for development and should not be used in production.

Selecting values from extension fields is supported, but carries a significant overhead and so should be avoided.

## Filtering

​The Rest API supports expressive filtering of search results.

### **$filter**

**$filter** accepts a C# LINQ style predicate which is translated to parameterized SQL and applied as a search filter

```
GET api:v1/call​?$filter=Priority==1
```

This would return all accessible calls where the Priority is equal to 1

## Equality Operators and Methods

All data types support basic equality comparison

<table data-header-hidden><thead><tr><th width="186"></th><th></th></tr></thead><tbody><tr><td>==</td><td>Is equal to</td></tr><tr><td>=</td><td>Is equal to</td></tr><tr><td>!=</td><td>Not equal to</td></tr></tbody></table>

Binary data types support basic equality comparison but in practice, this can only be used to compare the property value with null.

```
GET api:v1/call/1/attachment​?$filter=BinaryData!=null
```

### **Boolean** data types

**Boolean** data types support basic equality operators

When comparing with true or false, the right hand side of a boolean property equality expression can be omitted.

Binary equality expressions can also be negated with !

```
GET api:v1/person​?$filter=IsLoggedIn==true
```

is equivalent to

```
GET api:v1/person​?$filter=IsLoggedIn
```

or

```
GET api:v1/person​?$filter=IsLoggedIn==false
```

is equivalent to

```
GET api:v1/person​?$filter=!IsLoggedIn
```

## **DateTime** data type filters&#x20;

**DateTime** data type filters must be used with one of the applicable augmenters

```
GET api:v1/call​?$filter=CreatedDate>@DateTime(2017-01-01T00:00:00.000+1)
```

This will return all Calls which were created after Midnight on January 1st 2017 (UTC+1)

{% hint style="info" %}
Note that the date value must be expressed in ISO8601 format
{% endhint %}

### @Now

The @Now augmenter can be used to compare a date value with the current time.

```
GET api:v1/call​?$filter=CreatedDate==@Now
```

This is most useful where a query will be designed and then subsequently reused.

### @NowOffset

The @NowOffset augmenter can be used to compare a date value with the current time and an offset expressed in days hours and minutes

```
GET api:v1/call​?$filter=CreatedDate>@NowOffset(0,-1,-30)
```

This will return Calls created in the last 0 days, 1 hours and 30 minutes (in the last hour and a half).

As with all filters, the expressions can be combined using logical And (&&) and Or (||) operators

{% code overflow="wrap" %}

```
GET api:v1/call​?$filter=CreatedDate>=@DateTime(2017-01-01T00:00:00.000+1)&&CreatedDate<=@NowOffset(0,0,-30)​​
```

{% endcode %}

This will return Calls created between Midnight on January 1st 2017 (UTC+1)​ and half an hour ago.

{% hint style="warning" %}
Dates do not have to be defined in UTC format, but MUST include the timezone.

If no timezone is supplied, dates are assumed to be in local server time.
{% endhint %}

## **Text** and **RichText** data types

**Text** and **RichText** data types support basic equality and can also be used with some string comparison methods

### Contains

The **Contains** method can be used to match records where a string property contains a word or phrase

```
GET api:v1/call​?$filter=ShortDescription.Contains("email")
```

### StartsWith

The **StartsWith** method can be used to match records where a string property starts with a word or phrase​

```
GET api:v1/call​?$filter=ShortDescription.StartsWith("email")
```

### EndsWith

​The **EndsWith** method can be used to match records where a string property ends with a word or phrase​​

```
GET api:v1/call​?$filter=ShortDescription.EndsWith("email")
```

As with all filters, the expressions can be combined using logical **And (&&)** and **Or (||)** operators​

{% code overflow="wrap" %}

```
GET api:v1/call​?$filter=hortDescription.Contains("email")||ShortDescription.StartsWith("outlook")
```

{% endcode %}

## ​Number Data Types

**Number** data types support more complex equality comparison operators

<table data-header-hidden><thead><tr><th width="178"></th><th></th></tr></thead><tbody><tr><td>></td><td>Greater than</td></tr><tr><td>&#x3C;</td><td>Less than</td></tr><tr><td>>=</td><td>Greater than or equal to</td></tr><tr><td>&#x3C;=</td><td>Less than or equal to</td></tr></tbody></table>

```
GET api:v1/call​?$filter=Number1>=3
```

## Combining Expressions

Filter expressions can be combined using logical And (`&&`) and Or (`||`) operators​​ and can be grouped using ​parentheses `(` and `)`

{% code overflow="wrap" %}

```
GET api:v1/call​?$filter=((Number1>=3​||Number2==1)&&(Priority==3||Priority==1))||(CreatedDate>@NowOffset(0,0,-30)​​​&&@IsAssignedToMe)
```

{% endcode %}

​Note that query string parameter values must be url encoded

{% code overflow="wrap" %}

```
GET api:v1/call​?$filter=((Number1%3E%3D3%E2%80%8B%7C%7CNumber2%3D%3D1)%26%26(Priority%3D%3D3%7C%7CPriority%3D%3D1))%7C%7C(CreatedDate%3E%40NowOffset(0,0,-30)%E2%80%8B%E2%80%8B%E2%80%8B%26%26%40IsAssignedToMe)
```

{% endcode %}

## Sorting <a href="#sorting" id="sorting"></a>

### $order

The API supports sorting using $order, and you can use several qualifiers, as illustrated in the following examples.

`$orderby=FirstName` would sort the result by the FirstName property in descending (a-z) order.

`$orderby=FirstName desc` would also sort the result by the FirstName property in descending (a-z) order.

`$orderby=FirstName asc` would sort the result by the FirstName property in ascending (z-a) order.

It is also possible to specify multiple order properties:

`$orderby=FirstName, LastName asc` would sort the result by the FirstName property in descending (a-z) order and then sort by the LastName property in ascending (z-a) order, e.g. Andrew Anderson, John Smith, John Jones

## Joining <a href="#joining" id="joining"></a>

### $leftjoin & $innerJoin

You can use **$leftJoin** and **$innerJoin** to link to entities that are not already linked as part of the schema definition. This is the case with entities that have multi-column keys e.g. CallHistory, which has a composite key of Ref and LastHistoryOrder. Once you create such a join, you will want to refer to properties of that joined entity, so part of the definition of the join is an alias for that join, in the format

```
Alias:TargetEntity(TargetProperty==SourceProperty)
```

… where the clause in brackets can occur multiple times. For example:

```
&$leftJoin=LastAction:CallHistory(TicketId==Ref && Order==LastHistoryOrder)
```

You can then use the alias in your select clause just as if it were a property of the entity with a Data Type that is the target entity, e.g. LastAction.Description.

{% hint style="warning" %}
Note that this technique should be used sparingly, because as with extension fields the relationship is not indexed and so may result in reduced performance.
{% endhint %}

## Case sensitivity

Everything after any of the $ functions above is case sensitive.

## Security

### Handling partitions

Where entities are Partitioned, the results returned are automatically limited to those in partitions accessible to the current session. Therefore it is not necessary to apply partition filtering, however if desired, a specific partition can be specified in one of two ways.

* **$filter=Partition==1** will return records where the Partition Ref equals 1. The filter will be applied even if the entity is not partitioned
* **$partition=1** will work as above, but will only apply the partition filter if the entity is actually partitioned. This will also account for variable partitioning of Asset types, e.g api/v1/asset?$partition=1 will return a combination of Services, ConfigurationItems, etc. where Service may be partitioned, but ConfigurationItem is not.

**$partition=1** is the **recommended method**.

## Data Types <a href="#data" id="data"></a>

The following data types are exposed by the API:

<table data-header-hidden><thead><tr><th width="227"></th><th></th></tr></thead><tbody><tr><td>RESTful API</td><td>Equivalent in Classic (WCF) API</td></tr><tr><td>Binary</td><td>Byte Array</td></tr><tr><td>Boolean</td><td>Boolean, Yes/No</td></tr><tr><td>DateTime</td><td>Date/Time</td></tr><tr><td>Integer</td><td>Integer</td></tr><tr><td>Long</td><td>Long</td></tr><tr><td>Float</td><td>Float</td></tr><tr><td>Double</td><td>Double</td></tr><tr><td>Decimal</td><td>Decimal</td></tr><tr><td>Short</td><td>Short</td></tr><tr><td>Text</td><td>String</td></tr><tr><td>RichText</td><td>String</td></tr></tbody></table>

Data types can also be entities. For example, the Service properties on a Call has a Data Type of Service (Lookup in the metadata json). This means that it contains the key value of the associated object – click on the circle icon in the API Explorer to see what that is. (This is equivalent to the WCF data type “Lookup”.)

Note that Boolean property standardizes underlying data inconsistencies. Across various tables, flags are stored as **"Y", "YES", "T", "TRUE", "ON", "1", "P", "A"** – for all of these, the API will return true, and conversely will convert true to appropriate values on PUT and POST.

## Display Types

The following table shows the types that are supported, and the related data types.

<table data-header-hidden><thead><tr><th width="228"></th><th></th></tr></thead><tbody><tr><td>Display Type</td><td>Data Type</td></tr><tr><td>Checkbox</td><td>Boolean</td></tr><tr><td>DatePicker</td><td>DateTime</td></tr><tr><td>DateTimePicker</td><td>DateTime</td></tr><tr><td>Lookup</td><td>entity</td></tr><tr><td>MultiLookup</td><td>entity</td></tr><tr><td>MultiSelect</td><td>entity</td></tr><tr><td>ListBox</td><td>entity</td></tr><tr><td>Numeric</td><td>Integer, Long, Float, Double, Decimal, Short</td></tr><tr><td>Password</td><td>Text</td></tr><tr><td>RichText</td><td>RichText</td></tr><tr><td>Select</td><td>entity</td></tr><tr><td>Text</td><td>Text</td></tr><tr><td>TextArea</td><td>RichText</td></tr><tr><td>TieredSelect</td><td>Entity</td></tr></tbody></table>

## Augmenters <a href="#augmente" id="augmente"></a>

The API includes a set of inbuilt functions that simplify the retrieval of complex data using Search actions. This allows API users to easily select, view and manipulate data using business-level concepts, rather than dealing with the low level data that sometimes needs gathering from many sources to provide that information. These functions are known as augmenters. These can be used as virtual variables, for example in a filter clause. So if you only want to see calls that have breached, you would say:

```
SGET http://…/api/v1.0/call?$filter=@SlmBreached
```

There are a number of different types of Augmenters:

* **Condition Augmenters** – for use with $filter, encapsulating complex search conditions (including joins).
* **Function Augmenters** – provide additional functionality to the queries and are entity-independent
* **Token Augmenters** – return simple values for use in query filters and are entity-independent
* **Extension Augmenters** – computed properties, properties selected from other tables with join, etc.

### Useful Augmenters

The table below lists some of the most useful augmenters. They are used for all entity types, and apply to calls, requests and tasks.

To find the other augmenters appropriate for an entity, examine the entity in the API explorer.

| Augmenter       | Application                                                                                                    | Example                                                                                                                                                         |
| --------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| @IsDeleted      | Entities that have been deleted                                                                                | <p>$filter=@IsDeleted</p><p>$filter=!@IsDeleted</p>                                                                                                             |
| @DateTime       | Creates a value from a date/time string in ISO 8601 format, for use in query filters                           | $filter=LoggedDate > @DateTime(2000-01-01T00:00:00.000Z)                                                                                                        |
| @Guid           | Creates a value from a GUID string, for use in query filters                                                   | $filter=Id = @Guid(75f7a7d5-652f-4e30-bd92-dc6e9594b28b)                                                                                                        |
| @Now            | Current date                                                                                                   | $filter=LoggedDate <= @Now                                                                                                                                      |
| @NowOffset      | Offsets the current date by days, hours and minutes Filter logged date within last 7 days, 2 hours, 30 minutes | $filter= LoggedDate > @NowOffset(-7,-2,-30)                                                                                                                     |
| @OrganizationId | Current users Organization id                                                                                  | <p>$filter=User.OrganizationId == @OrganizationId</p><p>$filter=User.Organization == @OrganizationId</p><p>$filter=User.Organization.Ref == @OrganizationId</p> |
| @UserId         | Current user's id                                                                                              | <p>$filter=User == @UserId</p><p>$filter=UserId == @UserId</p><p>$filter=User.Ref == @UserId</p>                                                                |

## Error Handling

The API will return errors with an appropriate HTTP Status Code and a message with the following structure:

| Message:   | string - This is the error message                                                           |
| ---------- | -------------------------------------------------------------------------------------------- |
| Type:      | string - This is the type of the error – usually just the Exception type name                |
| SubStatus: | string - This is a string which will help to narrow down the reason for the HTTP Status Code |

### SubStatus Values

Current SubStatus values are:

None, ResourceNotFound, RecordNotFound, LinkedRecordNotFound, NotSupported, NotImplemented, NotAllowed

Programmatically, you should rely upon the HTTP Status Code and the SubStatus.

The HTTP Status Codes that are explicitly returned are: 200, 304, 400, 401, 403, 404, 405, 415 and 500.

Often a **404** response will include a message body (as described above). This is so that you can tell the difference between a badly formed url and a non-existent record.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.alemba.com/asm-hermes/integrate/apis/alemba-restful-api/alemba-api-programmers-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
