Skip to content

API reference

Coding API Beta

Beta: in use, and details can still change.

Account, models and streamed completions for coding clients. Beta. Needs a personal key with coding:read or coding:complete; an organisation integration key gets 403 integration_not_permitted.

Base URL
https://api.komplai.dk

Read the coding account Beta

GET /v1/coding/account

Your organisation, the current terms as contract, where a coding call's data goes, the organisation's monthly AI spending cap and this month's use (in balance, a name kept for installed clients), the default model and the coding models with the provider's prices. Read it before the first completion and whenever a completion answers 409 terms_changed, and show the terms to the person before they connect. It sends no text and runs no model. Needs a personal key with coding:read.

Scopes
coding:read
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.

Responses

200 OK

Your organisation, the current terms (contract) and data terms, the monthly AI spending cap and this month's use (balance), and the coding models with their prices.

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

  • id string required

    The organisation's id.

    Format
    uuid
  • name string required

    The organisation's name.

  • contract string required

    The current terms: provider, region, terms, data mode, agreement and the coding models with their prices, as one SHA-256 value. Send it as X-Komplai-Contract on every completion; it changes when any of them changes.

    Pattern
    ^[0-9a-f]{64}$
  • balance object required

    The organisation's monthly AI spending cap and how much of it is used this month. The field keeps its name for installed clients; it is a ceiling, not money held on account. When the effective limit is reached, calls stop; the API never moves to another model.

    Child fields (11)
    • budgetKind string

      pilot while komplai pays for a pilot's AI usage from one total allowance that never renews. Missing for a monthly cap.

      One of
      monthly pilot
    • periodStart string required nullable

      When the current month (or the pilot) began; null without a cap.

      Format
      date-time
    • periodEnd string required nullable

      When the current month ends; null for a pilot or without a cap.

      Format
      date-time
    • packageDkk integer required nullable

      The agreed monthly AI spending cap in whole kroner (for a pilot, its total allowance); null without one. The name is kept for installed clients.

    • budgetMicros integer required

      The agreed cap, in millionths of a krone (1000000 is one krone).

      Value
      at least 0
    • spentMicros integer required

      Usage settled so far this month, in millionths of a krone (1000000 is one krone).

      Value
      at least 0
    • reservedMicros integer required

      Usage held for calls still running, in millionths of a krone (1000000 is one krone).

      Value
      at least 0
    • availableMicros integer required

      What is left below the effective limit this month, never below 0, in millionths of a krone (1000000 is one krone).

      Value
      at least 0
    • active boolean required

      Whether the cap applies to the current month.

    • organisationLimitMicros integer required nullable

      The organisation's own lower limit, set by its administrator, in millionths of a krone; null without one.

    • limitMicros integer required

      The effective limit: the agreed cap, or the organisation's own limit when that is lower, in millionths of a krone (1000000 is one krone).

      Value
      at least 0
  • defaultModel string required nullable

    The organisation's default coding model; null when its default is not a coding model.

  • data object required

    Where a coding call's data goes and how it is kept, in Danish, as the coding clients show it to the person before they connect.

    Child fields (10)
    • recipients string required
    • region string required
    • training string required

      The provider's terms on training.

    • retention string required

      The provider's terms on retention.

    • source string required

      The provider's own page with the terms.

      Format
      uri
    • checkedAt string required

      When komplai last checked the terms.

      Format
      date
    • version string required
    • mode string required

      synthetic: use test data only. personal: personal data under the organisation's agreement.

      One of
      synthetic personal
    • accounting string required
    • platformStorage string required
  • credential object required

    The key that made this call.

    Child fields (3)
    • id string required
      Format
      uuid
    • scopes string[] required
    • expiresAt string required
      Format
      date-time
  • models object[] required

    The models a coding client may use.

    Child fields (14)
    • id string required

      The value for model in POST /v1/coding/chat/completions.

    • name string required
    • object string required
      One of
      model
    • owned_by string required
      One of
      komplai
    • context_length integer required

      The model's context in tokens: input and output together.

    • max_output_tokens integer required

      The most max_tokens the model takes.

    • capabilities object required
      Child fields (1)
      • function_calling boolean required
        One of
        true
    • reasoning_efforts string[] required

      The reasoning_effort values the model takes; empty when it takes none.

    • pricing object required

      The provider's prices, which usage is metered at and counted towards the organisation's monthly AI spending cap.

      Child fields (4)
      • currency string required
        One of
        DKK
      • prompt string required

        The provider's price per input token in DKK, as a decimal string.

      • completion string required

        The provider's price per output (reasoning included) token in DKK, as a decimal string.

      • input_cache_read string required

        The provider's price per cached input token in DKK, as a decimal string.

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.
  • coding_not_enabled Coding is not enabled for the organisation, its Chat does not run in komplai's EU cloud with an approved setup, or the key's person is not assigned Chat.

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.

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
RequestGET /v1/coding/account
curl
curl https://api.komplai.dk/v1/coding/account \
  -H "Authorization: Bearer $KOMPLAI_TOKEN"
