logo Viomba Dekaani

Update: Mar 5, 2025

Viomba Dekaani is an API to access Viomba's core services programmatically. In order to use the API, please, contact Viomba to get yourself an account.

Viomba services are based on Viomba's proprietary AI models. The models have been trained with samples collected from actual consumers equipped with high-precision eye tracking devices connected to their browsers.

"Dekaani" is Finnish and translates "Dean" in English. The name was chosen for the process controlling the task flow to the worker nodes which are called "Professori"s = "Professor" in English.

Overview

The API is available over HTTPS and it uses JSON-encoded messages in HTTP body to exchange information. All the requests require authentication and are available for authorized accounts, only.

All API operations start by the client calling one of the API end-points. There are two different ways how the client can get the result back from the server:

Both ways are available to all the requests at the same time. Even if the client uses a webhook, it can also poll for the result for the same request.

Result polling

Once client has sent a request to the API, the API assigns a task_id for the task and returns it to the client. The client can start checking for the result by calling the result end-point with the task_id.

The result end-point will respond with either

In case of "error" status, the end-point provides a description for the error.

In case of "success" status, the end-point provides the result data.

Completed tasks will be available for at least a week.

Webhooks

If the client wants the server send the results back using a webhook, it can do so by adding the callback URLs in the request. The client needs to state two webhook URLs:

The webhook process flow is:

Once the server has completed the request, it will either call the "successUrl" or "errorUrl" given in the request, depending on if the request was processed successfully or not. When calling back, the server will include the response data (when calling successUrl), and any passThrough data from the request.

Messages

When ever a client calls the API, or the server calls back the client, the request / response data is wrapped in a message container, which is sent using http "POST" method to the other party:

{
  data: <string, the payload of the request object serialized as a string>,
  created: <numeric, the unix time when the request was generated; Mind that the value is milliseconds!>,
  key_id: <string, the identifier of the key used for the MAC calculation>,
  mac: <string, MAC for authentication>
}

The properties of the data object varies between the API end-points.

Authentication

All the requests to the API needs to be authenticated with a message authentication code (MAC). The MAC is a SHA256-digest calculated from a string containing

<data><created><key_id><ssk>

where

and included in the message from which it was constructed.

When the server calls back the client, it will also sign the payload of the response. It is recommended that the client checks that the MAC in the response is correct to ensure authenticity of the response.

The data might be omitted and treated as an empty string whenever an endpoint doesn't require it.

Authentication with headers

If you wish to, instead of providing created, key_id and ssk in the message body, you can set the following headers in the request:

You will still need to provide the data object data as a JSON encoded string if required by the endpoint.

Authentication example

Given the following data...

{
  "passThrough": {
    "data": "xyz"
  },
  "errorUrl": "https://client.com/api?result=error",
  "successUrl": "https://client.com/api?result=success"
}

...and a key id and shared secret...

  "key_id": 3,
  "ssk": "4ba05045a317c3e8d70562b9e9a8fc62db3a580551cbcc682daf33891d955f27"

...a correctly signed request would look like this

{
  "data": "{\"passThrough\":{\"data\":\"xyz\"},\"errorUrl\":\"https://client.com/api?result=error\",\"successUrl\":\"https://client.com/api?result=success\"}",
  "key_id": 3,
  "created": 1739261442176,
  "mac": "21bde916eb5565dfa729b55da916ea4abd2699050515533b75c743072cc4aecd"
}

Rate limiting

The API imposes rate limits for the clients. If any of the rate limits are met, when the client calls the API, the API will respond with an error message, and the client needs to re-send the request later.

There are 2 limits for each account: The maximum number of request per minute, and per hour.

The benchmark endpoint has a separate general rate limit.

NOTE: Rate limiting is not applied to api/result end-point.

Amazon S3 settings

If the client uses end-points which upload result files to S3 bucket, the client needs to deliver its S3 settings to Viomba. The same S3 settings will be used by the API for uploading the result files.

The settings consists of

The default bucket can be changed by the client for each request, if needed.

Webhooks

When the server has completed a request, it will call either the successUrl or errorUrl of the request. The body of the call is a JSON-encoded object with the task_id that was handed to the client when the request was accepted, together with the possible result data from the end-point.

The server expects the client callback URL to respond with a status code 2xx. If the status code is not 2xx, it is assumed that the delivery failed, and the server will retry later up to 3 times.

The server callback is signed the account ssk. If there are more than one ssks for the account, the one used by the server can be identified by the key id.

Example callback response

{
  "data": "{\"task_id\":1759,\"passThrough\":{\"customer_data\":\"xyz\"}}",
  "created": 1739266858157,
  "key_id": 5,
  "mac": "6e517b90b551557eff2809d9c9c4a5945c1912aa77ccfe3098dbac6aaba1a507"
}

End-points

All end-points except api/result and api/benchmark have certain standard request parameters in the data-object:

 data: {
    successUrl: <string, callback URL for successful response. Optional - if not set, client must call api/result to get the result data>.
    errorUrl: <string, callback URL for failed response. Optional - if not set, client must call api/result to get the result data>,
    passThrough: <string, optional, data the client wants to pass back to itself>,
    s3Config: <object, optional, alternative upload S3 settings to use>
 }

s3Config-object, if present, is defined as:

{
  region: <string, name of the AWS region>,
  bucket: <string, name of the bucket>,
  accessKeyId: <string, AWS accessKeyId>,
  secrectAccessKey: <string, AWS secretAccessKey>
}

An example of a complete request to the ad_slicer end-point is below:

POST https://dekaani.viomba.com/api/ad_slicer

