Design Principles

Several design principles and patterns have guided the design and implementation of the ICWS APIs. These principles are discussed here.

This topic contains the following sections:

Subscriptions

Subscriptions in ICWS provide a way for applications to be informed when changes to the Interaction Center system take place. Applications first express interest in a subscription by calling the PUT method on the desired subscription resource. Each subscription resource has an associated message that will be sent to the client application via the messaging channel. This associated message is documented in the "Response" section of the subscription resource documentation. Once interest in a subscription has been established, messages will begin to be delivered through the messaging channel. Subscriptions can be stopped by calling the DELETE method on the subscription resource.

Messaging Channel

The messaging channel is provided by the GET /icws/{sessionId}/messaging/messages method. Client applications should periodically poll this resource to obtain the messages. When the messages are retrieved by the client application, ICWS will remove them from the queue and begin queuing new messages.

Messages

All messages are complex types that derive from a single message type. For more on derived types, see Derived Complex Types. Messages can be differentiated by the special __type (with two underscore characters) property which is a constant value that matches the __type value in the documentation for each message.

Messages also have an isDelta property which indicates whether or not the message is an update to information the client has already received or if the information in the message should replace all previously received information. When a subscription is started, the first message will be sent with "isDelta": false to indicate the message is providing the initial data. Subsequent messages will usually be sent with "isDelta": true and will only provide the differences from the previous state that was communicated to the client. If ICWS determines that it is better to resend the entire state instead of calculating and sending a difference, the message will be sent with "isDelta": false and clients are expected to clear all cached data and replace it with the information provided in the message.

Status Codes

Each API in ICWS describes the status codes that should be expected when using that API. The status codes that have a consistent meaning across all APIs are listed below with descriptions of their meanings.

400 - Bad Request
The 400 status code indicates the client issued an invalid request. This includes malformed requests, requests with data that does not match business logic rules, and other validation errors. The response body will include the details about why the request was rejected.
401 - Unauthorized
This will only be used when the client does not have a session or the session is no longer valid. It is used to indicate that the client needs to log on.
403 - Forbidden
This means that the client is logged on but is not able to perform the requested operation. This is most commonly associated with the enforcement of security rights or access control lists.
404 - Not Found
The 404 status code indicates that the requested resource does not exist. A common case where this is used is when specific resource in a collection does not exist (e.g. GET configuration/users/userThatDoesNotExist). This can also indicate that the server does not implement the API. Checking the version information (see Versioning) when connecting will allow client applications to refrain from making requests to resources that the server does not support.
410 - Gone
This status code is reserved for APIs that have been deprecated and removed. This will not be used when an item in a collection has been deleted, 404 instead will be used.

Error Responses

The HTTP status codes provide a broad classification of an error type, however many times it is useful to provide additional details about the particular error case. The errorId property provides the additional details and can be consumed programmatically for improved error handling in the client application. The message property on the error representations provides a string that is meant for user consumption and can be displayed to the user.

The error identifiers provided in the errorId property are constructed using a hierarchy of period-separated segments. This hierarchy allows for classes of errors to be handled in the same manner without having to handle each individual error identifier. Additionally it allows for the addition of more detailed error identifiers without breaking existing error handling. For example, client code that is handling error.foo will not break if a more detailed error.foo.bar error identifier is added.

In order to check an error identifier, a 'prefix match' must be performed. An error identifier matches a prefix value if every segment in the prefix value is equal to the corresponding segment in the error identifier starting from the first segment in the error identifier. This match takes into account the entire segment when matching, so error.f does not match error.foo.bar but error.foo does.

Note

In order to ensure that future enhancements to an error response do not cause consuming code to break, the 'prefix match' must be used. Do not use a string equality comparison or the addition of a more detailed error identifier may break client-side error handling.

The following JavaScript code provides an example function to match error identifiers:

function isMatch(prefix, errorId) {
    if (errorId === prefix) {
        // the prefix is a match if it is an exact match to the errorId 
        return true;
    }
    if (errorId.indexOf(prefix + '.') === 0) {
        // the prefix is a match if the errorId starts with the prefix followed 
        // by the period character to ensure the entire segment was matched
        return true;
    }
    // the prefix is not a match
    return false;
}

Enumerations

Enumerations (enums), as in many common programming languages, are distinct value types each represented by a set of named constants. In JSON, the enum values are represented as numbers by their integer values. The following is an example of the documentation and associated example JSON showing the enumeration licenseStatus.

Example Enumeration Documentation
{
    "licenseOperationResultList": [
        {
            "licenseName": "<License 1>",
            "isAvailable": true,
            "licenseStatus": 2,
            "errorDetails": ""
        }
    ]
}

In this example, the value of 2 indicates that the licenseStatus is available.

Bit Flags Enumerations

Bit flags enumerations are a special kind of enumeration where the representation of multiple values can be stored on individual bits. Using bitwise operations on the enumeration value, specific values can be added, detected or removed. As with standard enumerations, bit flags enumerations are represented as numbers by their integer values. The following is a simplified JavaScript example of a bit flags enumeration. Notice that each value is a power of 2.

var Colors = {
    RED: 1,
    GREEN: 2,
    BLUE: 4
};
  • To add a specific value to a bit flags enumeration, use the bitwise OR operator (|). The following example creates a value representing magenta using Colors.RED and Colors.BLUE.
    var magenta = Colors.RED | Colors.BLUE;
    
    The value of magenta will be 5.
  • To determine whether a specific value is set in a bit flags enumeration value, use a combination of the bitwise AND operator (&) and the equality operator (===). The following example illustrates how to check for Colors.BLUE and Colors.GREEN in magenta.
    var hasBlue = Colors.BLUE === (magenta & Colors.BLUE),
        hasGreen = Colors.GREEN === (magenta & Colors.GREEN);
    
    hasBlue will be true, while hasGreen will be false.
  • To remove a specific value to a bit flags enumeration, use a combination of the bitwise NOT operator (~) and the bitwise AND operator (&). The following example removes the value of Colors.RED and leaves Colors.BLUE.
    var blue = magenta & ~Colors.RED,
        isBlue = blue === Colors.BLUE;
    
    The value of isBlue will be true.