# Coding (Beta)

> Connect a coding client to komplai: read the account and terms, choose a model and stream OpenAI-compatible completions with function calls.

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](https://developers.komplai.dk/errors/coding_not_enabled). A completion also needs a monthly AI spending cap for the month; without one it answers 403 [ai_credit_not_granted](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/tools/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](https://hub.komplai.dk/api-access). An organisation integration key (`kp_org_...`) gets 403 [integration_not_permitted](https://developers.komplai.dk/errors/integration_not_permitted).

## The three calls

| Call | Scope | What it does |
| --- | --- | --- |
| GET /v1/coding/account | `coding:read` | Your 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/models | `coding:read` | The coding models with their limits, in the OpenAI list shape |
| POST /v1/coding/chat/completions | `coding:complete` | A 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

```bash
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.

```bash
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
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](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/errors/reasoning_not_supported). The answer must finish within 600 seconds, otherwise [timeout](https://developers.komplai.dk/errors/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.

```json
[
  {"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](https://developers.komplai.dk/errors/duplicate_request) instead of calling the provider a second time. Never retry automatically with a new id after [coding_service_unavailable](https://developers.komplai.dk/errors/coding_service_unavailable) or [timeout](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/errors/ai_credit_exhausted)) or your personal limit ([person_ai_credit_exhausted](https://developers.komplai.dk/errors/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](https://developers.komplai.dk/reference/coding): every field of the three calls, with code samples.
- [Coding client](https://developers.komplai.dk/tools/coding-client): komplai's client for the command line and OpenCode, which signs in, reads the account and sends the headers for you.
- [Errors](https://developers.komplai.dk/errors): every code with what to do.

---

https://developers.komplai.dk/tools/coding