PowerShell
$headers = @{
    Authorization = "Bearer $env:KOMPLAI_TOKEN"
}

$request = @{
    Method = 'Get'
    Uri = 'https://api.komplai.dk/v1/coding/account'
    Headers = $headers
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100
Python
import os

import requests

response = requests.get(
    "https://api.komplai.dk/v1/coding/account",
    headers={
        "Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
    },
    timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())
JavaScript
const response = await fetch("https://api.komplai.dk/v1/coding/account", {
  headers: {
    Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
  },
});

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 var client = new HttpClient { Timeout = TimeSpan.FromSeconds(330) };
using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.komplai.dk/v1/coding/account");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));

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
{
  "id": "2e7c4b9a-5d1f-4a3e-8b6c-9f0d1e2a3b4c",
  "name": "Eksempel Kommune",
  "contract": "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0",
  "balance": {
    "periodStart": "2026-10-01T00:00:00.000Z",
    "periodEnd": "2026-11-01T00:00:00.000Z",
    "packageDkk": 2500,
    "budgetMicros": 2500000000,
    "spentMicros": 412350000,
    "reservedMicros": 1200000,
    "availableMicros": 2086450000,
    "active": true,
    "organisationLimitMicros": null,
    "limitMicros": 2500000000
  },
  "defaultModel": "mistral-small-3.2-24b-instruct-2506",
  "data": {
    "recipients": "komplai → EU-cloud",
    "region": "komplais API: Hetzner, Tyskland. Model: komplais EU-cloud, EU · Frankrig.",
    "training": "komplais EU-cloud bruger ikke input, prompts eller svar til at træne, genoptræne eller forbedre grundmodellerne.",
    "retention": "Prompt- og svarindhold gemmes som udgangspunkt ikke. Midlertidig, projektisoleret cache af mellemresultater er automatisk og kan ikke fravælges. Ved særlige fejlfindings- eller sikkerhedshændelser, herunder undersøgelser af HTTP 500-fejl, kan hele forespørgslen gemmes i op til to uger. Aggregerede, anonymiserede forbrugsdata kan gemmes i op til seks måneder.",
    "source": "https://developers.komplai.dk/data-processing",
    "checkedAt": "2026-10-13",
    "version": "eu-cloud-2026-10-13",
    "mode": "synthetic",
    "accounting": "Forbruget måles til udbyderens pris i DKK og tæller med i organisationens månedlige loft for AI-forbrug. Cachet input har sin egen pris, hvor udbyderen har en. Ræsonnement tæller som outputtokens. Når loftet eller din personlige grænse er nået, stopper kaldene. Der skiftes aldrig automatisk til en anden model.",
    "platformStorage": "komplai gemmer forbrugs- og adgangsmetadata til regnskab og revision. Kode-API'et gemmer ikke prompts, svar eller værktøjsresultater. Se organisationens aftale for metadataenes slettefrist."
  },
  "models": [
    {
      "id": "mistral-small-3.2-24b-instruct-2506",
      "name": "Mistral Small 3.2 (24B)",
      "object": "model",
      "owned_by": "komplai",
      "context_length": 128000,
      "max_output_tokens": 32768,
      "capabilities": {
        "function_calling": true
      },
      "reasoning_efforts": [],
      "pricing": {
        "currency": "DKK",
        "prompt": "0.000001119",
        "completion": "0.000002611",
        "input_cache_read": "0.000001119"
      }
    },
    {
      "id": "qwen3.5-397b-a17b",
      "name": "Qwen3.5 (397B-A17B)",
      "object": "model",
      "owned_by": "komplai",
      "context_length": 250000,
      "max_output_tokens": 16384,
      "capabilities": {
        "function_calling": true
      },
      "reasoning_efforts": ["none", "low", "medium", "high"],
      "pricing": {
        "currency": "DKK",
        "prompt": "0.000004476",
        "completion": "0.000026856",
        "input_cache_read": "0.000004476"
      }
    }
  ],
  "credential": {
    "id": "a4b6c8d0-1e3f-4a5b-9c7d-2e4f6a8b0c1d",
    "scopes": ["coding:read", "coding:complete"],
    "expiresAt": "2026-11-19T08:00:00.000Z"
  }
}
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"
}
429 Too Many Requests
{
  "error": "rate_limited",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/rate_limited"
}
503 Service Unavailable
{
  "error": "chat_cloud_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/chat_cloud_unavailable"
}

