Skip to content

API reference

Decide API Beta

Beta: in use, and details can still change.

Typed questions about a text, answered with probabilities. Beta. Needs a personal key with decide:process; an organisation integration key gets 403 integration_not_permitted.

Base URL
https://api.komplai.dk

Evaluate one text Beta

POST /v1/decide

Decide (beta) answers typed questions about one text with probabilities instead of prose: choice picks one option, score places the text on a scale, and noul says how likely a statement is true. Every answer has the full posterior and a confidence. A decision model writes no text, so there is nothing to parse; it runs on komplai's local infrastructure in Denmark, with no AI charge, and has 30 seconds to answer. The text is not stored. Needs a personal key with decide:process.

Scopes
decide:process
Try it

Calls are real: komplai processes what you send, each call counts towards your key's limits, and processing in EU cloud counts towards your organisation's monthly AI spending cap. Use test data.

A key that starts with kp_live_. It stays on this page until you leave it and is sent only to api.komplai.dk.

Request body

  • model string

    The decision model: komplai-decide (Laya) or komplai-decide-claes (Claes). Leave it out for the default: the model you chose in the hub, else your organisation's default, else komplai-decide (Laya). A model Decide does not offer your organisation answers 409 model_not_enabled; the API never picks another one. Both run on komplai's local infrastructure in Denmark, with no AI charge.

    One of
    komplai-decide komplai-decide-claes
  • state string | object required

    What to judge: a text, or a JSON object that komplai turns into text. Arrays and other values are refused.

    One of

    • Textstring
    • JSON objectobject

      Can hold fields that are not listed here.

  • questions map<object> required

    Question id to question, from 1 to 64. An id may not be empty (400 invalid_input); it comes back unchanged in answers. The questions share one reading of each text, so several questions cost little more than one.

    Fields
    1 to 64
    Child fields (16)
    • Any key object

      One typed question. type says which answer comes back.

      One of

      • choiceobject
        • type string required
          One of
          choice
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria map<string> required

          Pick one option: option key to what that option means, 32 at most. The answer names the key, so keep keys short and machine-friendly.

          Fields
          2 to 32
          Child fields (1)
          • Any key string
      • scoreobject
        • type string required
          One of
          score
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria string[] required

          A scale: the levels' descriptions, lowest first. The level is the position, starting at 0.

          Items
          2 to 32
          Length of each item
          at least 1
      • noulobject
        • type string required
          One of
          noul
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria object required

          What true and what false mean. Both are required.

          Child fields (2)
          • true string required
            Length
            at least 1
          • false string required
            Length
            at least 1

Responses

200 OK

One answer for every question, with the probabilities behind it. The text is not stored.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid

Body

  • model string required

    The model that answered, by its checkpoint: convaiinnovations/laya/multilingual for Laya, syvai/claes-preview for Claes.

  • answers map<object> required

    Question id to answer, one for every question.

    Child fields (26)
    • Any key object

      One of

      • choiceobject
        • type string required
          One of
          choice
        • choice string required

          The option key with the highest probability.

        • probabilities map<number> required

          Every option key with its probability; they add up to 1.

          Child fields (1)
          • Any key number
            Value
            0 to 1
        • confidence number required

          How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

          Value
          0 to 1
        • action object

          When the model gives it: how likely the answer is safe to act on without a person checking it.

          Child fields (1)
          • act_probability number required
            Value
            0 to 1
      • scoreobject
        • type string required
          One of
          score
        • score number required

          The expected level: each level times its probability, added up. 0.32 on a scale of 0 to 2 lies between the two lowest levels.

          Value
          at least 0
        • max integer required

          The highest level: the number of levels minus 1.

          Value
          at least 1
        • probabilities number[] required

          Each level's probability, in the order of the question's criteria; they add up to 1.

          Value of each item
          0 to 1
        • confidence number required

          How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

          Value
          0 to 1
        • action object

          When the model gives it: how likely the answer is safe to act on without a person checking it.

          Child fields (1)
          • act_probability number required
            Value
            0 to 1
      • noulobject
        • type string required
          One of
          noul
        • noul number required

          The probability that the statement is true.

          Value
          0 to 1
        • probabilities object required
          Child fields (2)
          • true number required
            Value
            0 to 1
          • false number required
            Value
            0 to 1
        • confidence number required

          How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

          Value
          0 to 1
        • action object

          When the model gives it: how likely the answer is safe to act on without a person checking it.

          Child fields (1)
          • act_probability number required
            Value
            0 to 1
  • usage object required
    Child fields (2)
    • input_tokens integer required
      Value
      at least 0
    • output_tokens integer required

      Always 0: a decision model writes no text.

      One of
      0
  • latency_ms number required

    The model's own time in milliseconds, without the network.

    Value
    at least 0
