Reference
API reference
Endpoints, authentication, request fields, responses and streaming events for the Praus API.
#Base URL
https://praus.ai| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /api/chat/compound-pipeline-sync | API key | Send a message and get an answer, whole or streamed. |
| GET | /api/health | None | Check that the service is reachable. |
#Authentication
Send your Praus API key in either header. Both are supported and behave the same:
X-Api-Key: YOUR_PRAUS_API_KEYAuthorization: Bearer YOUR_PRAUS_API_KEYA missing, invalid or revoked key returns 401 UNAUTHORIZED. Keys are created in the Praus app; see API keys and access.
#Create an answer
https://praus.ai/api/chat/compound-pipeline-syncSends one message to Praus and returns the answer. Requests are JSON, sent with Content-Type: application/json.
#Request body
messagestringRequiredqueryProfilestringRequired"ask". This is the profile documented here for general questions and tasks.searchEnabledbooleanUse falsefalse. Web search has extra account and processing requirements and isn’t covered by these docs.streambooleanOptionalsessionOnlybooleanOptionalconversationHistoryarrayOptional{ "role": "user" | "assistant", "content": string }. Only the latest 60 messages are kept. See Conversations.userMemoryobjectOptional{ "memories": [], "customInstructions": "" }, as in the examples.#Example request
curl https://praus.ai/api/chat/compound-pipeline-sync \
-H "Content-Type: application/json" \
-H "X-Api-Key: $PRAUS_API_KEY" \
-d '{
"message": "A warehouse has 12 boxes containing 24 units each and ships 37 units. How many units remain?",
"queryProfile": "ask",
"searchEnabled": false,
"stream": false,
"sessionOnly": true,
"userMemory": {
"memories": [],
"customInstructions": ""
}
}'import os
import requests
response = requests.post(
"https://praus.ai/api/chat/compound-pipeline-sync",
headers={
"Content-Type": "application/json",
"X-Api-Key": os.environ["PRAUS_API_KEY"],
},
json={
"message": "A warehouse has 12 boxes containing 24 units each and ships 37 units. How many units remain?",
"queryProfile": "ask",
"searchEnabled": False,
"stream": False,
"sessionOnly": True,
"userMemory": {"memories": [], "customInstructions": ""},
},
timeout=120,
)
data = response.json()
if not response.ok:
raise RuntimeError(f"{response.status_code} {data.get('code')}: {data.get('message')}")
print(data["result"]["content"])// Node.js 18 or later (built-in fetch). Run on your server, never in a browser.
const response = await fetch("https://praus.ai/api/chat/compound-pipeline-sync", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": process.env.PRAUS_API_KEY,
},
body: JSON.stringify({
message: "A warehouse has 12 boxes containing 24 units each and ships 37 units. How many units remain?",
queryProfile: "ask",
searchEnabled: false,
stream: false,
sessionOnly: true,
userMemory: { memories: [], customInstructions: "" },
}),
});
const data = await response.json();
if (!response.ok) {
throw new Error(`${response.status} ${data.code}: ${data.message}`);
}
console.log(data.result.content);#Response
With stream: false, a successful request returns HTTP 200 and one JSON object:
{
"type": "done",
"result": {
"content": "251",
"sources": [],
"images": [],
"thoughtProcess": []
}
}typestringAlways"done" for a completed answer.result.contentstringAlwaysresult.sourcesarrayMay be emptyresult.imagesarrayMay be emptyresult.thoughtProcessarrayMay be emptyMore fields may appear in result or at the top level. Ignore fields you don’t use. The response isn’t a choices array, so read result.content directly.
#Streaming response
With stream: true, the response is application/x-ndjson: one JSON event per line.
{"type":"status","label":"Working"}
{"type":"token","content":"Hello"}
{"type":"token","content":" there."}
{"type":"done","result":{"content":"Hello there."}}
{"type":"reset"}
{"type":"error","code":"SERVICE_UNAVAILABLE","message":"Please retry shortly."}| Event | Meaning |
|---|---|
status | Progress label. Optional to display. |
token | Append content to the answer shown so far. |
reset | Discard the provisional text shown so far. |
done | result.content is the final answer. |
error | The request failed. Treat it as a failure even though the status was 200. |
A stream that closes without a done event is incomplete. Full client guidance is in Streaming.
#Errors
Errors return an HTTP error status and a JSON body, usually like this:
{
"error": "Error description",
"code": "ERROR_CODE",
"message": "User-facing explanation"
}Some errors also include requestId, retryAfterSeconds or recovery details. Codes and retry guidance are in Limits and errors.
#Check service health
https://praus.ai/api/healthNo authentication. Returns HTTP 200 when the service is reachable.
curl https://praus.ai/api/health{
"status": "ok",
"service": "Praus"
}A healthy response doesn’t confirm that your key or answer generation works. Use a real request for that.
#Not supported
- Image input. Requests with images are refused for API keys with
413 unsupported_image_budget. - Choosing a model. There is no model parameter and no list of selectable models.
- Other routes. Paths such as
/v1/models,/v1/chat/completions,/v1/responses,/v1/agentsand/v1/tasksaren’t part of the Praus API. Some can return a web page with HTTP 200. That is the website, not an API response. - Tools and task execution. Native tool calls are an account-restricted preview. Standard text requests do not execute tools. See Agents.