List the coding models Beta

GET /v1/coding/models

The models a coding client may use, with their limits and the provider's prices, in the OpenAI list shape, and the account without its models. Needs a personal key with coding:read.

Scopes
coding:read
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.

Responses

200 OK

The coding models with their limits and prices in data, and the account without its models in account.

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

  • object string required
    One of
    list
  • data object[] required
    Child fields (14)
    • id string required

      The value for model in POST /v1/coding/chat/completions.

    • name string required
    • object string required
      One of
      model
    • owned_by string required
      One of
      komplai
    • context_length integer required

      The model's context in tokens: input and output together.

    • max_output_tokens integer required

      The most max_tokens the model takes.

    • capabilities object required
      Child fields (1)
      • function_calling boolean required
        One of
        true
    • reasoning_efforts string[] required

      The reasoning_effort values the model takes; empty when it takes none.

    • pricing object required

      The provider's prices, which usage is metered at and counted towards the organisation's monthly AI spending cap.

      Child fields (4)
      • currency string required
        One of
        DKK
      • prompt string required

        The provider's price per input token in DKK, as a decimal string.

      • completion string required

        The provider's price per output (reasoning included) token in DKK, as a decimal string.

      • input_cache_read string required

        The provider's price per cached input token in DKK, as a decimal string.

  • account object required

    The same account as GET /v1/coding/account, without models.

    Child fields (31)
    • id string required

      The organisation's id.

      Format
      uuid
    • name string required

      The organisation's name.

    • contract string required

      The current terms: provider, region, terms, data mode, agreement and the coding models with their prices, as one SHA-256 value. Send it as X-Komplai-Contract on every completion; it changes when any of them changes.

      Pattern
      ^[0-9a-f]{64}$
    • balance object required

      The organisation's monthly AI spending cap and how much of it is used this month. The field keeps its name for installed clients; it is a ceiling, not money held on account. When the effective limit is reached, calls stop; the API never moves to another model.

      Child fields (11)
      • budgetKind string

        pilot while komplai pays for a pilot's AI usage from one total allowance that never renews. Missing for a monthly cap.

        One of
        monthly pilot
      • periodStart string required nullable

        When the current month (or the pilot) began; null without a cap.

        Format
        date-time
      • periodEnd string required nullable

        When the current month ends; null for a pilot or without a cap.

        Format
        date-time
      • packageDkk integer required nullable

        The agreed monthly AI spending cap in whole kroner (for a pilot, its total allowance); null without one. The name is kept for installed clients.

      • budgetMicros integer required

        The agreed cap, in millionths of a krone (1000000 is one krone).

        Value
        at least 0
      • spentMicros integer required

        Usage settled so far this month, in millionths of a krone (1000000 is one krone).

        Value
        at least 0
      • reservedMicros integer required

        Usage held for calls still running, in millionths of a krone (1000000 is one krone).

        Value
        at least 0
      • availableMicros integer required

        What is left below the effective limit this month, never below 0, in millionths of a krone (1000000 is one krone).

        Value
        at least 0
      • active boolean required

        Whether the cap applies to the current month.

      • organisationLimitMicros integer required nullable

        The organisation's own lower limit, set by its administrator, in millionths of a krone; null without one.

      • limitMicros integer required

        The effective limit: the agreed cap, or the organisation's own limit when that is lower, in millionths of a krone (1000000 is one krone).

        Value
        at least 0
    • defaultModel string required nullable

      The organisation's default coding model; null when its default is not a coding model.

    • data object required

      Where a coding call's data goes and how it is kept, in Danish, as the coding clients show it to the person before they connect.

      Child fields (10)
      • recipients string required
      • region string required
      • training string required

        The provider's terms on training.

      • retention string required

        The provider's terms on retention.

      • source string required

        The provider's own page with the terms.

        Format
        uri
      • checkedAt string required

        When komplai last checked the terms.

        Format
        date
      • version string required
      • mode string required

        synthetic: use test data only. personal: personal data under the organisation's agreement.

        One of
        synthetic personal
      • accounting string required
      • platformStorage string required
    • credential object required

      The key that made this call.

      Child fields (3)
      • id string required
        Format
        uuid
      • scopes string[] required
      • expiresAt string required
        Format
        date-time
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.
  • coding_not_enabled Coding is not enabled for the organisation, its Chat does not run in komplai's EU cloud with an approved setup, or the key's person is not assigned Chat.

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.

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
RequestGET /v1/coding/models
curl
curl https://api.komplai.dk/v1/coding/models \
  -H "Authorization: Bearer $KOMPLAI_TOKEN"
