curl --request POST \
--url https://pria.praxislxp.com/api/ai/chat/completions \
--header 'Content-Type: application/json' \
--header 'x-access-token: <x-access-token>' \
--data '
{
"messages": [
{
"content": "<string>",
"name": "<string>",
"tool_call_id": "<string>",
"tool_calls": [
{}
]
}
],
"model": "pria",
"stream": true
}
'import requests
url = "https://pria.praxislxp.com/api/ai/chat/completions"
payload = {
"messages": [
{
"content": "<string>",
"name": "<string>",
"tool_call_id": "<string>",
"tool_calls": [{}]
}
],
"model": "pria",
"stream": True
}
headers = {
"x-access-token": "<x-access-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-access-token': '<x-access-token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
messages: [
{
content: '<string>',
name: '<string>',
tool_call_id: '<string>',
tool_calls: [{}]
}
],
model: 'pria',
stream: true
})
};
fetch('https://pria.praxislxp.com/api/ai/chat/completions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://pria.praxislxp.com/api/ai/chat/completions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'messages' => [
[
'content' => '<string>',
'name' => '<string>',
'tool_call_id' => '<string>',
'tool_calls' => [
[
]
]
]
],
'model' => 'pria',
'stream' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-access-token: <x-access-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://pria.praxislxp.com/api/ai/chat/completions"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<x-access-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://pria.praxislxp.com/api/ai/chat/completions")
.header("x-access-token", "<x-access-token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pria.praxislxp.com/api/ai/chat/completions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<x-access-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}"
response = http.request(request)
puts response.read_body"data: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: [DONE]\n"{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "empty_user_message"
}
}{
"error": {
"message": "Chat Completion endpoint is not enabled for this institution.",
"type": "forbidden",
"code": "chat_completion_disabled"
}
}OpenAI-compatible Chat Completions endpoint (inbound integration)
OpenAI-compatible streaming chat completions endpoint. Accepts a messages[]
array, extracts the last user message as the active turn, replays any prior
user/assistant messages as conversation history (sanitized for Bedrock’s
alternating-role requirement), runs the active turn through Praxis’s
RAG/tool pipeline, and streams back OpenAI-format SSE chunks.
Today’s primary consumer: the ElevenLabs Voice Agent in Convo (Direct) mode — its custom-LLM webhook points at this endpoint.
OpenAI compatibility surface (what Pria reads vs. ignores):
Pria accepts the OpenAI shape but only reads messages[] and model.
model is informational — the effective model is determined by the
Praxis cascade (assistant > chatCompletionModel > institution
conversationModel). Fields commonly seen on OpenAI clients but
silently ignored here: tools, tool_choice, temperature,
max_tokens, stream, stream_options, top_p, n,
frequency_penalty, presence_penalty, response_format, seed,
logit_bias, user. The response is always SSE (server forces
streaming mode regardless of stream). Tool calls are executed
server-side by Pria’s tool runtime — they are not surfaced as OpenAI
tool_calls deltas; tool acknowledgements appear inline as spoken
phrases in the content stream.
Per-institution gate. Disabled by default. The administrator must
set institution.chatCompletionEnabled = true to allow inbound traffic.
Disabled institutions receive 403 chat_completion_disabled.
Override fields (institution-level, all optional):
chatCompletionModel— overrides the conversation model and provider routing for inbound requests. Priority:assistant.conversationModelchatCompletionModel>institution.conversationModel. Assistant always wins — the override only applies when no assistant has overridden the conversation model. Empty/unset = inherit from existing cascade.chatCompletionMaxCompletionTokens— overridesmaxCompletionTokens. Sentinel:-1= inherit,0= Auto (catalog cap),>0= explicit.chatCompletionReasoningEffort— overridesreasoningEffort. Empty string = inherit. Common voice-mode value:'none'.
Detection of “this is a chat-completion inbound request” is path-based —
any request landing here sets requestArgs.isChatCompletion = true,
which the override helpers in rag.js and reasoning_effort_utils.js
read to apply the cascade above.
curl --request POST \
--url https://pria.praxislxp.com/api/ai/chat/completions \
--header 'Content-Type: application/json' \
--header 'x-access-token: <x-access-token>' \
--data '
{
"messages": [
{
"content": "<string>",
"name": "<string>",
"tool_call_id": "<string>",
"tool_calls": [
{}
]
}
],
"model": "pria",
"stream": true
}
'import requests
url = "https://pria.praxislxp.com/api/ai/chat/completions"
payload = {
"messages": [
{
"content": "<string>",
"name": "<string>",
"tool_call_id": "<string>",
"tool_calls": [{}]
}
],
"model": "pria",
"stream": True
}
headers = {
"x-access-token": "<x-access-token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-access-token': '<x-access-token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
messages: [
{
content: '<string>',
name: '<string>',
tool_call_id: '<string>',
tool_calls: [{}]
}
],
model: 'pria',
stream: true
})
};
fetch('https://pria.praxislxp.com/api/ai/chat/completions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://pria.praxislxp.com/api/ai/chat/completions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'messages' => [
[
'content' => '<string>',
'name' => '<string>',
'tool_call_id' => '<string>',
'tool_calls' => [
[
]
]
]
],
'model' => 'pria',
'stream' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-access-token: <x-access-token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://pria.praxislxp.com/api/ai/chat/completions"
payload := strings.NewReader("{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-access-token", "<x-access-token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://pria.praxislxp.com/api/ai/chat/completions")
.header("x-access-token", "<x-access-token>")
.header("Content-Type", "application/json")
.body("{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pria.praxislxp.com/api/ai/chat/completions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-access-token"] = '<x-access-token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"messages\": [\n {\n \"content\": \"<string>\",\n \"name\": \"<string>\",\n \"tool_call_id\": \"<string>\",\n \"tool_calls\": [\n {}\n ]\n }\n ],\n \"model\": \"pria\",\n \"stream\": true\n}"
response = http.request(request)
puts response.read_body"data: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: [DONE]\n"{
"error": {
"message": "<string>",
"type": "invalid_request_error",
"code": "empty_user_message"
}
}{
"error": {
"message": "Chat Completion endpoint is not enabled for this institution.",
"type": "forbidden",
"code": "chat_completion_disabled"
}
}Headers
Praxis JWT
Public ID of the institution context (optional, defaults to user's primary institution)
Conversation/course ID
Assistant ObjectId (24-char hex)
IANA timezone string (e.g. "America/New_York") for date-aware prompts
Body
OpenAI-format messages array. The last user message is the
active turn; earlier user and assistant entries are
replayed as conversation history. system and tool
messages are accepted in the shape but ignored — Pria
builds its own system prompt from assistant + institution
settings, and tool execution is server-managed.
Show child attributes
Show child attributes
Informational only — echoed back in SSE chunks as
choices[].delta.model. The actual model dispatched is
determined by the Praxis cascade
(assistant.conversationModel >
institution.chatCompletionModel >
institution.conversationModel).
"pria"
Ignored — the endpoint always returns text/event-stream.
Accepted for OpenAI shape compatibility.
true
Response
SSE stream of OpenAI-format completion chunks. Terminated with a final data: [DONE] line.
The response is of type string.
"data: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"chatcmpl-1735...\",\"object\":\"chat.completion.chunk\",\"created\":1735000000,\"model\":\"pria\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"finish_reason\":null,\"logprobs\":null}]}\n\ndata: [DONE]\n"
Was this page helpful?