Changelog

What changed in the Cruxy API and its docs, newest first: each dated release by its API version, plus the additive changes that need no pin.

API version2026-10-07

The Cruxy API is date-versioned: info.version in the spec is a date, and every response echoes the version that served it in the Cruxy-Version header, so you can always confirm which version served a call. Send Cruxy-Version: YYYY-MM-DD to pin one; see Request IDs and metadata.

A new dated version ships for a breaking change, such as a change to streaming frame order. A date can also gate a new request field whose silent absence on an older gateway would make a response misrepresent what it used, and the four releases since 2026-06-13 each do that. Ordinary additive fields ship without a new version, so the spec dates neither them nor the endpoints added alongside them; Additive changes since 2026-06-13 lists both. Entries use the Keep a Changelog categories (Added, Changed, Fixed, and Deprecated), and a release lists only the categories it touched.

2026-10-07

The current version.

Added

  • A lifetime for uploaded files. POST /api/v1/files takes an optional expires_in, from 60 to 604800 seconds (7 days), and returns the moment it ends as expires_at. Once it passes, the file is gone to every read, and its bytes are deleted within 15 minutes. Setting expires_in requires Cruxy-Version: 2026-10-07 or later; without the pin the upload is 400 invalid_request and nothing is stored. A file uploaded without it lives until you delete it, as before.

2026-10-06

Added

  • Files on stored conversation messages. POST /api/v1/conversations/{id}/messages takes file_ids on a user message, at most 20 distinct files, and every read of the conversation returns them. It requires Cruxy-Version: 2026-10-06 or later; without the pin, file_ids is 400 invalid_request with required_version. The date is one day later than chat's on purpose: a gateway that knows only 2026-10-05 reads file_ids in chat but would drop them from an append.

2026-10-05

Added

  • Files in a chat turn. A user message on POST /api/v1/chat or POST /api/v2/chat can carry file_ids, naming files you uploaded with POST /api/v1/files, and the gateway reads each one into the turn: UTF-8 text, PDF and Word (.docx) documents as the text read from them at upload, and JPEG, PNG, and WebP images on a tier that reads images. It requires Cruxy-Version: 2026-10-05 or later; without the pin, file_ids is 400 invalid_request with required_version. A file's tokens are billed on every request that sends it, and POST /v1/chat/completions refuses file_ids.
  • cruxy.files_omitted, a top-level files_omitted on POST /api/v2/chat, lists the files on earlier messages that a turn left out, and why.
  • Three 400 codes for a file that cannot be read into a turn: file_not_text, file_too_large, and image_not_supported, which names the tiers that read images in vision_tiers. See Errors and retries.

2026-09-26

Added

  • Per-request memory controls on chat. memory: {"recall": …, "capture": …} on POST /api/v1/chat and POST /api/v2/chat turns automatic recall and capture on or off for one request; left out, each side follows the credential's default. Pin Cruxy-Version: 2026-09-26 before relying on false: a gateway that predates the field ignores it and captures anyway, while a pinned request is refused by such a gateway instead. See Memory.

Additive changes since 2026-06-13

These need no version pin, and the spec does not date them. Each is in the 2026-10-07 spec and was not in the 2026-06-13 spec.

