API Documentation
Complete reference for the PrivatAI REST API. Simple, privacy-friendly, and powerful.
Introduction
The PrivatAI API provides access to LLM models (e.g. gpt-oss-120b, GLM-5.2), hosted in the EU with full GDPR compliance. All requests are transmitted over HTTPS and your prompts are not stored.
Base URL
OpenAI and Grok compatible: In your client, set only the base URL to https://privatai.com/api/v1 (e.g. OPENAI_API_BASE).
Authentication
Authenticate with your API key in the Authorization header:
Authorization: Bearer privat_xxxxxxxxxxxxxxxxxxxx
Find your API key in the dashboard after logging in and payment.
Chat Completion
Generates a response to your message. OpenAI-compatible format; by default a single JSON response, or streaming via Server-Sent Events when stream: true.
Request Body
| Parameter | Type | Description |
|---|---|---|
messages |
array | Required. Array of messages (role, content) |
model |
string | Optional. Model key (e.g. gpt-oss-120b). If omitted: gpt-oss-120b for paid accounts. See GET /api/v1/models |
stream |
boolean | Optional, default false. If true: SSE stream |
temperature, top_p, max_tokens, frequency_penalty, presence_penalty, stop, seed |
— | Optional. Standard OpenAI params. max_tokens is tier-capped (Essential 8,192, Professional 32,768). |
Simple Request
curl -X POST https://privatai.com/api/v1/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "gpt-oss-120b", "messages": [{"role": "user", "content": "What is machine learning?"}]}'
With tools (function calling)
curl -X POST https://privatai.com/api/v1/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "user", "content": "What is the weather in Berlin?"} ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "Get the current weather for a city", "parameters": { "type": "object", "properties": { "location": {"type": "string"} }, "required": ["location"] } } } ], "tool_choice": "auto", "stream": false }'
Conversation (Multi-Turn)
curl -X POST https://privatai.com/api/v1/chat/completions \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "messages": [ {"role": "user", "content": "What is the capital of France?"}, {"role": "assistant", "content": "The capital of France is Paris."}, {"role": "user", "content": "What is the population?"} ] }'
Response (SSE Stream, OpenAI format)
The response is streamed as Server-Sent Events in OpenAI format:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":"The"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{"content":" capital"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{"content":" of"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{"content":" France"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{"content":" is"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{"content":" Paris"},"finish_reason":null}]} data: {"id":"chatcmpl-...","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":15,"completion_tokens":7,"total_tokens":22}}
Thinking models (Reasoning)
Models like gpt-oss-120b and GLM-5.2 are thinking models. When streaming, they may send delta.reasoning (reasoning trace) before or interleaved with delta.content (answer).
Handling: Accumulate delta.reasoning for the reasoning (e.g. to display or debug) and delta.content for the final user-facing answer.
{"choices":[{"index":0,"delta":{"reasoning":"Let me analyze..."}}]}
{"choices":[{"index":0,"delta":{"content":"The answer is Paris."}}]}
Check Usage
Returns your current usage.
curl https://privatai.com/api/v1/usage \ -H "Authorization: Bearer YOUR_API_KEY"
Response
{
"tokens_used": 15420,
"prompt_tokens": 5200,
"completion_tokens": 10220,
"requests": 89,
"last_used": "2026-07-02T14:30:00"
}
List Models
Returns available models (OpenAI-compatible). GLM-5.2 only appears with a Professional plan.
curl https://privatai.com/api/v1/models \ -H "Authorization: Bearer YOUR_API_KEY"
Python Example
import requests import json API_KEY = "YOUR_API_KEY" URL = "https://privatai.com/api/v1/chat/completions" def chat(messages): response = requests.post( URL, headers={ "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" }, json={"messages": messages}, stream=True ) for line in response.iter_lines(): if line.startswith(b"data: "): data = json.loads(line[6:]) if data.get("choices") and data["choices"][0].get("delta", {}).get("content"): print(data["choices"][0]["delta"]["content"], end="", flush=True) if data.get("choices") and data["choices"][0].get("finish_reason"): print() return data.get("usage") chat([{"role": "user", "content": "Explain quantum computing in simple terms."}])
JavaScript Example
const API_KEY = 'YOUR_API_KEY'; async function chat(messages) { const response = await fetch('https://privatai.com/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ messages }) }); const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); for (const line of chunk.split('\n')) { if (line.startsWith('data: ')) { const data = JSON.parse(line.slice(6)); if (data.choices && data.choices[0]?.delta?.content) process.stdout.write(data.choices[0].delta.content); if (data.choices && data.choices[0]?.finish_reason) console.log(); } } } } chat([{ role: 'user', content: 'What is the meaning of life?' }]);
Error Handling
The API returns standard HTTP status codes:
| Code | Meaning |
|---|---|
200 |
Success |
400 |
Bad request (e.g. missing messages) |
401 |
Invalid or missing API key |
402 |
Subscription inactive or budget not initialized — check/renew your plan |
403 |
Model requires the Professional plan (e.g. GLM-5.2) |
429 |
Rate limit or monthly allowance exceeded |
500 |
Server error |
Rate Limits
The API caps requests per minute by plan (per API key). Exceeding the limit returns HTTP 429. In addition, each plan includes a monthly usage allowance; once it is used up, the API also returns HTTP 429 until the next billing cycle. Web chat on the site is rate-limited separately.
| Plan | Requests / min | Max tokens / response | Volume / month (approx.) | Models |
|---|---|---|---|---|
| Trial | 6 | 4.096 | — | Standard model |
| Essential | 30 | 8.192 | ~ 20M tokens | Standard model (gpt-oss-120b) |
| Professional | 60 | 32.768 | ~ 40M tokens | Standard model (gpt-oss-120b) |
| ~ 4M tokens | Flagship model (GLM-5.2) |