PowerShell
$headers = @{
    Authorization = "Bearer $env:KOMPLAI_TOKEN"
}

$request = @{
    Method = 'Get'
    Uri = 'https://api.komplai.dk/v1/coding/models'
    Headers = $headers
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100
Python
import os

import requests

response = requests.get(
    "https://api.komplai.dk/v1/coding/models",
    headers={
        "Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
    },
    timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())
JavaScript
const response = await fetch("https://api.komplai.dk/v1/coding/models", {
  headers: {
    Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
  },
});

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 var client = new HttpClient { Timeout = TimeSpan.FromSeconds(330) };
using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.komplai.dk/v1/coding/models");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));

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
{
  "object": "list",
  "data": [
    {
      "id": "mistral-small-3.2-24b-instruct-2506",
      "name": "Mistral Small 3.2 (24B)",
      "object": "model",
      "owned_by": "komplai",
      "context_length": 128000,
      "max_output_tokens": 32768,
      "capabilities": {
        "function_calling": true
      },
      "reasoning_efforts": [],
      "pricing": {
        "currency": "DKK",
        "prompt": "0.000001119",
        "completion": "0.000002611",
        "input_cache_read": "0.000001119"
      }
    },
    {
      "id": "qwen3.5-397b-a17b",
      "name": "Qwen3.5 (397B-A17B)",
      "object": "model",
      "owned_by": "komplai",
      "context_length": 250000,
      "max_output_tokens": 16384,
      "capabilities": {
        "function_calling": true
      },
      "reasoning_efforts": ["none", "low", "medium", "high"],
      "pricing": {
        "currency": "DKK",
        "prompt": "0.000004476",
        "completion": "0.000026856",
        "input_cache_read": "0.000004476"
      }
    }
  ],
  "account": {
    "id": "2e7c4b9a-5d1f-4a3e-8b6c-9f0d1e2a3b4c",
    "name": "Eksempel Kommune",
    "contract": "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0",
    "balance": {
      "periodStart": "2026-10-01T00:00:00.000Z",
      "periodEnd": "2026-11-01T00:00:00.000Z",
      "packageDkk": 2500,
      "budgetMicros": 2500000000,
      "spentMicros": 412350000,
      "reservedMicros": 1200000,
      "availableMicros": 2086450000,
      "active": true,
      "organisationLimitMicros": null,
      "limitMicros": 2500000000
    },
    "defaultModel": "mistral-small-3.2-24b-instruct-2506",
    "data": {
      "recipients": "komplai → EU-cloud",
      "region": "komplais API: Hetzner, Tyskland. Model: komplais EU-cloud, EU · Frankrig.",
      "training": "komplais EU-cloud bruger ikke input, prompts eller svar til at træne, genoptræne eller forbedre grundmodellerne.",
      "retention": "Prompt- og svarindhold gemmes som udgangspunkt ikke. Midlertidig, projektisoleret cache af mellemresultater er automatisk og kan ikke fravælges. Ved særlige fejlfindings- eller sikkerhedshændelser, herunder undersøgelser af HTTP 500-fejl, kan hele forespørgslen gemmes i op til to uger. Aggregerede, anonymiserede forbrugsdata kan gemmes i op til seks måneder.",
      "source": "https://developers.komplai.dk/data-processing",
      "checkedAt": "2026-10-13",
      "version": "eu-cloud-2026-10-13",
      "mode": "synthetic",
      "accounting": "Forbruget måles til udbyderens pris i DKK og tæller med i organisationens månedlige loft for AI-forbrug. Cachet input har sin egen pris, hvor udbyderen har en. Ræsonnement tæller som outputtokens. Når loftet eller din personlige grænse er nået, stopper kaldene. Der skiftes aldrig automatisk til en anden model.",
      "platformStorage": "komplai gemmer forbrugs- og adgangsmetadata til regnskab og revision. Kode-API'et gemmer ikke prompts, svar eller værktøjsresultater. Se organisationens aftale for metadataenes slettefrist."
    },
    "credential": {
      "id": "a4b6c8d0-1e3f-4a5b-9c7d-2e4f6a8b0c1d",
      "scopes": ["coding:read", "coding:complete"],
      "expiresAt": "2026-11-19T08:00:00.000Z"
    }
  }
}
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"
}
429 Too Many Requests
{
  "error": "rate_limited",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/rate_limited"
}
503 Service Unavailable
{
  "error": "chat_cloud_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/chat_cloud_unavailable"
}

