Thetis IMS
Integration

Introduction

Our REST API is available at https://api.thetis-ims.com/2.

Authentication

To access the API you first need to get an access token from our authentication server at [https://auth.thetis-ims.com]. The authentication scheme is OAuth2 with client credentials. The authentication endpoint is described here.

To authenticate you will need a client id and a secret. We will provide you with both by email. Please contact us at support@thetis-ims.com to obtain a client id and a secret.

Authorization

On each request you must provide the access token acquired from the authentication server as ‘Authorization’ header. Furthermore, you must provide a ‘x-api-key’ header. You must generate the value of the ‘x-api-key’ from within the Thetis IMS application. We describe how to do that here.

The ‘x-api-key’ header value is specific to one area within a subscription. You may change the value of the ‘x-api-key’ from one request to another. This is only relevant if you are operating across multiple areas.

Areas are used differently by different subscribers. 3PL providers use areas to separate their customers from one another. Enterprises with multiple geographically separated warehouses use an area for each warehouse.

Limits

For each value of the ‘x-api-key’ header there are two limits attached:

A limit on the number of requests per second over a prolonged period of time: 50.

A limit on the number of requests per day: 100000.

If these limits are exceeded, further requests are throttled. The gateway will in that case return status code 429.

Endpoints

Get a list of resources
GET /resource

You may add filter and pagination parameters to this type of endpoints. See further details below.

Get a single resource
GET /resource/{id}
Get a list of subordinate resources
GET /resource/{id}/subordinate-resource
Post a resource
POST /resource
Post a subordinate resource
POST /resource/{id}/subordinate-resource
Put an attribute of a resource
PUT /resource/{id}/attribute
Patch a resource
PATCH /resource/{id}

You should only include those attributes that you want to change.

Not all endpoints are available for all resources. Please consult our Postman documentation to see which endpoints that are available for which resources.

Resources

Below you will find a list of the resources available through the REST API. You may click on an item in the list to get a description of the resource and its attributes.

Our REST API only returns the bare data and no metadata whatsoever.

References from one instance of a resource to instances of other resources are always in the form of the unique id. So, if for instance you have an instance of the ‘globalTradeItems’ resource in hand, and that instance has a ‘productId’ field with a given value, then you may use that value to lookup the related product.

Filters

To filter the instances returned you may provide query parameters like this:

{filter-field}={filter-value}

Our data catalogue shows which filters are available.

Pagination

All queries return a maximum of 1000 rows. To iterate through a larger set of rows you must provide pagination parameters like this:

maxNumRows=1000&firstRow=2000

With these query parameters your request will return 1000 rows starting with row number 2000.

Our Postman documentation shows several examples of this.

HTTP status codes

When you call an endpoint your call must first pass our gateway. Only after that is the call passed on to our application.

The gateway will return the usual HTTP status codes with the usual meaning, if your request is not valid or the gateway is not able to handle the request at this time:

  • 400
  • 403
  • 415
  • 429
  • 500
  • 503

If your call makes it to the application, the application will either fail or succeed in processing your request. If the application fails, the gateway will return status code 422. If the application succeeds, the gateway will return status code 200.

If the processing fails and the gateway therefore returns status code 422, the body of the response will look like this:

{
    "messageType": "ERROR",
    "messageCode": "unknown_Shipment",
    "messageText": "There is no shipment with number 4711 in area Randers."
}

You can find several examples of error messages in our Postman documentation.

Parsing the response body

When parsing the json response you must be aware that if a field has the value null in Thetis IMS, it might either be present in the response with the value null or it might be absent. In other words: Absence of a field signals that it has the value null.

When parsing the json response you must be aware that it might contain new fields. That is fields that were not described at the time of your implementation. Your parser should silently ignore these fields.

Further documentation

Postman

Our Postman documentation describes the endpoints of the interface and the request and response bodies. You can find it here.

Openapi 3

You can find a Openapi description here. If you copy and paste the content of the file into the editor at editor.swagger.io, you get a complete list of the endpoints available. You can invoke methods from the editor, and you can generate stubs for your integration program.

Authentication example

The following example show how we do authentication from our own client-side node.js programs.

const axios = require('axios');

var AWS = require('aws-sdk');
AWS.config.update({region:'eu-west-1'});


async function getIMS(contextId) {

    const authUrl = "https://auth.thetis-ims.com/oauth2/";
    const apiUrl = "https://api.thetis-ims.com/2/";

    let clientId = process.env.ClientId;
    let clientSecret = process.env.ClientSecret;  
    let apiKey = process.env.ApiKey;  

    let credentials = clientId + ":" + clientSecret;
    let base64data = Buffer.from(credentials, 'UTF-8').toString('base64');	
	
    let imsAuth = axios.create({
            baseURL: authUrl,
            headers: { Authorization: "Basic " + base64data, 'Content-Type': "application/x-www-form-urlencoded" },
            responseType: 'json'
        });

    let response = await imsAuth.post("token", 'grant_type=client_credentials');
    let token = response.data.token_type + " " + response.data.access_token;
    
    let ims = axios.create({
            baseURL: apiUrl,
            headers: { "Authorization": token, "x-api-key": apiKey, "Content-Type": "application/json" }
        });
	
    ims.interceptors.response.use(function (response) {
            console.log("SUCCESS " + JSON.stringify(response.data));
            return response;
        }, function (error) {
            if (error.response) {
                console.log("FAILURE " + error.response.status + " - " + JSON.stringify(error.response.data));
            }
            return Promise.reject(error);
        });
		
    return ims;
}