Connect & communicate

Introduction

In order to connect and communicate effectively with the Integration Platform API one needs to understand and adhere to the following rules, guidelines and best practices for efficient integration flows. Be sure to read through and understand the details outlined on this page before you start doing any hands-on integration work.

Environments

Production

All production access is obtained using this address. Be sure to quality assure your integration thoroughly before putting it into production.

Production address format: https://api.{HOSTNAME}/api/

Sandbox

All development and testing should be conducted using a sandbox environment. There are several sandbox environments and they are all accessed through specific environment prefixes. Consult your API account details for exact addresses to the sandboxes you have access to, since it depends on your integration license level.

Sandbox address format: https://api.{env}.{HOSTNAME}/api/

Protocol

The application protocol used is HTTP 1.1 as defined in RFC 2616. HTTP/2 (RFC 7540) is not supported at the moment, neither is HTTP 1.0 or HTTP 0.9. Clients must use HTTPS when interacting with the API. Clients must not ever use plain unencrypted HTTP as this can result in authentication details being exposed.

Request methods

The HTTP protocol defines a number of methods (commands) and these are the ones supported by the Integration Platform API.

GET
Method to retrieve a record. GET requests must not contain a request body. The server will either provide the record requested or an Error.
PUT
Method to update a record. The record will be created and the current record state will be available in the response body upon successful operation, or an Error on failure.
Also note that PUT supports partial modifications to a record which is why you will not ever use the PATCH method explicitly throughout the API.
POST
Method to create a new record. The record will be created and the current record state will be available in the response body upon successful operation, or an Error on failure.
DELETE
Method to remove a record. Only some record types are possible to DELETE in the Integration Platform and upon successful DELETE the record will be kept but marked as isDeleted: true.

Filter response

The API-response can be filtered for most API-endpoints. The first level in the json object can be filtered on fields names. The filter can be used to minimize the API-response to the fields that is relevant for the API-consumer.

Example: the result below can be filtered to only include sku with ?includeFields=sku,stock

{
  "title": "A title",
  "sku": "A sku",
  "stock": "10",
  "...": "..."
}

the result will be

{
  "sku": "A sku",
  "stock": "10"
}

Query parameters

includeFields
Define fields that should be present in the response. Available fields for each endpoint is defined in the OpenApi definition. includeFields can contain a string with multiple values separated by , e.g ?includeFields=field1,field2. It is also possible to send the fields parameter multiple times e.g ?includeFields=field1&includeFields=field2.
excludeFields
Define fields that should be excluded from the response. Available fields for each endpoint is defined in the OpenApi definition. excludeFields can contain a string with multiple values separated by , e.g ?excludeFields=field1,field2. It is also possible to send the fields parameter multiple times e.g ?excludeFields=field1&excludeFields=fields2.

Status codes

All method requests will yield an HTTP response status indicating whether the request was successful or not. The status codes are logically grouped (RFC 2616) as follows:

Informational responses
Status code class range 100199
Successful responses
Status code class range 200299
Redirection messages
Status code class range 300399
Client error responses
Status code class range 400499
Server error responses
Status code class range 500599

Encoding

Responses from the API are UTF-8 encoded and Requests must be UTF-8 encoded.

Rate limit

The Integration Platform use a rate limiter per Tenant. The current rate limit is 10 requests/s with an allowed burst of 25 requests. An exceeded rate of request will cause an increasing delay of the response.

The rate limiter is implemented using a token bucket approach. The bucket will contain a maximum of 25 tokens. Ten new tokens are added every second. A burst of 25 requests would empty the bucket and cause a delay for every following request until the bucket gets new tokens.

Exceeding the limit

The first strategy is to delay the requests but an excessive request rate can cause a rejection response with HTTP status code 429 (Too Many Requests).

Authentication

HTTP Basic Auth is used. Due to this it is required that HTTPS is used at all times. The Integration Platform will reject requests using HTTP only, however this may still cause client credentials to be exposed unencrypted and it is therefore vital that clients never use plain HTTP requests.

Headers

Authentication is achieved using HTTP Basic Auth with a few special HTTP headers. Required HTTP headers are;

X-Tenant
Specifies tenant (by code name) to interact with.
X-ConnectionId
Specifies the specific Connection Id for the API Connector on the Tenant to interact with.
Authorization
HTTP Basic Auth header and value should therefore have the format like Basic BASE64(UTF8(<username>:<password>)).

Authentication example

$ curl
    -u '<USERNAME>':'<PASSWORD>'
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/

User agent

The User-Agent header is not required, however it is recommended that one is provided containing your application name and possibly some contact information. Sending this information will aid in troubleshooting and debugging in the future.

Clients sending the User-Agent header must ensure it is correctly formatted according to RFC 2616. If the client wishes to provide an app name and a contact email address it must be encoded as the following example since @-chars are not allowed everywhere in User-Agent headers.

User agent example

$ curl
    -u '<USERNAME>':'<PASSWORD>' \
    -F 'User-Agent: my-app/1.0 (YOURADDRESS@example.com)' \
    -H 'X-Tenant: <TENANT CODE>' \
    -H 'X-ConnectionId: <CONNECTION ID>' \
    https://api.{HOSTNAME}/api/

Errors

Errors are communicated in two ways:

  1. All errors are signaled using the appropriate HTTP error codes, as defined in RFC 2616.
  2. The response body contains a JSON document with more details about the error.

Error field descriptions

The document contains these fields:

error
This field is always set to true.
time
The server time formatted as Date time when the error occurred.
code
A numeric error code denoting the type of error. A complete list of all error codes is available at errors.json.
defaultMessage
A short human-readable version of the error.
message
A longer human-readable version of the error if available.
helpText
A more elaborate human-readable help text if available.
field
Which field in the record this error relates to.
fieldValue
The current value of the field this error relates to.
helpText
A longer text trying to more in-depth explain the error.
class
Internal Integration Platform component generating the error.
errorCategory
The type of error where possible values are:
  • NotFound - The requested resource was not found.
  • InvalidData - Supplied input data invalid.
  • TypeError - You don’t conform to the schema, see Data types chapter.
  • PermissionDenied - You don’t have permission to access the resource.
  • RemoteAuthFailed - Authentication to the remote system failed.
  • Conflict - The request yielded a conflict where, for example, you tried to create a Product with an SKU already existing on the Tenant.
  • InvalidSettings - Settings provided in the query didn’t pass validations.
  • InternalError - Something went wrong within the Integration Platform. If the problem persists, please contact us.
  • RemoteSystemError - Something went wrong in the communication to the remote system.

Keep in mind that the message texts listed are only the defaults. The messages are usually elaborated when generating the error to provide more information.

Error example

{
    "error": true,
    "time": "2019-06-05T06:58:34Z",
    "code": 100002,
    "subCode": 101019,
    "message": "Field test field cannot be ordered by",
    "defaultMessage": "Field test field cannot be ordered by",
    "field": "field",
    "fieldValue": "unsortableField",
    "helpText": null,
    "class": "record.product.proto.ProductError$ProductFieldNotSortable"
}