400 Bad Request

The request was refused before processing.

Error codes

  • invalid_input The request is not what the operation documents, for example invalid JSON, a field that is not listed or a value out of range.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
401 Unauthorized

The key is missing or not valid.

Error codes

  • api_key_required No Authorization: Bearer header with a komplai key.
  • invalid_api_key The key is unknown, expired, revoked or retired, the person behind a personal key is no longer a member or no longer assigned any app the key covers, or your organisation's API access for it is not set up or no longer active.
  • invalid_token The key was revoked or expired, or its access ended, while the request was admitted or processed.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
403 Forbidden

The key may not do this, or the organisation's access does not cover it.

Error codes

  • integration_not_permitted An organisation integration key cannot use this operation or this option.
  • insufficient_scope The key lacks a scope the operation needs (x-komplai-scopes): it was not issued or created with it, its person is no longer assigned the app, or the organisation's processing approval no longer covers it.
  • identity_retired The person behind a personal key has been removed from komplai.
  • app_not_assigned The key's person lost the app or their membership while the request was admitted.
  • processing_not_enabled The processing is not enabled for the app in the organisation: EU processing is not approved and enabled, or the agreement keeps processing on local infrastructure.
  • processing_not_approved The organisation's processing approval for the app is missing or was withdrawn.
  • processing_choice_not_allowed The organisation does not allow this processing (local infrastructure or EU cloud) through the API, or the connection is not made available through the API.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
404 Not Found

Not found.

Error codes

  • model_not_enabled The model is not one you may use at this processing, or it is not offered there right now.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
409 Conflict

Conflict with the current state.

Error codes

  • model_not_enabled The model is not one you may use at this processing, or it is not offered there right now.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
413 Content Too Large

Too large.

Error codes

  • Payload Too Large Fastify's reason phrase: the body is over the operation's byte limit.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
415 Unsupported Media Type

The body has no Content-Type, or one the API does not read, such as XML or form data. Send application/json.

Error codes

  • Unsupported Media Type Fastify's reason phrase: the body has no Content-Type, or one the API does not read, such as XML or form data.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
429 Too Many Requests

Refused for now. Wait the seconds in Retry-After before you try again.