Stream a coding completion Beta

POST /v1/coding/chat/completions

An OpenAI-compatible chat completion for coding clients, streamed as server-sent events, with text and function calls. komplai never runs a tool: the client runs it, asks the person where needed, and sends the result in the next request. The model runs in komplai's EU cloud on your organisation's approved route. Before the provider is called, the most the call can cost is reserved under the organisation's monthly AI spending cap; usage is metered at the provider's price, and calls stop when the cap, the organisation's own limit or your personal limit is reached. komplai stores no prompts, answers or tool results, only the call's metadata. Send X-Komplai-Contract with the current contract and X-Request-Id with a new UUID for each operation. Needs a personal key with coding:complete.

Scopes
coding:complete
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.

Parameters

Headers

  • X-Komplai-Contract string required

    contract from GET /v1/coding/account, which needs coding:read. When the terms changed since, the call answers 409 terms_changed: read the account again, show the new terms to the person, and send the new contract.

    Pattern
    ^[0-9a-f]{64}$
  • X-Request-Id string required

    A new UUID (version 4) for each new logical operation. Send the same id again only to retry an operation whose outcome you do not know: komplai then answers 409 duplicate_request instead of calling the provider a second time. Request-Id in the response repeats it.

    Pattern
    ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

Request body

  • model string required

    A model id from GET /v1/coding/models.

    Length
    1 to 200
  • messages object[] required
    Items
    1 to 512

    One of

    • System or user messageobject
      • role string required
        One of
        system user
      • content string | object[] required

        Text or a list of text parts.

        One of

        • string
          Length
          at most 1,000,000
        • object[]

          A list of text parts.

          Items
          at most 100
          • type string required
            One of
            text
          • text string required
            Length
            at most 1,000,000
    • Assistant messageobject
      • role string required
        One of
        assistant
      • content string | object[] required

        Text, a list of text parts, or null when the message only calls tools.

        One of

        • string
          Length
          at most 1,000,000
        • object[]

          A list of text parts.

          Items
          at most 100
          • type string required
            One of
            text
          • text string required
            Length
            at most 1,000,000
      • tool_calls object[]

        The functions the model asked the client to call, each with an id that is unique in the conversation.

        Items
        1 to 64
        Child fields (5)
        • id string required
          Pattern
          ^[a-zA-Z0-9_-]{1,128}$
        • type string required
          One of
          function
        • function object required
          Child fields (2)
          • name string required
            Pattern
            ^[a-zA-Z0-9_-]{1,128}$
          • arguments string required

            A JSON object as text.

            Length
            at most 1,000,000
      • reasoning_content string

        The model's earlier reasoning, sent back unchanged.

        Length
        at most 1,000,000
    • Tool messageobject
      • role string required
        One of
        tool
      • content string | object[] required

        The tool's result: text or a list of text parts.

        One of

        • string
          Length
          at most 1,000,000
        • object[]

          A list of text parts.

          Items
          at most 100
          • type string required
            One of
            text
          • text string required
            Length
            at most 1,000,000
      • tool_call_id string required

        The id of the tool call this message answers.

        Pattern
        ^[a-zA-Z0-9_-]{1,128}$
  • tools object[]

    The functions the model may call.

    Items
    at most 64
    Child fields (6)
    • type string required
      One of
      function
    • function object required
      Child fields (4)
      • name string required
        Pattern
        ^[a-zA-Z0-9_-]{1,128}$
      • description string
        Length
        at most 50,000
      • parameters object required

        A JSON Schema for the arguments.

        Can hold fields that are not listed here.

      • strict boolean
  • tool_choice string | object

    auto, none, required, or one function from tools by name.

    One of

    • string
      One of
      auto none required
    • object
      • type string required
        One of
        function
      • function object required
        Child fields (1)
        • name string required
          Pattern
          ^[a-zA-Z0-9_-]{1,128}$
  • parallel_tool_calls boolean
  • stream boolean required

    Always true: the answer is streamed as server-sent events.

    One of
    true
  • stream_options object

    Optional; usage is always included in the stream.

    Child fields (1)
    • include_usage boolean required
      One of
      true
  • max_tokens integer

    The most tokens the answer may have, within the model's max_output_tokens; the input and max_tokens together must fit its context (413 context_limit). Required unless you send max_completion_tokens instead: send exactly one of the two (400 invalid_coding_input otherwise).

    Value
    1 to 32,000
  • max_completion_tokens integer

    The same as max_tokens, for clients that use this name. Send exactly one of max_tokens and max_completion_tokens.

    Value
    1 to 32,000
  • temperature number
    Value
    0 to 2
  • top_p number
    Value
    0 to 1
  • frequency_penalty number
    Value
    -2 to 2
  • presence_penalty number
    Value
    -2 to 2
  • stop string | string[]

    Up to 4 stop sequences of at most 500 characters.

    One of

    • string
      Length
      at most 500
    • string[]
      Items
      at most 4
      Length of each item
      at most 500
  • reasoning_effort string

    One of the model's reasoning_efforts (400 reasoning_not_supported otherwise).

    One of
    none low medium high xhigh max

