Chat API
Chat completions and model discovery on the organisation's approved processing. Needs a personal key with chat:complete; an organisation integration key gets 403 integration_not_permitted.
- Base URL
https://api.komplai.dk
List the permitted chat models
GET /v1/models
The models this key may use for POST /v1/chat/completions, with their context and output limits, the reasoning efforts they take and, in komplai's EU cloud, the provider's token rates. processing chooses which processing to list: komplai's local infrastructure, komplai's EU cloud or one of your organisation's own connections. It sends no text and runs no model. Needs a personal key with chat:complete.
- Scopes
chat:complete- Keys
- Personal key
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.
Response
Request-Id
Query parameters
Which processing to list. komplai-local: komplai's local infrastructure in Denmark, with no AI charge (local is accepted too). eu-cloud: komplai's EU cloud, when your organisation has EU processing approved for Chat; usage is metered at the provider's price and counts towards the organisation's monthly AI spending cap. connection:<id>: one of your organisation's own connections that its administrator has made available through the API, shown with its value on the hub's AI processing page; the organisation pays the provider itself, and the usage does not count towards the cap. Leave it out to list your organisation's Chat processing: local infrastructure, or EU cloud when that is what your organisation's Chat uses.
- Pattern
^(komplai-local|local|eu-cloud|connection:[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12})$
Responses
200 OK
The models this key may use at that processing. On local infrastructure: the models your organisation has switched on, or every selectable model while it has switched on none. In EU cloud: the models on your organisation's EU route, with their rates. For a connection: the one model or router it names. The list grants no access of its own.
Headers
Body
Child fields (14)
Only for komplai's EU cloud: the provider's prices, which usage is metered at and counted towards the organisation's monthly AI spending cap. Local infrastructure has no AI charge and no rates.
Child fields (5)
400 Bad Request
The request was refused before processing.
Error codes
invalid_inputThe request is not what the operation documents, for example invalid JSON, a field that is not listed or a value out of range.
Headers
401 Unauthorized
The key is missing or not valid.
Error codes
api_key_requiredNo Authorization: Bearer header with a komplai key.invalid_api_keyThe 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_tokenThe key was revoked or expired, or its access ended, while the request was admitted or processed.
Headers
403 Forbidden
The key may not do this, or the organisation's access does not cover it.
Error codes
integration_not_permittedAn organisation integration key cannot use this operation or this option.insufficient_scopeThe 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_retiredThe person behind a personal key has been removed from komplai.processing_not_enabledThe 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_choice_not_allowedThe 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
404 Not Found
Not found.
Error codes
connection_not_foundNo connection with this id is available to you through the API.
Headers
429 Too Many Requests
Refused for now. Wait the seconds in Retry-After before you try again.
Error codes
rate_limitedToo 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
503 Service Unavailable
Processing is not available right now.
Error codes
chat_cloud_unavailableThe organisation's EU cloud setup cannot be used right now.access_service_unavailableKeys and access could not be checked.
Headers
/v1/modelscurl https://api.komplai.dk/v1/models \
-H "Authorization: Bearer $KOMPLAI_TOKEN"$headers = @{
Authorization = "Bearer $env:KOMPLAI_TOKEN"
}
$request = @{
Method = 'Get'
Uri = 'https://api.komplai.dk/v1/models'
Headers = $headers
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100import os
import requests
response = requests.get(
"https://api.komplai.dk/v1/models",
headers={
"Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
},
timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())const response = await fetch("https://api.komplai.dk/v1/models", {
headers: {
Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
},
});
console.log(response.status, response.headers.get("Request-Id"));
console.log(await response.json());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/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.
{
"object": "list",
"data": [
{
"id": "qwen3.8-27b",
"object": "model",
"owned_by": "komplai",
"name": "Qwen3.8 27B",
"context_tokens": 32768,
"max_output_tokens": 4000,
"reasoning_efforts": ["none", "low", "medium", "high"]
},
{
"id": "qwen3.8-27b-q8",
"object": "model",
"owned_by": "komplai",
"name": "Qwen3.8 27B (Q8)",
"context_tokens": 32768,
"max_output_tokens": 4000,
"reasoning_efforts": ["none", "low", "medium", "high"]
}
]
}{
"object": "list",
"data": [
{
"id": "mistral-small-3.2-24b-instruct-2506",
"object": "model",
"owned_by": "komplai",
"name": "Mistral Small 3.2 (24B)",
"context_tokens": 128000,
"max_output_tokens": 32768,
"reasoning_efforts": ["none"],
"rates": {
"currency": "DKK",
"unit": "micro_dkk_per_million_tokens",
"input": 1119000,
"output": 2611000,
"cached_input": 1119000
}
},
{
"id": "qwen3.5-397b-a17b",
"object": "model",
"owned_by": "komplai",
"name": "Qwen3.5 (397B-A17B)",
"context_tokens": 250000,
"max_output_tokens": 16384,
"reasoning_efforts": ["none", "low", "medium", "high"],
"rates": {
"currency": "DKK",
"unit": "micro_dkk_per_million_tokens",
"input": 4476000,
"output": 26856000,
"cached_input": 4476000
}
}
]
}{
"object": "list",
"data": [
{
"id": "openrouter/free",
"object": "model",
"owned_by": "openrouter",
"name": "OpenRouter, gratis modeller",
"processing": "connection:6d3f9a2e-1b4c-4e7d-8a5f-0c2b9e4d7a31"
}
]
}{
"error": "invalid_input",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/invalid_input"
}{
"error": "api_key_required",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/api_key_required"
}{
"error": "integration_not_permitted",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/integration_not_permitted"
}{
"error": "connection_not_found",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/connection_not_found"
}{
"error": "rate_limited",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/rate_limited"
}{
"error": "chat_cloud_unavailable",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/chat_cloud_unavailable"
}Create a chat completion
POST /v1/chat/completions
An OpenAI-compatible chat completion with text only, returned whole (stream false). It runs where processing says: komplai's local infrastructure in Denmark, komplai's EU cloud when your organisation has it approved for Chat, or one of your organisation's own connections; without processing, where your organisation's Chat runs. The API never moves a call to other processing or another model, also not when the chosen one fails. At most 32 messages and 80,000 UTF-16 code units of text; the model has 120 seconds to answer. In EU cloud, usage is metered at the provider's price and counts towards the organisation's monthly AI spending cap; the call stops when the cap, the organisation's own limit or your personal limit is reached. Needs a personal key with chat:complete.
- Scopes
chat:complete- Keys
- Personal key
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.
Response
Request-Id
Request body
The conversation, oldest first: at most 32 messages and 80,000 UTF-16 code units of content together.
- Items
- 1 to 32
A model id from GET /v1/models at the same processing, with at least one character that is not white space. Leave it out for the default there: the model you chose in the hub, else your organisation's default. A model you may not use answers 409 model_not_enabled; the API never picks another one. For a connection, leave it out or send the model the connection names.
- Pattern
\S- Length
- 1 to 200
Where the model runs. komplai-local: komplai's local infrastructure in Denmark, with no AI charge (local is accepted too). eu-cloud: komplai's EU cloud, when your organisation has EU processing approved for Chat; usage is metered at the provider's price and counts towards the organisation's monthly AI spending cap. connection:<id>: one of your organisation's own connections that its administrator has made available through the API, shown with its value on the hub's AI processing page; the organisation pays the provider itself, and the usage does not count towards the cap. Leave it out for your organisation's Chat processing. The API never moves a call to other processing, also not when the chosen one fails.
- Pattern
^(komplai-local|local|eu-cloud|connection:[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12})$
Leave it out for plain text. json_object asks for a JSON object; json_schema asks for JSON that follows your schema. A connection to Anthropic takes only text.
One of
JSON schemaobject
Child fields (4)
Responses
200 OK
The whole answer, as an OpenAI-compatible chat.completion. Nothing is stored but the call's metadata (who, when, model, tokens).
Headers
Body
- Items
- 1 to 1
Child fields (4)
400 Bad Request
The request was refused before processing.
Error codes
invalid_inputThe request is not what the operation documents, for example invalid JSON, a field that is not listed or a value out of range.
Headers
401 Unauthorized
The key is missing or not valid.
Error codes
api_key_requiredNo Authorization: Bearer header with a komplai key.invalid_api_keyThe 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_tokenThe key was revoked or expired, or its access ended, while the request was admitted or processed.
Headers
403 Forbidden
The key may not do this, or the organisation's access does not cover it.
Error codes
integration_not_permittedAn organisation integration key cannot use this operation or this option.insufficient_scopeThe 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_retiredThe person behind a personal key has been removed from komplai.app_not_assignedThe key's person lost the app or their membership while the request was admitted.processing_not_enabledThe 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_approvedThe organisation's processing approval for the app is missing or was withdrawn.processing_choice_not_allowedThe 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_grantedNo monthly AI spending cap is set up for this month, so eu-cloud cannot run.
Headers
404 Not Found
Not found.
Error codes
connection_not_foundNo connection with this id is available to you through the API.model_not_enabledThe model is not one you may use at this processing, or it is not offered there right now.
Headers
409 Conflict
Conflict with the current state.
Error codes
model_not_enabledThe model is not one you may use at this processing, or it is not offered there right now.reasoning_not_enabledThe model does not take this reasoning_effort, or one of the organisation's own connections was sent one other than none.connection_model_unavailableThe provider behind the connection does not know the model the connection names.
Headers
413 Content Too Large
Too large.
Error codes
context_limitThe 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 LargeFastify's reason phrase: the body is over the operation's byte limit.
Headers
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 TypeFastify's reason phrase: the body has no Content-Type, or one the API does not read, such as XML or form data.
Headers
429 Too Many Requests
Refused for now. Wait the seconds in Retry-After before you try again.
Error codes
rate_limitedToo 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_exhaustedThe 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_exhaustedYour personal AI limit is reached (personal keys only).connection_rate_limitedThe provider behind the connection refused the call for now.
Headers
502 Bad Gateway
A processing service failed. No partial result is returned.
Error codes
service_unavailableThe model failed or could not be reached, or local infrastructure is not set up for this call right now.invalid_responseThe model's answer failed validation, so nothing was returned.eu_cloud_refusedkomplai's EU cloud refused the call, so the model did not answer it.connection_unauthorizedThe provider refused the connection's key.connection_payment_requiredThe provider behind the connection wants payment on the organisation's account.connection_request_refusedThe provider behind the connection refused the request, for example a value it does not take.connection_failedThe provider behind one of the organisation's own connections could not be reached or failed.
Headers
503 Service Unavailable
Processing is not available right now.
Error codes
service_unavailableThe model failed or could not be reached, or local infrastructure is not set up for this call right now.chat_cloud_unavailableThe organisation's EU cloud setup cannot be used right now.connection_unavailableThe connection cannot be used: its key cannot be read or its address is refused.access_service_unavailableKeys and access could not be checked.
Headers
504 Gateway Timeout
The call timed out.
Error codes
timeoutThe model did not answer in time. The call reached the model, so its outcome is unknown.
Headers
/v1/chat/completionscurl https://api.komplai.dk/v1/chat/completions \
-H "Authorization: Bearer $KOMPLAI_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"messages": [
{
"role": "system",
"content": "Svar kort og på dansk."
},
{
"role": "user",
"content": "Hvor lang tid har jeg til at klage over en afgørelse om boligstøtte?"
}
],
"max_tokens": 256
}'$headers = @{
Authorization = "Bearer $env:KOMPLAI_TOKEN"
}
$body = [ordered]@{
messages = @(
[ordered]@{
role = 'system'
content = 'Svar kort og på dansk.'
},
[ordered]@{
role = 'user'
content = 'Hvor lang tid har jeg til at klage over en afgørelse om boligstøtte?'
}
)
max_tokens = 256
} | ConvertTo-Json -Depth 100
$request = @{
Method = 'Post'
Uri = 'https://api.komplai.dk/v1/chat/completions'
Headers = $headers
ContentType = 'application/json; charset=utf-8'
Body = $body
}
$response = Invoke-RestMethod @request
$response | ConvertTo-Json -Depth 100import os
import requests
response = requests.post(
"https://api.komplai.dk/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['KOMPLAI_TOKEN']}",
},
json={
"messages": [
{
"role": "system",
"content": "Svar kort og på dansk.",
},
{
"role": "user",
"content": "Hvor lang tid har jeg til at klage over en afgørelse om boligstøtte?",
},
],
"max_tokens": 256,
},
timeout=330,
)
print(response.status_code, response.headers.get("Request-Id"))
print(response.json())const response = await fetch("https://api.komplai.dk/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KOMPLAI_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
messages: [
{
role: "system",
content: "Svar kort og på dansk.",
},
{
role: "user",
content: "Hvor lang tid har jeg til at klage over en afgørelse om boligstøtte?",
},
],
max_tokens: 256,
}),
});
console.log(response.status, response.headers.get("Request-Id"));
console.log(await response.json());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/chat/completions");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("KOMPLAI_TOKEN"));
request.Content = new StringContent(@"{
""messages"": [
{
""role"": ""system"",
""content"": ""Svar kort og på dansk.""
},
{
""role"": ""user"",
""content"": ""Hvor lang tid har jeg til at klage over en afgørelse om boligstøtte?""
}
],
""max_tokens"": 256
}", 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.
{
"id": "chatcmpl-8c1d5e3a-2f7b-4a9c-b6e0-3d4f5a6b7c8d",
"object": "chat.completion",
"created": 1792483200,
"model": "qwen3.8-27b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Du har normalt 4 uger til at klage, regnet fra den dag du fik afgørelsen. Fristen står i afgørelsens klagevejledning."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 41,
"completion_tokens": 33
}
}{
"id": "chatcmpl-8c1d5e3a-2f7b-4a9c-b6e0-3d4f5a6b7c8d",
"object": "chat.completion",
"created": 1792483200,
"model": "qwen3.8-27b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Du har normalt 4 uger til at klage, regnet fra den dag du fik afgørelsen. Fristen står i afgørelsens klagevejledning."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 27,
"completion_tokens": 33
}
}{
"id": "chatcmpl-8c1d5e3a-2f7b-4a9c-b6e0-3d4f5a6b7c8d",
"object": "chat.completion",
"created": 1792483200,
"model": "qwen3.8-27b",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "{\"uger\":4,\"kilde\":\"Afgørelsens klagevejledning\"}"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 64,
"completion_tokens": 15
}
}{
"id": "chatcmpl-8c1d5e3a-2f7b-4a9c-b6e0-3d4f5a6b7c8d",
"object": "chat.completion",
"created": 1792483200,
"model": "meta-llama/llama-3.3-70b-instruct:free",
"requested_model": "openrouter/free",
"processing": "connection:6d3f9a2e-1b4c-4e7d-8a5f-0c2b9e4d7a31",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Du har normalt 4 uger til at klage, regnet fra den dag du fik afgørelsen. Fristen står i afgørelsens klagevejledning."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 29,
"completion_tokens": 35
}
}{
"error": "invalid_input",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/invalid_input"
}{
"error": "api_key_required",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/api_key_required"
}{
"error": "integration_not_permitted",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/integration_not_permitted"
}{
"error": "connection_not_found",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/connection_not_found"
}{
"error": "model_not_enabled",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/model_not_enabled"
}{
"error": "context_limit",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/context_limit"
}{
"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"
}{
"error": "rate_limited",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/rate_limited"
}{
"error": "service_unavailable",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}{
"error": "service_unavailable",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/service_unavailable"
}{
"error": "timeout",
"request_id": "0f8e2c4a-6b1d-4e3f-9a7c-5d2b8e1f4a60",
"doc_url": "https://developers.komplai.dk/errors/timeout"
}