Error codes

  • rate_limited Too many requests: the per-minute limit of the person behind a personal key (shared with that person's other keys and use of the hub) or of the integration behind an organisation integration key (shared by its keys), the organisation's (120), the API's (300) or the per-IP network limit. Wait Retry-After seconds.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
  • Retry-After integer required

    Seconds to wait before trying again (at most 60).

    Value
    1 to 60
  • x-ratelimit-limit integer

    Requests per minute allowed from your IP address (the per-IP network limit).

  • x-ratelimit-remaining integer

    Requests left in the current minute from your IP address.

  • x-ratelimit-reset integer

    Seconds until the per-IP window resets.

502 Bad Gateway

A processing service failed. No partial result is returned.

Error codes

  • service_unavailable The model failed or could not be reached, or local infrastructure is not set up for this call right now.
  • invalid_response The model's answer failed validation, so nothing was returned.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
503 Service Unavailable

Processing is not available right now.

Error codes

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
RequestPOST /v1/decide
curl
curl https://api.komplai.dk/v1/decide \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "state": "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
    "questions": {
      "category": {
        "type": "choice",
        "instructions": "Hvad handler henvendelsen om?",
        "criteria": {
          "aktindsigt": "Borgeren beder om kopi af dokumenter eller aktindsigt",
          "klage": "Borgeren klager over en afgørelse",
          "andet": "Noget andet"
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "Hvor hurtigt skal henvendelsen besvares?",
        "criteria": [
          "Inden for den normale frist",
          "Inden for en uge",
          "Samme dag"
        ]
      },
      "personal_data": {
        "type": "noul",
        "instructions": "Indeholder teksten personoplysninger?",
        "criteria": {
          "true": "Ja, for eksempel et navn eller et CPR-nummer",
          "false": "Nej"
        }
      }
    }
  }'
PowerShell
$headers = @{
    Authorization = "Bearer $env:KOMPLAI_TOKEN"
}
$body = [ordered]@{
    state = 'Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm'
    questions = [ordered]@{
        category = [ordered]@{
            type = 'choice'
            instructions = 'Hvad handler henvendelsen om?'
            criteria = [ordered]@{
                aktindsigt = 'Borgeren beder om kopi af dokumenter eller aktindsigt'
                klage = 'Borgeren klager over en afgørelse'
                andet = 'Noget andet'
            }
        }
        urgency = [ordered]@{
            type = 'score'
            instructions = 'Hvor hurtigt skal henvendelsen besvares?'
            criteria = @(
                'Inden for den normale frist',
                'Inden for en uge',
                'Samme dag'
            )
        }
        personal_data = [ordered]@{
            type = 'noul'
            instructions = 'Indeholder teksten personoplysninger?'
            criteria = [ordered]@{
                true = 'Ja, for eksempel et navn eller et CPR-nummer'
                false = 'Nej'
            }
        }
    }
} | ConvertTo-Json -Depth 100

$request = @{
    Method = 'Post'
    Uri = 'https://api.komplai.dk/v1/decide'
    Headers = $headers
    ContentType = 'application/json; charset=utf-8'
    Body = $body
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100
Python
import os

import requests

response = requests.post(
    "https://api.komplai.dk/v1/decide",
    headers={
        "Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
    },
    json={
        "state": "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
        "questions": {
            "category": {
                "type": "choice",
                "instructions": "Hvad handler henvendelsen om?",
                "criteria": {
                    "aktindsigt": "Borgeren beder om kopi af dokumenter eller aktindsigt",
                    "klage": "Borgeren klager over en afgørelse",
                    "andet": "Noget andet",
                },
            },
            "urgency": {
                "type": "score",
                "instructions": "Hvor hurtigt skal henvendelsen besvares?",
                "criteria": [
                    "Inden for den normale frist",
                    "Inden for en uge",
                    "Samme dag",
                ],
            },
            "personal_data": {
                "type": "noul",
                "instructions": "Indeholder teksten personoplysninger?",
                "criteria": {
                    "true": "Ja, for eksempel et navn eller et CPR-nummer",
                    "false": "Nej",
                },
            },
        },
    },
    timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())
JavaScript
const response = await fetch("https://api.komplai.dk/v1/decide", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    state: "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
    questions: {
      category: {
        type: "choice",
        instructions: "Hvad handler henvendelsen om?",
        criteria: {
          aktindsigt: "Borgeren beder om kopi af dokumenter eller aktindsigt",
          klage: "Borgeren klager over en afgørelse",
          andet: "Noget andet",
        },
      },
      urgency: {
        type: "score",
        instructions: "Hvor hurtigt skal henvendelsen besvares?",
        criteria: [
          "Inden for den normale frist",
          "Inden for en uge",
          "Samme dag",
        ],
      },
      personal_data: {
        type: "noul",
        instructions: "Indeholder teksten personoplysninger?",
        criteria: {
          true: "Ja, for eksempel et navn eller et CPR-nummer",
          false: "Nej",
        },
      },
    },
  }),
});

