Features overview
What the Cruxy gateway gives you: OpenAI-compatible chat on three tiers, specialized model endpoints, and memory and rules you control.
Cruxy is an OpenAI-compatible LLM gateway. You call one API at
https://api.cruxy.ai with one key and name a model tier instead of a provider
model. Cruxy-native fields are additive and namespaced under a cruxy key, so
an OpenAI client keeps parsing the response and ignores what it does not know.
Three tiers and auto
You pass a tier id as the chat model. The gateway resolves the tier to an
upstream model on the server; an upstream provider model is never accepted or
returned, so the tier is the stable contract your code depends on.
| Tier | Profile | Default reasoning | Reasoning control |
|---|---|---|---|
kavi | Deep | high | On or off: any value except none turns thinking on. |
vaani | Balanced | low | Graded: low, medium, and high are different depths. |
mira | Fast | none | Graded: low, medium, and high are different depths. |
The reasoning columns are the shipped defaults. GET /api/v1/models reports
each tier's live reasoning.default_effort and reasoning.graded, along with
its context window, output cap, and pricing; Models
shows how to read the catalog at runtime, and
Choosing a tier compares the tiers.
A reasoning tier thinks inside the same max_tokens budget as its answer, and
the thinking is not returned as content. A small max_tokens on kavi can be
spent entirely on thinking, ending with finish_reason: "length" and empty
content. Send reasoning_effort: "none" for a short, direct answer, or leave
max_tokens unset to keep the tier's cap; see
Reasoning effort.
Send model: "auto" to let the server-side router pick the tier from the
request. It resolves to a concrete tier before billing and before the upstream
call, and the tier that served the request comes back as cruxy.routed_tier.
An auto request may be budget-downgraded to mira, so read routed_tier
rather than assuming it; Auto routing covers the
router, and Rate limits and budgets explains the
budgets behind the downgrade.
What you can call
| Area | Endpoints | What it does |
|---|---|---|
| Chat | POST /api/v1/chat | OpenAI-compatible chat with Cruxy features: Streaming, tool calling (see Define tools), Memory, Standing rules, and attached files. |
| Native chat | POST /api/v2/chat | The Cruxy-native wire: named SSE events that always end in a finish or error frame. |
| OpenAI wire | POST /v1/chat/completions, GET /v1/models | The plain OpenAI protocol for OpenAI clients and evaluation harnesses, with none of the Cruxy-native features. |
| Models | GET /api/v1/models | The tier catalog. |
| Token counting | POST /api/v1/tokens/count | The input tokens a chat request would bill, counted without inference and not billed. |
| Embeddings | POST /api/v1/embeddings | 1024-dimension vectors from cruxy-embed. |
| Rerank | POST /api/v1/rerank | Documents ranked against a query by cruxy-rerank. |
| Moderations | POST /api/v1/moderations | Content classification by cruxy-guard. |
| Feedback | POST /api/v1/feedback | A signal about an earlier call, joined to it by request_id. |
| Files | /api/v1/files | Uploads that a chat message attaches with file_ids; chat reads text, PDF, and Word (.docx) files. |
| Conversations | /api/v1/conversations | Conversation history stored server-side, private to its author, with branches. |
| Memory | /api/v1/memories, /api/v1/vaults | Stored facts, personal, organization-wide, or shared in a vault, that chat can recall. |
| Rules | /api/v1/rules, /api/v1/rules/resolved | Standing instructions for chat, set for your organization or a vault. |
| Prompts | /api/v1/prompts | Named prompts with immutable versions. |
| Evals | /api/v1/evals/suites | Test suites run against a tier; every case is a billed completion. |
| Account | /api/v1/me, /api/v1/profile, /api/v1/limits | Your identity, profile, and live limits. |
| Organization | /api/v1/org/members, /api/v1/workspaces, /api/v1/logs | Members, invitations, workspaces with spend caps, and request-log metadata. |
| Sign-in | /api/v1/device/code, /api/v1/device/token | Device login, which issues API keys; see Get your API key. |
| Status | GET /api/status, GET /api/health, GET /api/ready | Public platform status and health probes. |
Every /api/v1 endpoint is also served under /api/v2 with identical
behavior, and this site documents the /api/v1 path. Chat is the one
exception: POST /api/v2/chat is a different wire from POST /api/v1/chat.
API Reference has every operation with its exact
request and response shape.
Memory and standing rules
Two chat features add context beyond the messages you send. You control both per request, and their defaults depend on how the key was issued:
- On by default for a signed-in credential: what a person gets by signing in to the Cruxy web app, desktop, the CLI, or mobile. A key minted by device login or OAuth login is a signed-in credential whichever client ran the flow, a third-party tool included.
- Off by default for a developer API key or a headless key, which opts in per request.
GET /api/v1/limits reports which kind a key is as bucket: subscription is
a signed-in credential, and apikey and headless are not. A server, or
anything that serves people other than the key's owner, should use a developer
API key; see Get your API key.
To get the same behavior from any key, set both on every request.
Memory
Memory has two independent sides, each set in the request's memory object:
- Recall (
recall) adds the stored memories most relevant to the turn as background context and reports them incruxy.memory_recall: the scope and key of each, never the stored value. - Capture (
capture) lets the gateway store a durable fact from the turn, such as a stated preference, and reports it incruxy.memory_capture. No field means nothing was stored. Captures go to your personal memory, or to a vault you can write when the request names one, never to organization-wide memory. Content carrying an email address, phone number, or card number is dropped before any write.
true needs a key whose allowed scopes include memory; otherwise the request
fails with 403 key_scope_forbidden. false needs no scope. Pin
Cruxy-Version: 2026-09-26 on every request that relies on false, so a
gateway that predates the field refuses the request instead of ignoring it.
GET /api/v1/memories lists what is stored, and
DELETE /api/v1/memories/{id} removes an entry. Memory
covers recall, capture, and the scope a key needs.
Standing rules
Standing rules are instructions your organization sets for chat, and a vault
can have its own. They are injected into the turn as defaults that the user's
own message overrides. A developer API key gets them only when the request sends
rules: true, or when the key's allowed scopes name the rules family. Any key
may send rules: false to decline them for a turn.
When rules apply, the response carries cruxy.rules_applied with counts and
sources, never the rule text. GET /api/v1/rules/resolved returns the exact
rules a turn would get. Injected rule text counts as input tokens.
Standing rules covers opting in and what gets
injected.
This request recalls memory, stores nothing new, and declines standing rules:
curl https://api.cruxy.ai/api/v1/chat \
-H "Authorization: Bearer $CRUXY_API_KEY" \
-H "Content-Type: application/json" \
-H "Cruxy-Version: 2026-09-26" \
-d '{
"model": "vaani",
"stream": false,
"memory": { "recall": true, "capture": false },
"rules": false,
"messages": [
{ "role": "user", "content": "Which time zone should my meeting use?" }
]
}'const res = await fetch('https://api.cruxy.ai/api/v1/chat', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CRUXY_API_KEY}`,
'Content-Type': 'application/json',
'Cruxy-Version': '2026-09-26',
},
body: JSON.stringify({
model: 'vaani',
stream: false,
memory: { recall: true, capture: false },
rules: false,
messages: [{ role: 'user', content: 'Which time zone should my meeting use?' }],
}),
})
const completion = await res.json()
console.log(completion.message.content)
console.log(completion.cruxy.memory_recall) // undefined when nothing was recalledVersioning
The API is versioned by date. Send Cruxy-Version: YYYY-MM-DD to pin a
version, or omit it for the server's current default; an unknown or malformed
value is rejected with 400. Every response, errors included, echoes the
resolved version in its Cruxy-Version header.
A breaking change, such as a change to streaming frame order, ships under a new
dated version. Additive fields, including new cruxy.* fields, ship without
one, so ignore JSON fields you do not recognize.
Changelog records what changed.
Next steps
- Get your API key: mint the key every call needs.
- Quickstart: make your first chat call.
- Streaming: read a chat completion as it is written.
- Errors and retries: handle failures.