Skip to main content

AI & OpenAI-compatible

AI query endpoints

Controller: AIController — route prefix api/AI
Authentication: API Key only (x-api-key)

Provider selection — provider vs providerId

InputTypeDescription
providerstring (optional)Logical provider type: Azure, Bedrock, Ollama, Gemini, … The platform resolves an active configuration for that type.
providerIdinteger (optional)Specific provider instance (database row). When present, it takes precedence over provider. The instance must be active and must support the capability required (text, image, document, speech, agent tools, embeddings, realtime).

JSON and multipart both use camelCase: providerId, not provider_id.

Where providerId is accepted: POST /api/ai/query, /queryImage, /queryDocument, /queryAudio, /chat, and the realtime WebSocket start message.

No-Log Requests

By default every request is fully logged. A request may opt out of logging its prompt and response by setting noLog: true (JSON) or noLog=true (multipart). This is a two-level control:

  1. Project permission (admin): Allow no-log requests must be enabled on the project.
  2. Per-request flag: caller sets noLog: true.

When both are met, the LogEntry row is still created (system prompt + metrics retained) but RequestPrompt / PromptResponse are stored as null.
For OpenAI-compat: { "extension": { "noLog": true } }.


POST /api/ai/query

Text completion / one-shot query.

{
"prompt": "What is the recommended workflow for onboarding?",
"projectId": 1,
"promptId": 5,
"provider": "Azure",
"providerId": 12,
"stream": false,
"externalId": "EMR-12345",
"externalUser": "doctor-smith",
"noLog": false,
"parameters": { "temperature": 0.7, "maxTokens": 500 },
"messageHistory": [
{ "role": "user", "content": "Context from a prior turn" },
{ "role": "assistant", "content": "…" }
]
}
ParameterTypeRequiredDescription
promptstringText query
projectIdintegerProject (often implied by API key)
promptIdintegerPrompt template
provider / providerIdstring / intRouting (see above)
streambooleanSSE streaming (default false)
externalId / externalUserstringCaller tracking ids
noLogbooleanSee No-Log Requests
parametersobjecttemperature, maxTokens, …
messageHistoryarrayPrior { role, content } turns

Success (non-stream):

{
"success": true,
"content": "A typical onboarding workflow includes…",
"errorMessage": null,
"provider": "Azure",
"providerId": 12,
"executionDuration": "00:00:02.345",
"requestId": 12345,
"inputTokens": 25,
"outputTokens": 150
}

Status codes: 200, 400, 401, 403, 500, 502 (provider failure).

curl -X POST https://your-kroov-host/api/ai/query \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "prompt": "Explain the escalation policy", "projectId": 1, "providerId": 12 }'

POST /api/ai/queryImage

Vision analysis. multipart/form-data.

FieldTypeRequiredDescription
filefilePNG, JPEG, GIF, WebP, BMP (max ~20 MB)
promptstringQuestion about the image
projectId, promptId, provider, providerIdRouting / templates
stream, externalId, externalUser, noLogSame semantics as /query
curl -X POST https://your-kroov-host/api/ai/queryImage \
-H "x-api-key: your-api-key" \
-F "file=@xray.png" \
-F "prompt=Describe what you see" \
-F "projectId=1" \
-F "providerId=12"

POST /api/ai/queryDocument

Document Q&A. multipart/form-data. Formats: PDF, DOCX, TXT, CSV, XLSX, XLS (max ~50 MB).

FieldTypeRequiredDescription
filefileDocument
promptstringQuestion
providerIdintegerSupported — specific instance
Other fieldsSame pattern as queryImage
curl -X POST https://your-kroov-host/api/ai/queryDocument \
-H "x-api-key: your-api-key" \
-F "file=@report.pdf" \
-F "prompt=Summarize key points" \
-F "projectId=1" \
-F "providerId=12"

POST /api/ai/queryAudio

Batch transcription (+ optional prompt formatting). multipart/form-data. Formats: MP3, WAV, WebM, OGG, M4A, MP4, FLAC, AAC (max ~100 MB).

FieldTypeRequiredDescription
filefileAudio
languagestringOmit / "auto" = detect; or fr / en / he
providerIdintegerInstance with speech capability
enableSpeakerDiarizationbooleanPerson 1 / Person 2 labels
usePromptForFormattingbooleanRun formatting prompt after STT
promptId / transcriptionPromptId / formattingPromptIdintTemplates
projectId, stream, externalId, externalUser, noLogStandard

Response includes audioDuration (seconds) when available.


WebSocket — Live realtime transcription

Endpoint: wss://{host}/api/ai/realtime/transcribe
Auth: x-api-key query, handshake header, or first message { "type":"auth", "apiKey":"..." }.

Audio: PCM16 mono 24 kHz, ~100 ms base64 chunks.

Client typeFieldsPurpose
authapiKeyIf not provided via query/header
startproviderId?, projectId?, language?, externalId?, externalUser?Open Azure Realtime session
audiodata (base64 PCM16)Append chunk
stopEnd
Server typeMeaning
session_readySafe to send audio
partial / finalTranscript deltas
speech_started / speech_stoppedVAD
error / doneFailure / close (logged as audio-realtime)

Provider config: type AzureRealtime (or Azure with realtime capability), supportsRealtimeAudio, realtimeDeployment (e.g. gpt-realtime).