console.log(response.status, response.headers.get("Request-Id"));
console.log(await response.json());
C#
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(330) };
using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.komplai.dk/v1/decide");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));
request.Content = new StringContent(@"{
  ""state"": ""Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm"",
  ""questions"": {
    ""category"": {
      ""type"": ""choice"",
      ""instructions"": ""Hvad handler henvendelsen om?"",
      ""criteria"": {
        ""aktindsigt"": ""Borgeren beder om kopi af dokumenter eller aktindsigt"",
        ""klage"": ""Borgeren klager over en afgørelse"",
        ""andet"": ""Noget andet""
      }
    },
    ""urgency"": {
      ""type"": ""score"",
      ""instructions"": ""Hvor hurtigt skal henvendelsen besvares?"",
      ""criteria"": [
        ""Inden for den normale frist"",
        ""Inden for en uge"",
        ""Samme dag""
      ]
    },
    ""personal_data"": {
      ""type"": ""noul"",
      ""instructions"": ""Indeholder teksten personoplysninger?"",
      ""criteria"": {
        ""true"": ""Ja, for eksempel et navn eller et CPR-nummer"",
        ""false"": ""Nej""
      }
    }
  }
}", Encoding.UTF8, "application/json");

using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);
if (response.Headers.TryGetValues("Request-Id", out var requestId))
{
    Console.WriteLine(string.Join(", ", requestId));
}
Console.WriteLine(await response.Content.ReadAsStringAsync());

Set the environment variable KOMPLAI_TOKEN to your key first.

