OpenAI-compatible /v1
Base URL ends in /v1. Use a chat-scoped key. Works with Continue, Cline, Aider, OpenClaw (openai-completions), LibreChat, and the official OpenAI SDKs pointed at a custom base URL.
Implemented
GET /v1/models,GET /v1/models/{id}POST /v1/chat/completions— blocking and SSEstream: true- Tools /
tool_calls/role: tool(API adapts upstream Ollama or OpenAI-shaped backends) - Vision via multipart
contentarrays withimage_urlparts —data:image/…;base64,…orhttps://(SSRF-safe: public IPs only, redirect re-checked, size-capped). Images are resized, scanned for child-safety, then sent to a vision-capable model - PDF file parts — text extracted into the prompt when a text layer exists; embedded JPEG/PNG streams attached for vision when present. No Tesseract OCR in this binary — scanned pages without embeds need page screenshots + a vision model (practical path; see below)
- Context / history / learning cache (when Valkey + column encryption are armed): plan byte floors + addon GiB; over quota continuously evicts least-recently-used entries; personal cache is seat-private; shared learning (
o/…) is opt-in per org (default on); seat and org purge endpoints bump generation counters (seedocs/ADDONS.md) - Opt-in web search (SearXNG) — model-only by default
max_completion_tokensas an alias ofmax_tokensGET /v1/chat/queue/{id}— Galtops extension when a completion is deferred (X-Galtops-Chat-Queued)
Web search (opt-in)
Default is model-only — no internet egress, predictable cost and latency. Same posture as the studio chat toggle. Check GET /api/meta → search_enabled for whether this deployment has SearXNG configured.
- Body:
"search": true(studio parity) or"web_search": true - Header:
X-Galtops-Web-Search: true(when the SDK body is fixed). Body wins over header when both are present - Response includes
galtops.web_search(used,results,degraded,available). Strict OpenAI clients ignore unknown keys - Asking for search when it is not configured → 400. SearXNG unreachable → answer continues model-only with
degraded: true
# Model-only (default)
curl -sS https://YOUR-HOST/v1/chat/completions \
-H "Authorization: Bearer YOUR_CHAT_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "general",
"messages": [{"role":"user","content":"Summarise quantum entanglement in two sentences."}]
}'
# Opt-in web search
curl -sS https://YOUR-HOST/v1/chat/completions \
-H "Authorization: Bearer YOUR_CHAT_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "general",
"search": true,
"messages": [{"role":"user","content":"What happened in AI regulation this week?"}]
}'Vision + PDF
Pick a model that reads images (catalogue label / vision / vl name). Child-safety scanning still runs on every image — that floor is never liftable.
OCR: this API does not run Tesseract. Text-layer PDFs are extracted; embedded rasters go to vision; pure scans should be sent as images (or rendered page screenshots) to a vision model.
# Image (data URI) — Python sketch
import base64, json, urllib.request
img_b64 = base64.b64encode(open("photo.jpg","rb").read()).decode()
body = {
"model": "vision", # or your deployment's vision id
"messages": [{
"role": "user",
"content": [
{"type": "text", "text": "Describe this and list any text you see."},
{"type": "image_url", "image_url": {
"url": f"data:image/jpeg;base64,{img_b64}"
}},
],
}],
}
req = urllib.request.Request(
"https://YOUR-HOST/v1/chat/completions",
data=json.dumps(body).encode(),
headers={
"Authorization": "Bearer YOUR_CHAT_KEY",
"Content-Type": "application/json",
},
)
print(urllib.request.urlopen(req).read().decode())
# PDF text extract (file part)
# content item:
# {"type":"file","file":{"filename":"brief.pdf",
# "file_data":"data:application/pdf;base64,..."}}Context cache & shared learning
When the organisation's context (or history / learning) byte cap is exceeded on write, the platform continuously evicts the least-recently-used sealed entries until the new entry fits — newest stays, oldest goes. TTL is only a backstop.
Personal cache is always private-to-seat (u/… partitions, seat-bound seal). Completions for a user only use that seat's context, history and personal learning — never another seat's. Clear your own seat cache anytime from the profile page (end of day is fine); that does not touch org shared learning.
Shared learning (o/…) is the only org-wide pool. It defaults on and can be turned off by an org admin in the organisation console (/api/org/shared-learning). When off, assistants neither read nor write org-shared learning; seat-private memory continues. Org admins can still purge shared learning or force-purge every seat (type-to-confirm). Never cross-org.
Stubbed and refused
POST /v1/embeddings→ 501. Not implemented — an error beats fabricated vectorsPOST /v1/completions,/v1/responses,/v1/images/*→ OpenAI-shaped 404 with a message pointing at the right surface- Remote
http://image_urland private / metadata hosts → 400. Publichttps://is fetched SSRF-safely
Differences from stock OpenAI
- Unknown model on completions → 404, not a silent upstream 502
- 429 includes
Retry-After - Floors run on every user/tool message and on search/PDF text before inference
- Web search and
galtops.*are Galtops extensions — optional fields clients may ignore - No Tesseract OCR — text-layer PDFs and embedded rasters only; pure scan pages need screenshots + vision
Also see
Editor setup: repo docs/integrations.md. Image graphs: /docs/comfy. Studio cards: /docs/api.