{
    "data": "{\"pageUrl\":\"https:\\\/\\\/adserver.com\\\/ad\\\/12345\\\/\",\"successUrl\":\"https:\\\/\\\/myapp.com\\\/result\\\/success\",\"errorUrl\":\"https:\\\/\\\/myapp.com\\\/result\\\/error\",\"passThrough\":\"{'mydata':'myvalue'}\"}",
    "created": 1739434653000,
    "key_id": 1,
    "mac": "0a52c552b3ae8314e401403a2dbb8bf18f8428fe9db445c1f801286cdf877714"
}

The API always responds with the same response with the task ID the server has assigned to the request, if successful:

{
  success: true,
  task_id: <numeric, the ID assigned to the request by the server>,
  message: 'task queued with the id xxxx'
}

or if the request was not accepted, with an error:

{
  success: false,
  message: <string, the description of why the request could not be accepted>
}

Errors

Possible protocol level errors

If the request is accepted it's still possible for the request processing to fail for various reasons. In this case the provided error URL will be called with the reason after Viomba Dekaani has finished processing the request.

{
  error: "Error while processing task: data should have required property 'pageUrl'",
  task_id: 123,
  passThrough: { customer_data: 'xyz' }
}

POST /api/result/{task_id}

Once client has sent a request to any of the other end-points, it can call this end-point to check for the results. The referenced task is given as an URL parameter.

Required parameters (path):

Response object:

If the request is invalid, the end-point will respond with an appropriate HTTP status code (500, 429, 404, 403, 401 or 400). The response body might contain optional information, but no status is provided.

The mac for this request should be computed from the string <task_id><created><key_id><ssk>

Note that when querying results the task id needs to be appended to the mac hash string even though it's not part of the request body!

Example request

{
  key_id: 4,
  created: 1741073863624,
  mac: '7af63913b381a6410d1ce6435fc2254558d9957819358b3ae0de9b3f7883bd5b'
}

Example responses

{
  status: 'processing'
}

Task success response

{
  status: 'success',
  data: { task_id: 1234, passThrough: { customer_data: 'xyz' } }
}

Task error response

{
  status: 'error',
  data: {
    error: "Error while processing task: data should have required property 'urls'",
    task_id: 1234,
    passThrough: { customer_data: 'xyz' }
  }
}

POST /api/test

A test end-point for developers. The end-point has no required parameters, as it is intended for the developers to test the authentication.

Example result

{
  task_id: 123,
  passThrough: { customer_data: 'xyz' }
}

POST /api/ad_slicer

Slices an ad into PNGs and stores them into a S3 bucket. The ad must be available over HTTPS, like on an ad server, or a document hosted on a web server.

Required parameters:

Optional parameters:

Response object properties:

Example result

{
  slices: [
    {
      t: 0,
      url: 'https://customer-bucket.s3.amazonaws.com/1207987adffbebe418124812409880909abbcdeee890109824124214bbfaasf.png',
      width: 300,
      height: 300
    }, {
      t: 200,
      url: 'https://customer-bucket.s3.amazonaws.com/b59beafc59fea5c95abe899b58aeb48ce4bcef4b4b4489bba494e4bac498333.png',
      width: 300,
      height: 300
    },
  ],
  hash: '0x930b70141ffd1374',
  task_id: 123,
  passThrough: { customer_data: 'xyz' }
}

POST /api/creative_prediction

Predicts the performance of the creative from one (or multiple, if animated) image(s) of the creative.

Required parameters:

Response object properties:

Example result

{
  modelVersionNumber: 112,
  seen: 0.07857066988945008,
  seen3000: 0.02052544504404068,
  seen6500: 0.006649241596460342,
  seen8500: 0.0050738144665956495,
  viewtime: 9772,
  task_id: 123,
  passThrough: { customer_data: 'xyz' }
}

POST /api/heatmap_prediction

Predicts the distribution of the focus points of viewing on different areas of a display ad surface. The ad creative is given as one (or multiple, if animated) image(s).

Required parameters:

Optional parameters:

Response object properties:

Example result

{
  heatmap: 'https://customer-bucket.s3.amazonaws.com/9085481309abbd57abbd1358abbdef.png',
  colored: 'https://customer-bucket.s3.amazonaws.com/addf8b4684rer8466ae88cd8abgd23.png',
  fogmap: 'https://customer-bucket.s3.amazonaws.com/6814e86d86bb888fffa687c6e9a7e9.png',
  modelVersionNumber: 106,
  task_id: 123,
  passThrough: { customer_data: 'xyz' }
}

POST /api/benchmark

Returns the latest market data benchmarks for ad formats.

This endpoint is not a task endpoint and responds with the bechmark results directly. Likewise there are no required parameters for calling this endpoint and it's enough to only provide the minimal parameters for authentication: created, key_id and mac

The mac for this request should be computed from the string <created><key_id><ssk>

Example response

{
  "byRegion": [
    {
      "region": "ee",
      "lastUpdated": "2025-11-21",
      "byFormat": [
        {
          "media": "desktop",
          "type": "display",
          "width": 160,
          "height": 600,
          "seen": 0.088,
          "viewtime": 1201
        }
      ]
    },
    {
      "region": "fi",
      "lastUpdated": "2025-11-21",
      "byFormat": [
        {
          "media": "desktop",
          "type": "display",
          "width": 160,
          "height": 600,
          "seen": 0.288,
          "viewtime": 2951
        },
      ]
    },
  ],
  "average": {
    "byFormat": [
      {
        "media": "desktop",
        "type": "display",
        "width": 160,
        "height": 600,
        "seen": 0.898,
        "viewtime": 4755
      },
    ]
  },
  "success": true
}