Response
200 OK
{
  "model": "convaiinnovations/laya/multilingual",
  "answers": {
    "category": {
      "type": "choice",
      "choice": "aktindsigt",
      "probabilities": {
        "aktindsigt": 0.91,
        "klage": 0.03,
        "andet": 0.06
      },
      "confidence": 0.672,
      "action": {
        "act_probability": 0.88
      }
    },
    "urgency": {
      "type": "score",
      "score": 0.32,
      "max": 2,
      "probabilities": [0.72, 0.24, 0.04],
      "confidence": 0.356
    },
    "personal_data": {
      "type": "noul",
      "noul": 0.97,
      "probabilities": {
        "true": 0.97,
        "false": 0.03
      },
      "confidence": 0.806
    }
  },
  "usage": {
    "input_tokens": 118,
    "output_tokens": 0
  },
  "latency_ms": 38
}
400 Bad Request
{
  "error": "invalid_input",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/invalid_input"
}
401 Unauthorized
{
  "error": "api_key_required",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/api_key_required"
}
403 Forbidden
{
  "error": "integration_not_permitted",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/integration_not_permitted"
}
404 Not Found
{
  "error": "model_not_enabled",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/model_not_enabled"
}
409 Conflict
{
  "error": "model_not_enabled",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/model_not_enabled"
}
413 Content Too Large
{
  "error": "Payload Too Large",
  "statusCode": 413,
  "code": "FST_ERR_CTP_BODY_TOO_LARGE",
  "message": "Request body is too large",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/payload-too-large"
}
415 Unsupported Media Type
{
  "error": "Unsupported Media Type",
  "statusCode": 415,
  "code": "FST_ERR_CTP_INVALID_MEDIA_TYPE",
  "message": "Unsupported Media Type",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/unsupported-media-type"
}
429 Too Many Requests
{
  "error": "rate_limited",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/rate_limited"
}
502 Bad Gateway
{
  "error": "service_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}
503 Service Unavailable
{
  "error": "service_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}

Evaluate several texts Beta

POST /v1/decide/batch

Decide (beta): the same questions for up to 100 texts in one call, answered in one pass of the model. The answers come back in the order of states, and the batch is answered whole or refused whole. It counts as one request. Needs a personal key with decide:process.

Scopes
decide:process
Try it

Calls are real: komplai processes what you send, each call counts towards your key's limits, and processing in EU cloud counts towards your organisation's monthly AI spending cap. Use test data.

A key that starts with kp_live_. It stays on this page until you leave it and is sent only to api.komplai.dk.

Request body

  • model string

    The decision model: komplai-decide (Laya) or komplai-decide-claes (Claes). Leave it out for the default: the model you chose in the hub, else your organisation's default, else komplai-decide (Laya). A model Decide does not offer your organisation answers 409 model_not_enabled; the API never picks another one. Both run on komplai's local infrastructure in Denmark, with no AI charge.

    One of
    komplai-decide komplai-decide-claes
  • states (string | object)[] required

    The texts, each judged as state would be on its own.

    Items
    1 to 100

    One of

    • Textstring
    • JSON objectobject

      Can hold fields that are not listed here.

  • questions map<object> required

    Question id to question, from 1 to 64. An id may not be empty (400 invalid_input); it comes back unchanged in answers. The questions share one reading of each text, so several questions cost little more than one.

    Fields
    1 to 64
    Child fields (16)
    • Any key object

      One typed question. type says which answer comes back.

      One of

      • choiceobject
        • type string required
          One of
          choice
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria map<string> required

          Pick one option: option key to what that option means, 32 at most. The answer names the key, so keep keys short and machine-friendly.

          Fields
          2 to 32
          Child fields (1)
          • Any key string
      • scoreobject
        • type string required
          One of
          score
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria string[] required

          A scale: the levels' descriptions, lowest first. The level is the position, starting at 0.

          Items
          2 to 32
          Length of each item
          at least 1
      • noulobject
        • type string required
          One of
          noul
        • instructions string required

          The question, in your own words.

          Length
          at least 1
        • criteria object required

          What true and what false mean. Both are required.

          Child fields (2)
          • true string required
            Length
            at least 1
          • false string required
            Length
            at least 1

Responses

200 OK

The answers for every text, in the order of states. The texts are not stored.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid

Body

  • model string required

    The model that answered, by its checkpoint: convaiinnovations/laya/multilingual for Laya, syvai/claes-preview for Claes.

  • results object[] required

    One per text, in the order of states. A batch is answered whole or refused whole.

    Child fields (30)
    • answers map<object> required

      Question id to answer, one for every question.

      Child fields (26)
      • Any key object

        One of

        • choiceobject
          • type string required
            One of
            choice
          • choice string required

            The option key with the highest probability.

          • probabilities map<number> required

            Every option key with its probability; they add up to 1.

            Child fields (1)
            • Any key number
              Value
              0 to 1
          • confidence number required

            How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

            Value
            0 to 1
          • action object

            When the model gives it: how likely the answer is safe to act on without a person checking it.

            Child fields (1)
            • act_probability number required
              Value
              0 to 1
        • scoreobject
          • type string required
            One of
            score
          • score number required

            The expected level: each level times its probability, added up. 0.32 on a scale of 0 to 2 lies between the two lowest levels.

            Value
            at least 0
          • max integer required

            The highest level: the number of levels minus 1.

            Value
            at least 1
          • probabilities number[] required

            Each level's probability, in the order of the question's criteria; they add up to 1.

            Value of each item
            0 to 1
          • confidence number required

            How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

            Value
            0 to 1
          • action object

            When the model gives it: how likely the answer is safe to act on without a person checking it.

            Child fields (1)
            • act_probability number required
              Value
              0 to 1
        • noulobject
          • type string required
            One of
            noul
          • noul number required

            The probability that the statement is true.

            Value
            0 to 1
          • probabilities object required
            Child fields (2)
            • true number required
              Value
              0 to 1
            • false number required
              Value
              0 to 1
          • confidence number required

            How decided the answer is: 1 minus the posterior's normalised entropy. 1 puts everything on one option, 0 spreads it evenly. It says nothing about whether the answer is right.

            Value
            0 to 1
          • action object

            When the model gives it: how likely the answer is safe to act on without a person checking it.

            Child fields (1)
            • act_probability number required
              Value
              0 to 1
    • usage object required
      Child fields (2)
      • input_tokens integer required
        Value
        at least 0
      • output_tokens integer required

        Always 0: a decision model writes no text.

        One of
        0
  • usage object required

    The whole batch.

    Child fields (2)
    • input_tokens integer required
      Value
      at least 0
    • output_tokens integer required

      Always 0: a decision model writes no text.

      One of
      0
  • latency_ms number required

    The model's own time for the whole batch, in milliseconds.

    Value
    at least 0
400 Bad Request

The request was refused before processing.

Error codes

  • invalid_input The request is not what the operation documents, for example invalid JSON, a field that is not listed or a value out of range.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
401 Unauthorized

The key is missing or not valid.

Error codes

  • api_key_required No Authorization: Bearer header with a komplai key.
  • invalid_api_key The key is unknown, expired, revoked or retired, the person behind a personal key is no longer a member or no longer assigned any app the key covers, or your organisation's API access for it is not set up or no longer active.
  • invalid_token The key was revoked or expired, or its access ended, while the request was admitted or processed.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
403 Forbidden

The key may not do this, or the organisation's access does not cover it.

Error codes

  • integration_not_permitted An organisation integration key cannot use this operation or this option.
  • insufficient_scope The key lacks a scope the operation needs (x-komplai-scopes): it was not issued or created with it, its person is no longer assigned the app, or the organisation's processing approval no longer covers it.
  • identity_retired The person behind a personal key has been removed from komplai.
  • app_not_assigned The key's person lost the app or their membership while the request was admitted.
  • processing_not_enabled The processing is not enabled for the app in the organisation: EU processing is not approved and enabled, or the agreement keeps processing on local infrastructure.
  • processing_not_approved The organisation's processing approval for the app is missing or was withdrawn.
  • processing_choice_not_allowed The organisation does not allow this processing (local infrastructure or EU cloud) through the API, or the connection is not made available through the API.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
404 Not Found

Not found.

Error codes

  • model_not_enabled The model is not one you may use at this processing, or it is not offered there right now.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
409 Conflict

Conflict with the current state.

Error codes

  • model_not_enabled The model is not one you may use at this processing, or it is not offered there right now.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
413 Content Too Large

Too large.

Error codes

  • Payload Too Large Fastify's reason phrase: the body is over the operation's byte limit.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
415 Unsupported Media Type

The body has no Content-Type, or one the API does not read, such as XML or form data. Send application/json.

Error codes

  • Unsupported Media Type Fastify's reason phrase: the body has no Content-Type, or one the API does not read, such as XML or form data.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
429 Too Many Requests

Refused for now. Wait the seconds in Retry-After before you try again.

Error codes

  • rate_limited Too many requests: the per-minute limit of the person behind a personal key (shared with that person's other keys and use of the hub) or of the integration behind an organisation integration key (shared by its keys), the organisation's (120), the API's (300) or the per-IP network limit. Wait Retry-After seconds.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
  • Retry-After integer required

    Seconds to wait before trying again (at most 60).

    Value
    1 to 60
  • x-ratelimit-limit integer

    Requests per minute allowed from your IP address (the per-IP network limit).

  • x-ratelimit-remaining integer

    Requests left in the current minute from your IP address.

  • x-ratelimit-reset integer

    Seconds until the per-IP window resets.

502 Bad Gateway

A processing service failed. No partial result is returned.

Error codes

  • service_unavailable The model failed or could not be reached, or local infrastructure is not set up for this call right now.
  • invalid_response The model's answer failed validation, so nothing was returned.

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
503 Service Unavailable

Processing is not available right now.

Error codes

Headers

  • Request-Id string required

    This request's id: your X-Request-Id when you sent one valid UUID, otherwise a new UUID. An error body repeats it as request_id.

    Format
    uuid
RequestPOST /v1/decide/batch
curl
curl https://api.komplai.dk/v1/decide/batch \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "states": [
      "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
      "Jeg klager over afslaget på min ansøgning om boligstøtte. Afgørelsen er forkert, og jeg har brug for svar hurtigt."
    ],
    "questions": {
      "category": {
        "type": "choice",
        "instructions": "Hvad handler henvendelsen om?",
        "criteria": {
          "aktindsigt": "Borgeren beder om kopi af dokumenter eller aktindsigt",
          "klage": "Borgeren klager over en afgørelse",
          "andet": "Noget andet"
        }
      },
      "urgency": {
        "type": "score",
        "instructions": "Hvor hurtigt skal henvendelsen besvares?",
        "criteria": [
          "Inden for den normale frist",
          "Inden for en uge",
          "Samme dag"
        ]
      },
      "personal_data": {
        "type": "noul",
        "instructions": "Indeholder teksten personoplysninger?",
        "criteria": {
          "true": "Ja, for eksempel et navn eller et CPR-nummer",
          "false": "Nej"
        }
      }
    }
  }'
PowerShell
$headers = @{
    Authorization = "Bearer $env:KOMPLAI_TOKEN"
}
$body = [ordered]@{
    states = @(
        'Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm',
        'Jeg klager over afslaget på min ansøgning om boligstøtte. Afgørelsen er forkert, og jeg har brug for svar hurtigt.'
    )
    questions = [ordered]@{
        category = [ordered]@{
            type = 'choice'
            instructions = 'Hvad handler henvendelsen om?'
            criteria = [ordered]@{
                aktindsigt = 'Borgeren beder om kopi af dokumenter eller aktindsigt'
                klage = 'Borgeren klager over en afgørelse'
                andet = 'Noget andet'
            }
        }
        urgency = [ordered]@{
            type = 'score'
            instructions = 'Hvor hurtigt skal henvendelsen besvares?'
            criteria = @(
                'Inden for den normale frist',
                'Inden for en uge',
                'Samme dag'
            )
        }
        personal_data = [ordered]@{
            type = 'noul'
            instructions = 'Indeholder teksten personoplysninger?'
            criteria = [ordered]@{
                true = 'Ja, for eksempel et navn eller et CPR-nummer'
                false = 'Nej'
            }
        }
    }
} | ConvertTo-Json -Depth 100

$request = @{
    Method = 'Post'
    Uri = 'https://api.komplai.dk/v1/decide/batch'
    Headers = $headers
    ContentType = 'application/json; charset=utf-8'
    Body = $body
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100
Python
import os

import requests

response = requests.post(
    "https://api.komplai.dk/v1/decide/batch",
    headers={
        "Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
    },
    json={
        "states": [
            "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
            "Jeg klager over afslaget på min ansøgning om boligstøtte. Afgørelsen er forkert, og jeg har brug for svar hurtigt.",
        ],
        "questions": {
            "category": {
                "type": "choice",
                "instructions": "Hvad handler henvendelsen om?",
                "criteria": {
                    "aktindsigt": "Borgeren beder om kopi af dokumenter eller aktindsigt",
                    "klage": "Borgeren klager over en afgørelse",
                    "andet": "Noget andet",
                },
            },
            "urgency": {
                "type": "score",
                "instructions": "Hvor hurtigt skal henvendelsen besvares?",
                "criteria": [
                    "Inden for den normale frist",
                    "Inden for en uge",
                    "Samme dag",
                ],
            },
            "personal_data": {
                "type": "noul",
                "instructions": "Indeholder teksten personoplysninger?",
                "criteria": {
                    "true": "Ja, for eksempel et navn eller et CPR-nummer",
                    "false": "Nej",
                },
            },
        },
    },
    timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())
JavaScript
const response = await fetch("https://api.komplai.dk/v1/decide/batch", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    states: [
      "Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm",
      "Jeg klager over afslaget på min ansøgning om boligstøtte. Afgørelsen er forkert, og jeg har brug for svar hurtigt.",
    ],
    questions: {
      category: {
        type: "choice",
        instructions: "Hvad handler henvendelsen om?",
        criteria: {
          aktindsigt: "Borgeren beder om kopi af dokumenter eller aktindsigt",
          klage: "Borgeren klager over en afgørelse",
          andet: "Noget andet",
        },
      },
      urgency: {
        type: "score",
        instructions: "Hvor hurtigt skal henvendelsen besvares?",
        criteria: [
          "Inden for den normale frist",
          "Inden for en uge",
          "Samme dag",
        ],
      },
      personal_data: {
        type: "noul",
        instructions: "Indeholder teksten personoplysninger?",
        criteria: {
          true: "Ja, for eksempel et navn eller et CPR-nummer",
          false: "Nej",
        },
      },
    },
  }),
});