Responses

200 OK

Server-sent events (text/event-stream). Each data line is a chat.completion.chunk from the model, passed on after validation: text in choices[0].delta.content, reasoning in reasoning_content, function calls in tool_calls, and usage in the last chunk. data: [DONE] ends a complete answer. If the call fails after the stream began, the last event is data: {"error": {"message", "code", "request_id", "doc_url"}} without [DONE]; treat the outcome as unknown.

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

Bodytext/event-stream

string

400 Bad Request

The request was refused before processing.

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
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.
  • coding_not_enabled Coding is not enabled for the organisation, its Chat does not run in komplai's EU cloud with an approved setup, or the key's person is not assigned Chat.
  • 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.
  • ai_credit_not_granted No monthly AI spending cap is set up for this month, so eu-cloud cannot run.

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

  • terms_changed X-Komplai-Contract is not the current contract: the provider, its terms, the data mode, the agreement or the coding models and their prices changed.
  • duplicate_request This X-Request-Id was used before with this key, so nothing was sent to the model.
  • 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

  • context_limit The input and the requested output do not fit the model: max_tokens is over the model's limit, the input with max_tokens is over its context, or, in Redact, a part of the text does not fit even after it was asked again in halves down to 1,500 characters.
  • 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.
  • ai_credit_exhausted The organisation's monthly AI spending cap for EU cloud is reached, or its own lower limit, or on a pilot the pilot's total allowance. Local processing keeps working.
  • person_ai_credit_exhausted Your personal AI limit is reached (personal keys only).
  • upstream_rate_limited The coding model's provider refused the call for 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
  • Retry-After integer

    Seconds to wait before trying again (at most 60). Sent with rate_limited; upstream_rate_limited, ai_credit_exhausted and person_ai_credit_exhausted carry none.

    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

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
504 Gateway Timeout

