Known limitations

What the Cruxy API does not do today, why each limit matters for your code, and the workaround to use until it changes.

These are the limits you are most likely to hit when you build on the API. Each entry says what happens, why it matters, and what to do instead. When the API changes, the Changelog records it by version.

Kavi's thinking spends max_tokens and isn't returned

  • What: kavi reasons by default, at reasoning_effort high, and a reasoning tier writes its thinking inside the same max_tokens budget as its answer. POST /api/v1/chat and POST /v1/chat/completions do not return the thinking. POST /api/v2/chat returns it as a separate reasoning string, but no wire reports a reasoning-token count.
  • Why it matters: A small max_tokens on kavi can be spent entirely on thinking. The call ends with finish_reason: "length" and empty content, and on the v1 wire nothing in the response shows where the tokens went.
  • Workaround: For a short, direct answer, send reasoning_effort: "none". To keep the reasoning, leave max_tokens unset, which gives the tier's cap (8192 on kavi). Treat finish_reason: "length" with empty content as a spent budget, not an empty answer. See Reasoning effort.
# reasoning_effort "none" turns kavi's thinking off, so the whole
# max_tokens budget goes to the answer.
curl https://api.cruxy.ai/api/v1/chat \
  -H "Authorization: Bearer $CRUXY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kavi",
    "reasoning_effort": "none",
    "max_tokens": 256,
    "messages": [
      { "role": "user", "content": "In one sentence, what is a monsoon?" }
    ]
  }'

Non-streaming calls have a 90-second ceiling

  • What: With stream: false, the gateway makes one attempt, bounded by the tier's deadline: 90 seconds on kavi and vaani, and 45 seconds on mira. Past it, the call is cancelled and answered 504 upstream_timeout. It is not billed, and the gateway does not retry it.
  • Why it matters: A long kavi turn, with reasoning on and a large output, can need more than 90 seconds. The same request takes as long again on a retry, so retrying it unchanged times out every time.
  • Workaround: Stream long turns with stream: true: a stream may run for up to five minutes. Otherwise, ask for less with a lower max_tokens or reasoning_effort. See Reliability.

Signed-in keys expire in 90 days, and you can't revoke one

  • What: A key from device login or native OAuth login is a signed-in credential. It stops working at its expires_at, 90 days after issue by default. Use does not extend it, and there is no refresh grant. Its holder can neither rotate nor revoke it: it ends at expires_at, when its organization membership ends, or when Cruxy support revokes it.
  • Why it matters: A signed-in key that leaks stays valid until one of those happens. And a tool that stores one stops working the moment it expires, with 401 unauthorized, the same answer as a revoked key.
  • Workaround: On a server, use a developer API key, created in the Cruxy Console: it does not expire, and you rotate or revoke it there. In a person's own tool, store expires_at with the key and prompt for a new login before it passes. If a signed-in key leaks, ask Cruxy support to revoke it. See Get your API key.

Tool-call IDs may not use OpenAI's call_ format

  • What: A tool call's id is a string with no documented format. It is not guaranteed to start with the call_ prefix OpenAI uses, even though the examples in these docs show call_abc123.
  • Why it matters: Code that validates, parses, or generates ids on the call_ pattern can reject a real call or fail to match its result. When the model makes several calls in one turn, tool_call_id is the only thing that says which result answers which call.
  • Workaround: Treat each id as opaque. Copy it unchanged into the tool_call_id of your result, key any lookup on the whole string, and never build an id yourself. See Handle tool calls.

No per-language list for Indic languages

  • What: Cruxy supports 20+ Indic languages, but it publishes no list of which ones, and the tier catalog at GET /api/v1/models has no language field.
  • Why it matters: Neither the docs nor the API can confirm that a specific language is supported, or how well each tier handles it.
  • Workaround: Before you launch in a language, test it on each tier you plan to use, with prompts from your own product. An eval suite under /api/v1/evals/suites runs the same cases against the tier you name; each case is billed as a chat completion.

Next steps

Was this page helpful?