Skip to content

Tools

Chat

The Chat API gives your own systems the models your organisation uses in Chat. POST /v1/chat/completions takes an OpenAI-compatible chat request with text messages and returns the whole answer as one chat.completion. You choose where the model runs: on komplai's local infrastructure, in komplai's EU cloud or through one of your organisation's own AI connections.

Before you start

Your first call

Without processing and model, the call runs where your organisation's Chat runs, with your default model there.

Shell
curl https://api.komplai.dk/v1/chat/completions \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [
      {"role": "system", "content": "Answer briefly."},
      {"role": "user", "content": "How long do I have to appeal a decision on housing benefit?"}
    ],
    "max_tokens": 256
  }'
JSON
{
  "id": "chatcmpl-8c1d5e3a-2f7b-4a9c-b6e0-3d4f5a6b7c8d",
  "object": "chat.completion",
  "created": 1792483200,
  "model": "qwen3.8-27b",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Usually four weeks from the day you received the decision. The deadline is in the decision's guidance on how to appeal."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 41, "completion_tokens": 33 }
}

The answer is in choices[0].message.content. finish_reason: "length" means the answer reached max_tokens and is incomplete.

Choose where the model runs

processing decides where the call runs. The same values work for GET /v1/models.

processingWhere the model runsAI usage
komplai-localkomplai's local infrastructure in Denmark, run by komplai. Data does not leave the EU. The queue is shared with other organisations, without priority. local is accepted too.No AI charge
eu-cloudkomplai's EU cloud in France. Data does not leave the EU. Needs EU processing approved for Chat in your organisation.Metered at the provider's price and counts towards the organisation's monthly AI spending cap
connection:<id>One of your organisation's own AI connections that its administrator has made available through the API.Your organisation's own agreement with the provider. It does not count towards the cap.
left outWhere your organisation's Chat runs: local infrastructure, or EU cloud when that is what your organisation's Chat uses.As for that processing

The API never moves a call to other processing or to another model, also not when the chosen one fails. A choice your organisation does not allow through the API answers processing_choice_not_allowed.

Administrators decide this in the hub under AI and processing: the Processing tab (/settings/processing) sets where each tool may process text through the API, and the Connections tab (/settings/ai, the AI connections page) adds connections and switches Can be used through the API on for each one.

Models

GET /v1/models lists the models your key may use at a processing, with their context, their output limit and the reasoning efforts they take. In the EU cloud each model also carries the provider's token rates in rates.

Shell
curl "https://api.komplai.dk/v1/models?processing=komplai-local" \
  -H "Authorization: Bearer $KOMPLAI_TOKEN"
JSON
{
  "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"]
    }
  ]
}
  • On local infrastructure the list holds the models your organisation has switched on, or every selectable model while it has switched on none. In the EU cloud it holds the models on your organisation's EU route. For a connection it holds the one model or router the connection names.
  • Send model with an id from the list at the same processing. Leave it out for your default there: the model you chose in the hub, else your organisation's default.
  • A model you may not use answers model_not_enabled. The API never picks another one.
  • reasoning_effort takes one of the model's reasoning_efforts; another value answers reasoning_not_enabled. More reasoning uses more of the output limit.
Shell
curl https://api.komplai.dk/v1/chat/completions \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "processing": "komplai-local",
    "model": "qwen3.8-27b",
    "reasoning_effort": "none",
    "max_tokens": 256,
    "messages": [
      {"role": "user", "content": "How long do I have to appeal a decision on housing benefit?"}
    ]
  }'

Use one of your organisation's connections

A connection is your organisation's own infrastructure, such as Azure OpenAI, or its own account with a provider such as Anthropic, OpenAI, Mistral or OpenRouter. It names one model or a router. Its value for processing is on the AI connections page, under Value for processing in the API; ask your administrator for it.

Shell
curl https://api.komplai.dk/v1/chat/completions \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "processing": "connection:6d3f9a2e-1b4c-4e7d-8a5f-0c2b9e4d7a31",
    "max_tokens": 256,
    "messages": [
      {"role": "user", "content": "How long do I have to appeal a decision on housing benefit?"}
    ]
  }'