The call timed out.

Error codes

  • timeout The model did not answer in time. The call reached the model, so its outcome is unknown.

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/coding/chat/completions
curl
curl https://api.komplai.dk/v1/coding/chat/completions \
  -N \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H 'X-Komplai-Contract: 86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0' \
  -H "X-Request-Id: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "mistral-small-3.2-24b-instruct-2506",
    "stream": true,
    "stream_options": {
      "include_usage": true
    },
    "max_tokens": 256,
    "messages": [
      {
        "role": "system",
        "content": "You are a careful coding assistant."
      },
      {
        "role": "user",
        "content": "What does this expression evaluate to: 1 + 1?"
      }
    ]
  }'
PowerShell
$headers = @{
    Authorization = "Bearer $env:KOMPLAI_TOKEN"
    'X-Komplai-Contract' = '86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0'
    'X-Request-Id' = [guid]::NewGuid().ToString()
}
$body = [ordered]@{
    model = 'mistral-small-3.2-24b-instruct-2506'
    stream = $true
    stream_options = [ordered]@{
        include_usage = $true
    }
    max_tokens = 256
    messages = @(
        [ordered]@{
            role = 'system'
            content = 'You are a careful coding assistant.'
        },
        [ordered]@{
            role = 'user'
            content = 'What does this expression evaluate to: 1 + 1?'
        }
    )
} | ConvertTo-Json -Depth 100

$request = @{
    Method = 'Post'
    Uri = 'https://api.komplai.dk/v1/coding/chat/completions'
    Headers = $headers
    ContentType = 'application/json; charset=utf-8'
    Body = $body
}
$response = Invoke-RestMethod @request
$response
Python
import os
import uuid

import requests

