2. World Modeler™ Server REST API
The World Modeler™ API is made available as a REST endpoint from which the various operations included in the API can be invoked by any external client or consumer that provides a standard HTTP client. All World Modeler Server instances that provide the API should be configured to use HTTPS for security. For an introduction to REST, please see any of the many articles and tutorials on this subject, for example REST API: Your Guide to Getting Started Quickly .
Being a REST API, the World Modeler interface has the following properties:
- The resource that is being requested is defined via an HTTP URI. These generally have the form URI ROOT/Path to required resource?arguments.
- The operation to be performed on the requested resource is determined by the HTTP method used in the HTTP request. The following methods are used, each for the purpose described below:
HTTP Method | Purpose |
GET | Retrieve information without making any changes to the data on the World Modeler server. GET requests cannot have any payload in their body. |
POST | Submit data to the World Modeler server, possibly making changes on the server. Since the body of POST requests can contain a payload, POST is the method that is most commonly used whenever data must be submitted to the server for any reason. In all cases, the body of a request sent to the World Modeler server should be formatted as a JSON string.
Note that when a new object of any kind is to be created and added to the World Modeler database, the POST method is used. Contrast this to the PUT method which is only used to update existing instances. |
PUT | Update an existing instance of an object managed by the World Modeler server. |
DELETE | Delete an existing instance of an object managed by the World Modeler server. |
- The status of the request is returned to the caller as the HTTP status code value. A full list of HTTP status codes can be found here. Those most commonly used by the World Modeler API and their meanings are listed below:
HTTP Status Code | Meaning |
200 | Success |
400 | Bad Request. The request was not well formed or did not meet the API specification. |
401 | Unauthorized. The required authorization information was missing or invalid. See section 3, below, for further information on World Modeler’s authorization and authentication features. |
403 | Forbidden. The user credentials under which the request is being made do not have permission to perform the specified operation on the requested resource. |
404 | Not Found. The requested resource does not exist. |
500 | An error occurred on the server while trying to fulfill the request. In this case, the message field of the RESTResponse object in the body of the response (see below) will contain further diagnostic information. |
API license key
To use the API on a World Modeler Server endpoint, a valid username and password is required which is used to determine and validate the identity of the user and the permissions that they have been granted or denied. In addition, an API license key must be provided when logging in to the API which the REST interface validates every time a REST call is made. The API license key is intended to be used at the “application” level, in the sense that each client application that connects to the REST API is assigned a single key that user login requests made by the application all share. This allows World Modeler Server to grant or deny permissions at the application level, as well as the user level. Developers accessing the API through tools other than the application they are working on (e.g. Fiddler, Swagger, etc.) should use the API key assigned to that application. To obtain a username, password, and API key for a World Modeler Server endpoint, please contact the system’s administrator.
Returned data and the RESTResponse object
When a World Modeler API invocation successfully completes, the result is returned in the response body as the JSON representation of RESTResponse object. This is part of the World Modeler API definition, and has the form shown below:
{
"status": "Success",
"value": {
"valueField1": "value1",
"valueField2": "value2",
. . .
},
"message": null,
"requestTime": "0001-01-01T00:00:00",
"duration": "00:00:00",
"url": "https://wmserver.some.domain/resource"
}
The fields and their meanings are listed below.
RESTResponse Field | Meaning |
status | Indicates whether the requested operation completed successfully or not. Possible values are:
|
value | If the status is Success, then the data returned by the operation will be placed in the value field as a JSON sub-object. If the status is Fail, or if no value is returned, then value will be null. |
message | If status is Fail, then the message field will contain a diagnostic message. Otherwise, it is null. |
requestTime | The UTC time at which the request was received by the server. |
duration | The time taken to execute the request. |
url | The URL of the request. |
Lazy Loading and “collection” vs “instance” queries
There are many cases where data objects contain levels of detail that may or may not be required depending on the context of the operation being performed. Consider Decision Models, for example. A Decision Model contains fields that directly describe it (its name, description, etc.), but also collections of other objects such as the Decision Model Elements. These collections can be quite large, both in number and in the size of the JSON string required to define each element of the collection.
Sometimes, the entire Decision Model is required, including its Decision Model Element collection. For example, a client application that contains a user interface control for visualizing and editing the Decision Model will require the entire Decision Model object, including all of the Decision Model Elements. But another control, for example, one that lists all of the Decision Models owned by the current user, does not require the entirety of each Decision Model but only its descriptive properties such as name, description etc. Loading the Decision Model Element collection for each Decision Model in this case would be very wasteful.
To support both scenarios, the World Modeler API takes a “lazy loading” approach by distinguishing between “collection” query operations and “instance” query operations. A “collection” query is one that returns a list of objects. Note that query parameters may be supplied that restricts this list to a small number of entities, possibly even a single entity. But the result is still a list. Collection queries are “lazy” in that they only populate the “top level” properties of each object in the returned collection. In the case of a Decision Model, the “collection” version of the GET operation returns the name, description, summary, etc. of each Decision Model in the returned list, but does not populate the Decision Model Element collection. To retrieve the internal details of a “lazy loaded” object, the “instance” version of the GET operation is used. It takes a single object ID as an argument and will return all details of the object, including any nested sub-objects or collections.
Open DI
When representing Decision Intelligence objects, such as Decision Models, their elements, assets, and related data types, the World Modeler API complies with the Open DI standard. For further information, please see https://www.opendi.org.
Test connection to World Modeler Server API
If you have the URL of a World Modeler Server API endpoint, you can test your connection to the endpoint by sending a GET request to: World Modeler Server Root URL/about Note that authentication/authorization is not required to invoke the about operation. The following result should be returned.
{
"status": "Success",
"value": {
"appName": "World Modeler Server",
"message": "This is a demonstration server for the World Modeler API",
"copyright": "Copyright © Quantellia LLC 2023",
"version": "1.0.7",
"buildNumber": "101",
"buildDate": "12/06/2023 16:50:03",
"hostName": "QWW012"
},
"message": null,
"requestTime": "0001-01-01T00:00:00",
"duration": "00:00:00",
"url": "https://host/about"
}
As a simple test, you can navigate to the URL for the about operation in a browser. You should obtain results similar to those shown below.
Cross Origin Resource Sharing (CORS)
Enabling Cross Origin Resource Sharing (CORS) simplifies accessing REST services from within a web browser (see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS for further information), although it may make a browser less secure. The World Modeler Server API allows CORS to be enabled or disabled on an instance by instance basis, and it is enabled by default. If the endpoint you are connecting to blocks CORS requests, then contact the World Modeler Server administrator for the site. Alternatively, a reliance on CORS can be eliminated by invoking the World Modeler Server API from the web server, rather than the browser. This eliminates the need for the browser to make direct requests to any endpoint other than the one from which the page HTML was sent.
Examples: Invoking the API from Javascript
The following code snippets provide examples of how to consume API resources in Javascript using the fetch()
method.
1. Invoke /about
The simplest API resource to invoke is /about
, sinct it uses the HTTP GET method, and does not require authorization.
async function WMAbout()
{
var result = null;
await fetch('https://api.worldmodeler.com/about')
.then(response => response.json())
.then(data => result = data);
return result;
}
2. Invoke /login
and obtain access and refresh tokens
Before any other API resources can be invoked, access and refresh tokens token must be obtained using /login
async function WMLogin(user, pass)
{
var result = null;
/* Set the options that configure the fetch() request. */
options = {
method: 'POST',
headers: { "Accept": "application/json",
"Content-Type": "application/json",
},
mode: "cors",
body: JSON.stringify({
"loginName": user,
"password": pass,
"organization": "string",
"clientAgent": "string",
"apiKey": "string"
})
}
await fetch('https://api.worldmodeler.com/login', options)
.then(response => response.json())
.then(data => result = data);
return result;
}
Note the following:
- For all POST requests, the
Accept
andContent-Type
headers must be set. - The
mode
must be set tocors
to prevent Cross-Origin Resource Sharing errors. - The body must be a JSON string, hence the use of
JSON.stringify
. - On success, the strings returned in
result.value.accessToken
andresult.value.refreshToken
should be retained as they will be needed to authorize calls to other API resources.
3. Invoke /decisionModel
with Authorization
Invoking almost all World Modeler Server API resources requires authorization. Section 3 of this guide describes the API's
authentication and authorization protocols in detail. To summarize, API requests use Bearer
authorization with a Jason Web Token (JWT)
generated by calling /login
, as above.
The function below shows how to use the access token obtained from /login
to authorize the invocation of another API resource—/decisionModel
in this case.
async function WMDecisionModels(accessTok)
{
var result = null;
// Set the options that configure the fetch() request.
options = {
method: 'GET',
headers: { "Accept": "application/json",
"Authorization": "Bearer " + accessTok
}
}
await fetch('https://api.worldmodeler.com/decisionModel', options)
.then(response => response.json())
.then(data => result = data);
return result;
}
Note:
accessTok
is a JWT access token previously obtained by calling/login
.- The JWT in
accessTok
typically has a very short lifespan. If the token has expired, it can be refreshed as described in Section 3 of this guide.
Online Swagger documentation and test harness for World Modeler Server API
You can review each of the World Modeler Server API calls, and if you have a user login ID and an API key, test them out on a live instance of World Modeler server on our interactive API test page.
⇦ Prev: 1. Architecture of World Modeler Server Next: 3. Authentication and authorization ⇨