Skip to content

Tools

Coding Beta

Beta: in use, and details can still change.

Coding is in Beta. It gives coding clients an OpenAI-compatible chat completion, streamed as server-sent events, with text, reasoning and function calls. komplai never runs a tool: the client runs it on your machine, asks you where needed and sends the result back in the next request.

Coding uses your organisation's Chat access and approved models. The model runs in komplai's EU cloud, and usage counts towards the organisation's monthly AI spending cap. Coding is not a separate app licence.

Before you start

  • Coding is enabled for your organisation, its Chat runs in komplai's EU cloud with an approved setup, and you are assigned Chat. Otherwise every call answers 403 coding_not_enabled. A completion also needs a monthly AI spending cap for the month; without one it answers 403 ai_credit_not_granted.
  • You have a personal API key (kp_live_...) with the scopes coding:read and coding:complete. komplai's coding client creates one when you sign in with your organisation, valid for 30 days; Coding client shows how. You can also create a key with both scopes on the hub's API keys page at hub.komplai.dk/api-access. An organisation integration key (kp_org_...) gets 403 integration_not_permitted.

The three calls

CallScopeWhat it does
GET /v1/coding/accountcoding:readYour organisation, the current terms as contract, where a call's data goes, the monthly AI spending cap and this month's use, the default model and the coding models
GET /v1/coding/modelscoding:readThe coding models with their limits, in the OpenAI list shape
POST /v1/coding/chat/completionscoding:completeA streamed completion
  1. Read the account and show its terms to the person before they connect.
  2. Pick a model from the account's models or from GET /v1/coding/models.
  3. Stream a completion with the current contract in X-Komplai-Contract and a new UUID in X-Request-Id.

Read the account

Shell
curl https://api.komplai.dk/v1/coding/account \
  -H "Authorization: Bearer $KOMPLAI_TOKEN"

The answer, shortened:

JSON
{
  "id": "2e7c4b9a-5d1f-4a3e-8b6c-9f0d1e2a3b4c",
  "name": "Eksempel Kommune",
  "contract": "86fb88e41acf1ec181a16eaf5d7725059473b626b7d4289ee1b9c3b2aaed45b0",
  "defaultModel": "mistral-small-3.2-24b-instruct-2506",
  "data": {
    "recipients": "komplai → EU-cloud",
    "region": "komplais API: Hetzner, Tyskland. Model: komplais EU-cloud, EU · Frankrig.",
    "checkedAt": "2026-10-13"
  },
  "models": [
    {
      "id": "mistral-small-3.2-24b-instruct-2506",
      "name": "Mistral Small 3.2 (24B)",
      "context_length": 128000,
      "max_output_tokens": 32768,
      "capabilities": { "function_calling": true },
      "reasoning_efforts": []
    }
  ],
  "credential": {
    "scopes": ["coding:read", "coding:complete"],
    "expiresAt": "2026-11-19T08:00:00.000Z"
  }
}
  • contract identifies the current terms: the provider and its terms, the data mode, your organisation's agreement, and the coding models with their prices. Send it with every request to POST /v1/coding/chat/completions.
  • data states who receives a call's data, where it is processed, the provider's terms for training and retention, how usage is accounted, what komplai stores, the source of the provider's terms and when komplai checked them. Show these terms to the person before they connect.
  • balance holds the monthly AI spending cap and this month's use, reserved amount and what is left. Each model in models carries the provider's prices.
  • credential names the key's scopes and when it expires.

Stream a completion

Put the contract in a variable, then send the request. -N makes curl print each event as it arrives.

Shell
KOMPLAI_CODING_CONTRACT=$(curl -s https://api.komplai.dk/v1/coding/account \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" | jq -r .contract)

curl -N https://api.komplai.dk/v1/coding/chat/completions \
  -H "Authorization: Bearer $KOMPLAI_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Komplai-Contract: $KOMPLAI_CODING_CONTRACT" \
  -H "X-Request-Id: $(uuidgen)" \
  -d '{
    "model": "mistral-small-3.2-24b-instruct-2506",
    "stream": 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?"}
    ]
  }'
text/event-stream
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]

Each data line is a chat.completion.chunk from the model, passed on after komplai has checked it: 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.

A stream without [DONE] is not a complete answer

If the call fails after the stream began, the last event is data: {"error": {"message": ..., "code": ..., "request_id": ..., "doc_url": ...}} and no [DONE] follows. Treat the outcome as unknown, as you would a stream that stops early.

The request must have:

  • model: an id from GET /v1/coding/models. Another id answers model_not_enabled.
  • stream: true. stream_options is optional; usage is always in the stream.
  • Exactly one of max_tokens and max_completion_tokens, from 1 to 32,000 and within the model's max_output_tokens. The input and the output together must fit the model's context, otherwise context_limit.

A request holds at most 512 messages and 64 tools, and the body at most 2,000,000 bytes. reasoning_effort takes one of the model's reasoning_efforts; another value answers reasoning_not_supported. The answer must finish within 600 seconds, otherwise timeout.

Function calls

Describe the functions the model may call in tools. When the model wants one, the stream carries tool_calls and ends with finish_reason: "tool_calls". Your client runs the function, asks the person where needed, and sends the next request with the conversation so far: the assistant message with its tool_calls, then a tool message with the result for each call.

The messages of the next request
[
  {"role": "user", "content": "What is in README.md?"},
  {
    "role": "assistant",
    "content": null,
    "tool_calls": [
      {"id": "call_7b2d", "type": "function", "function": {"name": "read_file", "arguments": "{\"path\":\"README.md\"}"}}
    ]
  },
  {"role": "tool", "tool_call_id": "call_7b2d", "content": "# My project\nA small command-line tool."}
]

Every tool call must be answered, by its tool_call_id, before the next message. Send earlier reasoning_content back unchanged on the assistant message. tool_choice takes auto, none, required or one function by name.

Request ids and retries

X-Request-Id takes a new UUID (version 4) for each new logical operation. If you do not know whether an operation reached komplai, for example after a dropped connection, send it again with the same id: komplai then answers duplicate_request instead of calling the provider a second time. Never retry automatically with a new id after coding_service_unavailable or timeout, because the call may have reached the model and counted towards the cap. Request-Id in the response repeats your id.

When the terms change

When the provider, its terms, the data mode, the agreement or the coding models and their prices change, contract changes too, and a completion with the old one answers terms_changed. Read the account again, show the new terms to the person, and send the new contract. Never accept new terms automatically. Ordinary AI usage does not change the contract.

The monthly AI spending cap

Before the provider is called, komplai reserves the most the call can cost under the organisation's monthly AI spending cap. Usage is then metered at the provider's price; cached input has its own price where the provider has one, and reasoning counts as output tokens. Calls stop when the cap or the organisation's own limit is reached (ai_credit_exhausted) or your personal limit (person_ai_credit_exhausted). The API never switches to another model.

Where data is processed

Prompts, code and tool results go to the coding model in komplai's EU cloud in France. komplai's API runs on its servers in Germany. Data does not leave the EU. komplai stores no prompts, answers or tool results, only the call's metadata for accounting and audit. The provider's own terms for training and retention are in the account's data.

Reference and errors

  • Coding reference: every field of the three calls, with code samples.
  • Coding client: komplai's client for the command line and OpenCode, which signs in, reads the account and sends the headers for you.
  • Errors: every code with what to do.
komplaidevelopers
Contact us

Search the documentation

Use the arrow keys to choose and Enter to open.