with requests.post(
    "https://api.komplai.dk/v1/coding/chat/completions",
    headers={
        "Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
        "X-Komplai-Contract": "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0",
        "X-Request-Id": str(uuid.uuid4()),
    },
    json={
        "model": "mistral-small-3.2-24b-instruct-2506",
        "stream": True,
        "stream_options": {
            "include_usage": True,
        },
        "max_tokens": 256,
        "messages": [
            {
                "role": "system",
                "content": "You are a careful coding assistant.",
            },
            {
                "role": "user",
                "content": "What does this expression evaluate to: 1 + 1?",
            },
        ],
    },
    stream=True,
    timeout=330,
) as response:
    print(response.status_code, response.headers.get("Request-Id"))
    for line in response.iter_lines(decode_unicode=True):
        if line:
            print(line)
JavaScript
const response = await fetch("https://api.komplai.dk/v1/coding/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
    "Content-Type": "application/json",
    "X-Komplai-Contract": "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0",
    "X-Request-Id": crypto.randomUUID(),
  },
  body: JSON.stringify({
    model: "mistral-small-3.2-24b-instruct-2506",
    stream: true,
    stream_options: {
      include_usage: true,
    },
    max_tokens: 256,
    messages: [
      {
        role: "system",
        content: "You are a careful coding assistant.",
      },
      {
        role: "user",
        content: "What does this expression evaluate to: 1 + 1?",
      },
    ],
  }),
});

console.log(response.status, response.headers.get("Request-Id"));
const decoder = new TextDecoder();
for await (const chunk of response.body) {
  process.stdout.write(decoder.decode(chunk, { stream: true }));
}
C#
using System;
using System.IO;
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/coding/chat/completions");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));
request.Headers.Add("X-Komplai-Contract", "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0");
request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString());
request.Content = new StringContent(@"{
  ""model"": ""mistral-small-3.2-24b-instruct-2506"",
  ""stream"": true,
  ""stream_options"": {
    ""include_usage"": true
  },
  ""max_tokens"": 256,
  ""messages"": [
    {
      ""role"": ""system"",
      ""content"": ""You are a careful coding assistant.""
    },
    {
      ""role"": ""user"",
      ""content"": ""What does this expression evaluate to: 1 + 1?""
    }
  ]
}", Encoding.UTF8, "application/json");

using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
Console.WriteLine((int)response.StatusCode);
if (response.Headers.TryGetValues("Request-Id", out var requestId))
{
    Console.WriteLine(string.Join(", ", requestId));
}
using var stream = await response.Content.ReadAsStreamAsync();
using var reader = new StreamReader(stream);
while (await reader.ReadLineAsync() is { } line)
{
    Console.WriteLine(line);
}

Set the environment variable KOMPLAI_TOKEN to your key first.

Response
200 OK
data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{"role":"assistant","content":"It evaluates to 2"},"finish_reason":null}]}

data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{"content":": the sum of 1 and 1."},"finish_reason":null}]}

data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":31,"completion_tokens":14}}

data: [DONE]
200 OK
data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"id":"call_7b2d","type":"function","function":{"name":"read_file","arguments":""}}]},"finish_reason":null}]}

data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"path\":\"README.md\"}"}}]},"finish_reason":null}]}

data: {"id":"chatcmpl-5f1e9d2c","object":"chat.completion.chunk","created":1792483200,"model":"mistral-small-3.2-24b-instruct-2506","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":58,"completion_tokens":18}}

data: [DONE]
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"
}
409 Conflict
{
  "error": "terms_changed",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/terms_changed"
}
413 Content Too Large
{
  "error": "context_limit",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/context_limit"
}
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": "coding_service_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/coding_service_unavailable"
}
503 Service Unavailable
{
  "error": "chat_cloud_unavailable",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/chat_cloud_unavailable"
}
504 Gateway Timeout
{
  "error": "timeout",
  "request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
  "doc_url": "https://developers.komplai.dk/errors/timeout"
}
komplaidevelopers
Contact us

Search the documentation

Use the arrow keys to choose and Enter to open.