The answer adds processing and requested_model. With a router such as openrouter/free, model is the model that actually answered and requested_model the router the connection names; komplai also records the answering model in your organisation's usage log.

  • Leave model out, or send the model the connection names.
  • reasoning_effort takes only none. A connection to Anthropic takes temperature up to 1 and no response_format other than text.
  • Where a connection processes data, who runs it and whether data stays in the EU/EEA is what your administrator stated for it on the AI connections page. The provider is not a komplai subprocessor.
  • With a free model, the provider may store and use what is sent. Use it for testing, synthetic data and ideas.
  • A connection id your organisation does not have answers connection_not_found. A connection your administrator has not made available through the API answers processing_choice_not_allowed on POST /v1/chat/completions, and GET /v1/models does not list it (connection_not_found). When the provider refuses the call, the code names the reason, such as connection_unauthorized or connection_payment_required.

Your own AI connections shows how an administrator adds one.

The monthly AI spending cap

Only calls to the EU cloud count towards the organisation's monthly AI spending cap. Local infrastructure and your organisation's own connections do not.

  • Before a call to the EU cloud, komplai reserves a conservative estimate of the input and the whole max_tokens. When the answer is in, the known usage is recorded and the rest released. A max_tokens that fits the task leaves room for other calls.
  • The cap applies across the organisation's apps, people and keys. An administrator can set a lower limit for the organisation and personal limits on the AI usage limits page (/settings/ai-budget).
  • When the cap or the organisation's own limit is reached, calls stop with ai_credit_exhausted; a reached personal limit answers person_ai_credit_exhausted. Retrying does not help until the cap starts again next month. Local processing keeps working.
  • Without a cap for the month, the EU cloud cannot run: ai_credit_not_granted.

The answer comes back whole

The Chat API does not stream. stream is always false, and stream: true answers 400 invalid_input, as do tools, images and files. For streamed answers with function calls, coding clients use Coding.

  • A request holds at most 32 messages and 80,000 UTF-16 code units of text. max_tokens defaults to 2,000 and may not exceed the model's own max_output_tokens (GET /v1/models); with the input it must also fit the model's context, otherwise context_limit.
  • The model has 120 seconds to answer. Give your HTTP client a slightly longer timeout, for example 150 seconds.
  • After timeout or a 502 service_unavailable, the call may have reached the model and used capacity. Do not send it again automatically, and turn off automatic retries of POST in your HTTP client or SDK.
  • eu_cloud_refused means komplai's EU cloud refused the call. Choose local processing or a connection, and send komplai the request_id.

Structured JSON

response_format asks for a JSON object (json_object) or JSON that follows your schema (json_schema). The answer is still text in choices[0].message.content: check finish_reason, parse it and validate it before you rely on it.

Request body
{
  "processing": "komplai-local",
  "model": "qwen3.8-27b",
  "max_tokens": 256,
  "messages": [
    {"role": "user", "content": "Answer in JSON. How long do I have to appeal a decision on housing benefit?"}
  ],
  "response_format": {
    "type": "json_schema",
    "json_schema": {
      "name": "appeal_deadline",
      "strict": true,
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "required": ["weeks", "source"],
        "properties": {
          "weeks": {"type": "integer"},
          "source": {"type": "string"}
        }
      }
    }
  }
}

The whole response_format may hold at most 32,768 bytes, 24 levels and 2,048 values, and a $ref must point inside the schema.

What is stored

Chat through the API stores no messages and no answers. komplai records the call's metadata: who called, when, which model and how many tokens. Each response has a Request-Id header; quote it when you ask komplai about a call.

Reference and errors

  • Chat reference: every field of GET /v1/models and POST /v1/chat/completions, with code samples and a console to try each call.
  • Errors: every code with what to do. Request limits are on Limits.
  • Where data is processed compares local infrastructure, the EU cloud and your own connections.
komplaidevelopers
Contact us

Search the documentation

Use the arrow keys to choose and Enter to open.