console.log(response.status, response.headers.get("Request-Id"));
console.log(await response.json());
C#
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(330) };
using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.komplai.dk/v1/decide/batch");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));
request.Content = new StringContent(@"{
  ""states"": [
    ""Hej. Jeg vil gerne have en kopi af min ansøgning om byggetilladelse fra marts. Venlig hilsen Mette Kjærgaard Holm"",
    ""Jeg klager over afslaget på min ansøgning om boligstøtte. Afgørelsen er forkert, og jeg har brug for svar hurtigt.""
  ],
  ""questions"": {
    ""category"": {
      ""type"": ""choice"",
      ""instructions"": ""Hvad handler henvendelsen om?"",
      ""criteria"": {
        ""aktindsigt"": ""Borgeren beder om kopi af dokumenter eller aktindsigt"",
        ""klage"": ""Borgeren klager over en afgørelse"",
        ""andet"": ""Noget andet""
      }
    },
    ""urgency"": {
      ""type"": ""score"",
      ""instructions"": ""Hvor hurtigt skal henvendelsen besvares?"",
      ""criteria"": [
        ""Inden for den normale frist"",
        ""Inden for en uge"",
        ""Samme dag""
      ]
    },
    ""personal_data"": {
      ""type"": ""noul"",
      ""instructions"": ""Indeholder teksten personoplysninger?"",
      ""criteria"": {
        ""true"": ""Ja, for eksempel et navn eller et CPR-nummer"",
        ""false"": ""Nej""
      }
    }
  }
}", Encoding.UTF8, "application/json");