Batch queryAudioLive WebSocket
InputFilePCM16 stream
LatencyEnd of filePartial + final while speaking
CapabilitySupportsAudioSupportsRealtimeAudio

POST /api/ai/chat

Stateful conversational chat with optional MCP agent loop, knowledge-base grounding, attachments, and agent-definition grants.

{
"chatId": null,
"messageUser": "Draft a reply to this customer message",
"messageServer": null,
"projectId": 1,
"promptId": 5,
"providerId": 12,
"stream": true,
"endSession": false,
"externalId": "EMR-12345",
"externalUser": "doctor-smith",
"noLog": false,
"parameters": { "temperature": 0.7, "maxTokens": 500 },
"knowledgeBaseIds": [3, 7],
"agentDefinitionId": 1,
"attachments": [
{
"base64Data": "<base64>",
"contentType": "application/pdf",
"fileName": "note.pdf"
}
],
"delegation": {
"enableRemoteTools": true,
"mcpServerIds": [12],
"mcpInstanceId": null,
"mcpAccountNames": { "12": "default" },
"maxToolRounds": 10,
"maxToolCalls": 10,
"credential": null
}
}
ParameterTypeRequiredDescription
messageUserstringUser message
messageServerstringExtra server instructions
chatIdGUID stringNull = new session
projectId / promptId / provider / providerIdRouting
streambooleanSSE (recommended for MCP tools)
endSessionbooleanClose session
knowledgeBaseIdsint[]Internal KB grounding for a normal text provider (not a KnowledgeBase provider type)
agentDefinitionIdintInherit agent MCP allow-list + tool grants; materializes a chat-scoped invocation
attachmentsarrayMultimodal base64 attachments (audio/image/document) converted server-side
delegationobjectMCP agent loop configuration

delegation fields:

FieldTypeDescription
enableRemoteToolsbooleanEnable MCP / tool agent loop
credentialstringInline JWT / API key / PAT when required
mcpServerIdintSingle server when project has several
mcpServerIdsint[]Multi-MCP; null = unspecified, [] = no MCP (grants only), non-empty = exact set
mcpInstanceId / mcpInstanceIdsguid / mapManaged worker instance(s)
mcpAccountNamesmapPer-server vault account name
maxToolRounds / maxToolCallsintLoop limits (default 10)
internalApiBaseUrlstringOverride for InternalAPI-style MCPs
contextOverridesobjectSandbox overrides

Flow: first message with chatId: null → response includes chatId → subsequent turns reuse it → endSession: true to close.

SSE events (when stream: true and tools enabled): content, toolCalls, status, tokens, error, [DONE].


POST /api/ai/vote/{requestId}

POST /api/ai/vote/chat/{chatId}/{messageIndex}

{ "isThumbsUp": true, "comment": "Accurate and concise" }

Field name is isThumbsUp (not vote).


GET /api/ai/logs

Project logs visible to the API key (filters: date range, prompt text, externalId, …).

GET /api/ai/assistants?providerId=

List Azure Assistants for a provider.

GET /api/ai/download-blob?blobUrl= / GET /api/ai/view-blob?blobUrl=

Download or inline-view a knowledge-base / storage blob URL previously returned by the platform.


OpenAI-compatible API (/v1)

Controller: OpenAiCompatController — route prefix v1
Authentication: API Key via Authorization: Bearer <api-key> or x-api-key

MethodPathPurpose
GET/v1/modelsList models / provider aliases
GET/v1/models/{id}Model detail
POST/v1/chat/completionsChat completions (tools / MCP supported via platform translation)
POST/v1/audio/transcriptionsMultipart transcription
POST/v1/embeddingsEmbeddings (same service as internal RAG)

Kroov extension on chat completions:

{
"model": "gpt-4o",
"messages": [{ "role": "user", "content": "Hello" }],
"x-kroov": { "noLog": true }
}

Chat Completions compatibility boundary

Kroov guarantees the Chat Completions subset for messages, streaming, structured output, client tools, and tool_choice. Options outside the implemented request model are rejected with an OpenAI-shaped invalid_request_error; they are not silently ignored.

Providertextjson_objectjson_schemaNative mapping
OpenAI / Azure OpenAIYesYesYesOpenAI response_format
GeminiYesYesYesresponseMimeType + unmodified responseJsonSchema
AnthropicYesNoYesoutput_config.format
OpenAI-compatible, Mistral, Moonshot, Z.ai, DeepSeekYesPassthroughPassthroughOpenAI response_format; the upstream model may explicitly reject it
Bedrock, Ollama, Knowledge BaseYesNoNoNo equivalent guarantee on this route

For json_schema, Kroov preserves the complete schema and validates the final non-streaming response independently before returning success. A schema violation returns structured_output_validation_failed; for example, {"click":4} is rejected when the schema requires {"click":{"index":4}}. json_schema with strict:true and stream:true is explicitly rejected because a complete response cannot be validated before fragments have already been sent.

tool_choice supports none, auto, required, and a named function. OpenAI-shaped providers receive the original value; Gemini and Anthropic receive their native equivalents. If the selected provider or model cannot honor an option, the API returns HTTP 400 with code: unsupported_value.

POST /v1/embeddings accepts a string or array of strings and returns float vectors (currently 1536-d for internal RAG).

curl https://your-kroov-host/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [{"role":"user","content":"Summarize the product guidelines"}]
}'