Chat completions

POST /llm/chat/completions is the endpoint your application calls to get an answer from a model, in the OpenAI format. This page is the reference for what you can send, what comes back, and how the platform refuses a request it cannot serve; for your first request from scratch, see Use the API.

Send a chat request

Send a JSON body with your company's API key in the x-api-key header:

bash
curl https://platform.datamind.ai/llm/chat/completions \
  -H "x-api-key: $DATAMIND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model_id>",
    "messages": [
      { "role": "user", "content": "Summarise this ticket in two lines." }
    ]
  }'
SettingValue
Method and pathPOST /llm/chat/completions
Authenticationx-api-key: <api_key> header. An Authorization: Bearer header alone is not accepted.
BodyA JSON object. Anything else is refused with Request body must be a JSON object.
StreamingAdd "stream": true to receive the answer as it is written; see Stream an answer.

Request fields

Choose the model

Send model with one ID, or models with a non-empty array of IDs to give the request fallbacks. One of these two fields is required. Take IDs from GET /llm/models (Models API); the Models page shows the same list.

Add messages and your user ID

messages is required: an array of message objects with a role and a content, as in the OpenAI format. A request without it is refused with Request must include a `messages` array.

user is optional: send your end user's identifier there. The platform records it as the External ID on Usage, where you can filter requests by it.

Control thinking

For a model whose thinking is not mandatory, send a reasoning object:

An effort outside the model's list is refused: Reasoning effort "<effort>" is not available on this model - allowed: <allowed list>.

Choose the provider order

Send "provider": { "sort": "<sort>" } to override your company's Provider sort for one request; the value on the request wins. The allowed values are throughput, latency, price and balanced, and an unknown value is refused with Invalid provider.sort - allowed values: <allowed values>. Provider order applies to pay-as-you-go models.

Set the length of the answer

max_tokens is optional:

What comes back

The response follows the OpenAI shape: the answer text is in choices[0].message.content, and usage is always included, with the prompt, completion and cached token counts and, when the model reports it, the reasoning token count. usage rides the response whether you stream or not; no stream_options is needed.

The tokens and the cost of every request are on Usage.

Stream an answer

Add "stream": true. The answer arrives as server-sent events; each event carries an OpenAI-style chunk with the new text in choices[0].delta.content, and the final chunk carries usage. The [DONE] marker ends the stream.

Limits and checks

The platform checks your company's limits before it forwards a request: requests per minute, requests running at once, and the monthly spend cap on billable usage. A refused request carries the matching status and code; what to retry is on Errors and retries, and the limits themselves are on Limits and the spend cap.

If your company prohibits personal data transmission, the request is checked before it reaches a provider; a request with personal data fails with status 400 and code content_filter and is not forwarded. See Settings.

Zero data retention

Every request that reaches a model provider runs with zero data retention. The platform enforces this for all requests: it cannot be turned off, and preferences you send in the provider object cannot override it.

Refusals

These are the refusals the endpoint itself produces for a chat request; the full list of statuses and codes is on Errors and retries.

WhenWhat the error says
The body is not a JSON objectRequest body must be a JSON object
No model or models was sentRequest must specify `model` or a non-empty `models` array
No messages was sentRequest must include a `messages` array
A model is not in your key's menuModel(s) not available: <ids> - see GET /models for the available catalog
An effort is outside the model's listReasoning effort "<effort>" is not available on this model - allowed: <allowed list>
An unknown provider.sort valueInvalid provider.sort - allowed values: <allowed values>
A Kartlos model is called from outside DataMind OS"<alias>": Kartlos models are DataMind-exclusive and can only be used from within the DataMind platform
A Kartlos model is combined with other models"<alias>" must be the only model in the request - house models cannot be combined with other models or fallback arrays

Questions, answered

Can I send more than one model in one request?

Yes. Send models with a non-empty array of IDs instead of model, and the request is billed for the model that actually served the answer. A Kartlos model cannot be combined with other models or fallback arrays.

What happens if I do not send max_tokens?

The platform sets an output ceiling for you: at most 64,000 tokens, lowered if a model you listed allows less. If a provider rejects the request for asking more output than it can produce, the platform retries with smaller ceilings first (for the default: 48,000, then 32,000), and only a ceiling the platform set itself is reduced.

Why was my answer cut off?

It reached its output limit, and the response ends with finish_reason length. Raise max_tokens, within the model's max_output_tokens, or make the request smaller.

How do I control thinking on a model?

Send a reasoning object: {"effort": "<value>"} selects a level from the model's supported list, and {"enabled": false} turns thinking off when the model's thinking is not mandatory. An effort outside the list is refused with Reasoning effort "<effort>" is not available on this model - allowed: <allowed list>.

Can I choose the provider order for one request?

Yes. A provider.sort value on the request wins over the company's Provider sort for that request. The values are throughput, latency, price and balanced, and an unknown value is refused. Provider order applies to pay-as-you-go models.

What happens if my stream breaks?

The stream ends with an error event carrying the code stream_interrupted and the message Upstream stream interrupted. Send the request again; you are billed for the tokens generated before the stream stopped.

Why was my request refused with Model(s) not available?

One of the IDs is not in the list GET /llm/models returns for your key. A withdrawn model and a model outside your company's region are refused the same way. Take an ID from that list and send the request again.

What is usage.free_tokens in a response?

The Kartlos Discount for the request: agent-prompt tokens that are part of the prompt and are not charged. It appears only when something was deducted; a pay-as-you-go response does not carry it.

Can I turn off zero data retention?

No. Every request that reaches a model provider runs with zero data retention, and no request setting or provider preference can override it.

What does the user field do?

It carries your end user's identifier. The platform records it as the External ID on the Usage log, where you can filter requests by it.