using var response = await client.SendAsync(request);
Console.WriteLine((int)response.StatusCode);
if (response.Headers.TryGetValues("Request-Id", out var requestId))
{
    Console.WriteLine(string.Join(", ", requestId));
}
Console.WriteLine(await response.Content.ReadAsStringAsync());

Set the environment variable KOMPLAI_TOKEN to your key first.

Response
200 OK
{
  "model": "convaiinnovations/laya/multilingual",
  "results": [
    {
      "answers": {
        "category": {
          "type": "choice",
          "choice": "aktindsigt",
          "probabilities": {
            "aktindsigt": 0.91,
            "klage": 0.03,
            "andet": 0.06
          },
          "confidence": 0.672,
          "action": {
            "act_probability": 0.88
          }
        },
        "urgency": {
          "type": "score",
          "score": 0.32,
          "max": 2,
          "probabilities": [0.72, 0.24, 0.04],
          "confidence": 0.356
        },
        "personal_data": {
          "type": "noul",
          "noul": 0.97,
          "probabilities": {
            "true": 0.97,
            "false": 0.03
          },
          "confidence": 0.806
        }
      },
      "usage": {
        "input_tokens": 118,
        "output_tokens": 0
      }
    },
    {
      "answers": {
        "category": {
          "type": "choice",
          "choice": "klage",
          "probabilities": {
            "aktindsigt": 0.08,
            "klage": 0.86,
            "andet": 0.06
          },
          "confidence": 0.544,
          "action": {
            "act_probability": 0.79
          }
        },
        "urgency": {
          "type": "score",
          "score": 1.15,
          "max": 2,
          "probabilities": [0.15, 0.55, 0.3],
          "confidence": 0.113
        },
        "personal_data": {
          "type": "noul",
          "noul": 0.12,
          "probabilities": {
            "true": 0.12,
            "false": 0.88
          },
          "confidence": 0.471
        }
      },
      "usage": {
        "input_tokens": 112,
        "output_tokens": 0
      }
    }
  ],
  "usage": {
    "input_tokens": 230,
    "output_tokens": 0
  },
  "latency_ms": 52
}
400 Bad Request
{
  "error": "invalid_input",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/invalid_input"
}
401 Unauthorized
{
  "error": "api_key_required",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/api_key_required"
}
403 Forbidden
{
  "error": "integration_not_permitted",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/integration_not_permitted"
}
404 Not Found
{
  "error": "model_not_enabled",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/model_not_enabled"
}
409 Conflict
{
  "error": "model_not_enabled",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/model_not_enabled"
}
413 Content Too Large
{
  "error": "Payload Too Large",
  "statusCode": 413,
  "code": "FST_ERR_CTP_BODY_TOO_LARGE",
  "message": "Request body is too large",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/payload-too-large"
}
415 Unsupported Media Type
{
  "error": "Unsupported Media Type",
  "statusCode": 415,
  "code": "FST_ERR_CTP_INVALID_MEDIA_TYPE",
  "message": "Unsupported Media Type",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/unsupported-media-type"
}
429 Too Many Requests
{
  "error": "rate_limited",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/rate_limited"
}
502 Bad Gateway
{
  "error": "service_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}
503 Service Unavailable
{
  "error": "service_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}
komplaidevelopers
Contact us

Search the documentation

Use the arrow keys to choose and Enter to open.