Added

  • The plain OpenAI wire: POST /v1/chat/completions and GET /v1/models, for OpenAI clients and evaluation harnesses. It carries none of the Cruxy-native chat features.
  • Conversations under /api/v1/conversations: history stored on the server, with search, archiving, and branches.
  • Standing rules: GET, PUT, and DELETE /api/v1/rules, GET /api/v1/rules/resolved, and a vault's own rules at /api/v1/vaults/{id}/rules, with the chat rules switch and cruxy.rules_applied. See Standing rules.
  • Chat request fields tool_choice, vault_id, and mentioned_vault_ids, and the response signals cruxy.memory_recall, cruxy.memory_capture, and cruxy.undeclared_tool_replay. See Request IDs and metadata.
  • Eval suites, cases, and runs under /api/v1/evals.
  • Invitations and memberships: /api/v1/invitations, /api/v1/org/invitations, and /api/v1/org/memberships.
  • Native sign-in: POST /api/v1/auth/oauth/start and POST /api/v1/auth/oauth/token. A key minted this way is a signed-in credential, as from device login.
  • The X-Request-Id header, declared on every response: a correlation id that you can set on the request. See Request IDs and metadata.
  • A public status document at GET /api/status. See Reliability.
  • GET /api/v1/service-token/self, which describes the calling service token.
  • Tier catalog fields on GET /api/v1/models: created, owned_by, profile, reasoning (default_effort and graded), and supports_vision.
  • results[].cruxy.hazard_codes on a flagged moderation result.
  • org on the device-login token response: the organization the new key is bound to.
  • content_type on an uploaded file, plus text_status and text_tokens for a PDF or Word document, whose text is read once at upload.
  • Error codes: client_closed_request, conversation_forbidden, conversation_not_found, eval_case_not_found, eval_run_not_found, eval_suite_not_found, eval_suite_slug_exists, input_not_countable, invalid_tool_schema, invitation_not_found, key_read_only, key_scope_forbidden, key_spend_cap_exceeded, limits_unavailable, message_not_found, model_not_allowed, moderation_rejected, provider_not_supported, redirect_uri_not_allowed, request_not_found, rules_forbidden, rules_too_large, server_shutting_down, and vault_external_id_conflict. See Errors and retries.

Changed

  • The production hostname is https://api.cruxy.ai. https://api.cruxy.in is the legacy hostname for the same service, and is still supported.
  • The spec documents each endpoint once, under /api/v1. Every public endpoint is also served under /api/v2 by the same handler, with the same authentication, rate limit, and bodies. Chat is the exception: POST /api/v2/chat is the separate Cruxy-native wire.

Deprecated

  • scope_unsupported is retired. It is never sent, and it stays in the error vocabulary so the string is never reused.

2026-06-13

This release types the surfaces you build against and documents the limits and failure modes the gateway already enforced.

Added

  • Model catalog metadata on Models (GET /api/v1/models): each tier advertises its context_window, max_output, latency_target_ms, and pricing, so you read a tier's limits at runtime instead of hardcoding them. Pricing is provisional; read it from the live response, never from a copy.
  • The full finish_reason enum on Chat (stop, tool_calls, length, and content_filter) for both streaming and non-streaming responses, with tool_calls as the signal to answer message.tool_calls and continue the turn.
  • Per-request batch limits on the specialized endpoints: Embeddings, Rerank, and Moderations accept at most 512 inputs, with the whole body capped at 64 KiB; exceeding either ceiling is a 400. Batch a larger corpus across multiple requests.
  • Per-type feedback payloads on Feedback: type fixes the shape of payload, and thumbs, edit_accepted/edit_rejected, and test_result each carry their own schema, so the reference documents the exact fields for each event.
  • Mid-stream failure behavior for streaming Chat: a response that ends without the data: [DONE] terminator is a failed, incomplete completion. The 200 is already committed, so no error frame follows; treat a stream that stops before [DONE] as a failure and retry it.

Changed

  • The non-streaming chat response is now typed and flattened. Chat with stream: false returns a ChatCompletionResponse: the assistant reply is the top-level message with a sibling finish_reason, not an OpenAI choices[] array; read message.content directly. Streaming responses are typed as ChatCompletionChunk. This replaces the previously untyped 200 body.
  • Feedback validation is stricter. Feedback rejects unknown payload keys, wrong types, and bad enum values with a 400, and a stored event's payload is consent-gated and redacted rather than persisted verbatim.

Next steps

  • API Reference: every endpoint, typed and interactive.
  • Models: the live tier catalog and its metadata.
  • Errors: the 400/401/429 shape these changes reference.

Was this page helpful?