> Keiro Labs API documentation - Changelog
> Page: https://docs.keirolabs.ai/changelog.html
> Markdown: https://docs.keirolabs.ai/changelog.md
> Agent index: https://docs.keirolabs.ai/llms.txt
> API base URL: https://api.keirolabs.ai/v1
> Auth: send "Authorization: Bearer <api-key>" with a key created in the
> Keiro console (https://console.keirolabs.ai/api-keys). Use credentials saved by
> `keiro setup`, or resolve the key from a secret manager or an owner-only
> secret file and pass it to the client explicitly. Never read another
> provider's variable, and never put raw key material in environment
> variables, code, docs, or logs.

# Changelog

This changelog covers public developer-docs and API-contract changes.

Entries summarize customer-visible documentation and compatibility updates for
the paid beta public API. Private operational and deployment notes stay out of
the public changelog.

## 2026-08-10

- New setup guides for two additional coding agents: [OpenCode](opencode.md)
  registers Keiro as an OpenAI-compatible provider in `opencode.json`, and
  [Pi](pi.md) adds a Keiro provider entry to `~/.pi/agent/models.json`. Both
  pages appear in the Build navigation alongside the existing Codex,
  Claude Code, and Omnigent guides.

## 2026-08-08

- `/v1/messages` usage adopts Anthropic's native disjoint input-side
  semantics for all callers, effective with the next deployment:
  `input_tokens` excludes the cached portions of the prompt, and
  `input_tokens + cache_read_input_tokens + cache_creation_input_tokens`
  equals the full prompt. The previous additive-subset shape — the full
  inclusive count in `input_tokens` with the cache fields as subsets of it —
  is retired. Clients that read `input_tokens` as the inclusive total should
  sum the three input-side fields to recover it; responses with zero cache
  activity are unchanged. See [Messages](messages.md).
- Prompt tokens served from a prompt cache now bill at 0.1x the model's
  input rate on every public model. Cache writes carry no surcharge and
  bill at the standard input rate. The usage fields that report cached
  prompt portions are unchanged; only the billed amount drops. See
  [Usage and billing](usage-billing.md#prompt-cache-pricing).

## 2026-08-05

- Requests refused by a platform-internal capacity gate now return
  `503 server_error` with the new code `route_capacity`, a retriable
  condition carrying a `Retry-After` horizon. These refusals previously
  surfaced as `502 upstream_server_error`, wrongly implying an upstream
  dependency; no upstream is involved and an unchanged retry usually
  succeeds within seconds. `provider_unavailable` remains reserved for
  genuine upstream unavailability.

## 2026-08-02

- `eb1-preview` and `eb1-efficient-preview` now report a `context_window`
  (and `max_input_tokens`) of `400000` in `/v1/models`, up from `120000`;
  `eb1-fast-preview` reports `240000`. The previous figures were aggregated
  over the smallest reachable execution target, which is only correct for
  fixed ensembles; routed requests are admitted whenever any evaluated
  target fits, so the published number understated the window the API was
  already serving. The published figure remains a floor the API honors on
  every request; `eb1-frontier-preview` is unchanged at `400000`. Existing
  Codex setups pick up the new windows on their next setup run.
- Context-overflow errors now report the enforced bound. The `M` in
  `prompt is too long: {N} tokens > {M} maximum` (and
  `details.context_window`) is the largest limit the rejected request was
  actually evaluated against, in the same units as `{N}`, rather than the
  requested model's published window; `{N} > {M}` holds on every such error,
  so clients that trim by the reported gap now trim the right amount.

## 2026-07-29

- Model IDs the API does not offer now return a uniform `404 model_not_found`
  that names the public IDs, with `403 model_not_available` reserved for
  public models your plan does not include. Previously some unknown IDs
  surfaced as availability errors.
- Streamed Messages responses carry `thinking` summary blocks, delivered
  through `thinking_delta` events, when extended thinking is enabled. These
  blocks contain summary text constructed by the API and are unsigned; do not
  round-trip them as provider-signed thinking blocks.
- `POST /v1/messages/count_tokens` now applies the same per-part minimums to
  image and document blocks that admission and billing apply, so multimodal
  estimates rise to match what is charged.
- Validation errors on `/v1/messages` now name fields in Messages coordinates
  (`messages[i].content[j]`) instead of the Responses spelling.
- `/v1/messages` error bodies now carry `error.request_id`, matching the
  `X-Request-Id` header, completing the 2026-07-15 error-identification
  contract on the Messages surface.
- The Claude Code installer verifies the key with one authenticated request
  before storing it, reports incomplete setups honestly, and gains an
  uninstall command.
- `eb1-frontier-preview` now reports a `context_window` of `400000` in
  `/v1/models`, up from `128000`. The raised figure remains a floor the API
  honors on every request: admission continues to validate against every
  execution target with the same safety margins as before. The `120000`
  windows on `eb1-preview`, `eb1-fast-preview`, and `eb1-efficient-preview`
  are unchanged, as are the legacy request identifiers accepted for
  compatibility. Requests remain subject to the organization's per-minute
  token budget (`request_exceeds_capacity`, see 2026-07-19). Existing Codex
  setups pick up the new window on their next setup run.
- Routed preview requests rejected purely for context size now return
  `400 invalid_request_error` with `code` `context_length_exceeded`, matching
  every other context-overflow rejection. Previously this one path reported
  the generic `request_requirements_unsatisfied`. That code is now reserved
  for requests whose input, tool, reasoning, or media requirements cannot be
  satisfied together for reasons beyond context size alone.

## 2026-07-26

- Stream lifetimes are now documented per-effort time entitlements instead of
  one flat internal timeout. A stream that is actively working is never ended
  for taking long: streams end early only on a documented idle timeout (90
  seconds without model activity; 120 seconds at `xhigh` and above) or on the
  wall-clock ceiling for the requested reasoning effort (5 minutes at
  `none`/`minimal` up to 60 minutes at `max`/`ultra`). Requests that do not
  set a reasoning effort resolve no lower than the `medium` row (10 minutes);
  `eb1-frontier-preview` defaults to the `max` row. Previously, long runs
  could be interrupted near 600 seconds even while the model was still
  working.
- When a stream deadline fires, the run ends with one honest terminal instead
  of a spurious error: Responses streams carry `response.incomplete` with
  `incomplete_details.reason` of `stream_idle_timeout` or
  `stream_ceiling_timeout`; Chat Completions reports `finish_reason` `length`
  and Messages reports `stop_reason` `max_tokens`. Tokens consumed before the
  stop are billed; the terminal event is truthful about why the run stopped.
  See [Streaming](streaming.md#stream-lifetime-and-time-entitlements).

## 2026-07-22

- The discoverable model catalog is `eb1-preview`, `eb1-frontier-preview`,
  `eb1-fast-preview`, and `eb1-efficient-preview`, superseding the naming
  contract published on 2026-07-20. The `eb1-preview-efficient`,
  `eb1-preview-fast`, and `eb1-preview-delta` identifiers remain accepted on
  requests and in stored conversations with unchanged behavior and pricing,
  but no longer appear in `/v1/models`, Console menus, CLI listings, or Codex
  setup. Responses to requests that use one of those identifiers name the
  canonical id; responses to `eb1-preview-delta` requests name
  `eb1-delta-preview`, which remains callable but does not appear in
  discovery.
- Invalid model-exclusion inputs now return the governed, non-retriable
  `400 invalid_request_error` envelope with `code` `bad_request`. Previously
  these caller-fixable requests could be serialized as a retriable
  `502 upstream_error`. Synchronous responses now carry
  `x-should-retry: false`; synchronous bodies and streaming error frames carry
  `retryable: false` with no retry horizon.

## 2026-07-20

- Public discovery, Console, CLI, and Codex now use one four-model naming
  contract: `eb1-preview`, `eb1-preview-efficient`, `eb1-preview-fast`, and
  `eb1-preview-delta`. Existing stored configurations using earlier preview
  spellings remain request-compatible, but new configuration and response
  identity use the current IDs.
- Keiro 0.12.22 requests safe reasoning summaries for registered eb1 models
  and displays available segments while a response is in progress. These
  segments are terminal activity, not assistant answer text: they do not enter
  conversation history, copied code blocks, or piped stdout. Python callers
  can consume the same validated stream separately with
  `ModelsAPI.responses_stream(on_reasoning_summary=...)` or its admin sibling.
  Direct-provider requests receive no implicit summary setting.

## 2026-07-19

- Responses usage now reports provider-supplied prompt-cache reads and writes
  in `input_tokens_details.cached_tokens` and `cache_write_tokens`, instead of
  always reporting zero. Both are subsets of `input_tokens` and do not change
  `total_tokens`. The Console chat tester preserves those reported cache-read
  counts and `output_tokens_details.reasoning_tokens` in a compact Token
  details disclosure when those subsets are positive; required structural
  zeroes remain undisclosed because they do not prove provider provenance. It
  labels arithmetic totals and remainders as derived and does not fabricate
  system-prompt, history, user-message, or tool-schema buckets that the API
  does not separately report.
- Published context windows now match the limit the API enforces end to end.
  `eb1-preview`, `eb1-efficient-preview`, and `eb1-fast-preview` report a
  `context_window` of `120000` in `/v1/models`, down from the previously
  published `128000`; `eb1-frontier-preview` is unchanged at `128000`.
  Requests between the two figures could previously be rejected with a
  context-overflow error despite sitting inside the published window; the
  published figure is now a floor the API honors on every request.
- Requests whose selected model cannot satisfy every input, tool, reasoning,
  and context requirement now fail before dispatch with non-retriable HTTP
  400 code `request_requirements_unsatisfied`.
- Requests whose token estimate exceeds a full minute of the organization's
  token-per-minute budget now return a terminal
  `400 invalid_request_error` with `code` `request_exceeds_capacity`,
  instead of a `429` rate limit. The old `429` carried a `Retry-After`
  header even though no unchanged retry could ever succeed, trapping
  status-driven clients in an infinite retry loop. The new response carries
  `x-should-retry: false`, no retry horizon, and no
  `x-ratelimit-reset-*-tokens` header; the message and
  `details.dimension: "token_budget_request"` are unchanged. Reduce the
  input or `max_output_tokens`, or raise the limit, and resend.

## 2026-07-18

- Usage objects on OpenAI-format surfaces now itemize reasoning tokens and
  follow the standard arithmetic exactly. Chat Completions usage gains
  `completion_tokens_details` (with `reasoning_tokens`), and `total_tokens`
  always equals `prompt_tokens + completion_tokens`, with reasoning counted
  inside `completion_tokens`. Previously, reasoning-heavy requests could
  report a `total_tokens` larger than the visible sum with no breakdown.
- Responses usage now matches the standard `ResponseUsage` schema:
  `input_tokens`, `input_tokens_details.cached_tokens`, `output_tokens`,
  `output_tokens_details.reasoning_tokens`, and `total_tokens`
  (`= input_tokens + output_tokens`). The former non-standard flat
  `reasoning_tokens` key and the `prompt_tokens`/`completion_tokens` aliases
  are removed. Strict typed SDK clients that previously failed to validate
  usage now parse it; clients reading the flat keys must switch to the
  nested fields.
- `/v1/messages` `output_tokens` now includes reasoning tokens, matching the
  Anthropic convention that thinking is part of output.
- `usage` detail objects report `cached_tokens: 0` for now; prompt-cache
  accounting is not yet reflected in usage counts.

## 2026-07-17

- Retired the `/v24b` versioned endpoint path. It no longer differs from the
  current default deployment, so requests to `/v24b/v1/*` now return
  `410 endpoint_retired` instead of routing to current-default weights under a
  versioned label. Use the default API (`/v1`).
- The Keiro CLI no longer offers a `v24b` endpoint preset. `keiro endpoint
  v24b`, saved v24b gateway URLs, and explicit v24b URLs surface the
  retirement guidance instead of binding to the default gateway.

## 2026-07-15

- Missing pricing for an otherwise valid model now returns the governed,
  non-retriable `404 model_not_found` envelope with `x-should-retry: false`.
- Chat Completions stream error frames now nest a full `error` object
  (code, type, message, retry signals, `retryable`, `request_id`, and
  `details` on limit denials) alongside the existing flat fields.
  OpenAI-compatible SDKs surface it as a typed error instead of failing to
  parse the frame. The flat fields are deprecated (removal is at least two
  releases out and gated on usage telemetry); Messages and Responses stream
  error frames gain the same `details` object on limit denials.
- `/v1/messages` responses now also carry a `request-id` header (an alias of
  `X-Request-Id`) so Anthropic-compatible SDKs populate `.request_id`.
- Responses that produced no output because reasoning consumed the entire
  completion budget now report `status: "incomplete"` with
  `incomplete_details.reason: "max_output_tokens"` and a `warning` naming
  the fix, instead of claiming success; Chat Completions report
  `finish_reason: "length"`. Billed usage is unchanged and still reported.
- Error messages no longer carry `[Error NNNN]` / `[Recovery: …]` bracket
  furniture; recovery guidance appears as a plain sentence only when it
  applies to the specific failure. Message text remains non-contractual.
- Corrected upstream authentication failures to a fixed `502` with `code`
  `upstream_auth_error`. Previously an upstream `401` could pass through as
  your fault; SDKs raised `AuthenticationError` and stopped retrying for a
  platform-side condition. Your API key is valid when you see this code.
- Replaced the `401` `code` `authentication_error` (which duplicated `type`)
  with three specific codes: `missing_authorization`,
  `bearer_scheme_required`, and `invalid_api_key` (with a redacted
  `details.key_hint`). Code-matching clients keep working: the old code's
  value remains as the error `type`. All `401` responses now carry
  `WWW-Authenticate: Bearer`.
- `error.param` is now populated with the offending field name where known;
  previously documented as always `null`.
- Documented every error code with per-code anchors, added `413` and `415`
  to the status table, and removed the never-emitted `408` row.
- Added retry-signal headers to error responses: `retry-after-ms`
  (milliseconds, fractional precision) on retriable denials and
  `x-should-retry: false` on denials an unchanged retry cannot clear.
  Deterministic denials also carry `"retryable": false` in the error body.
- Error responses now include `error.request_id`, matching the
  `X-Request-Id` header; stream error frames carry it on the Messages and
  Responses wires.

## 2026-07-10

- Added an API reference index and dedicated guides for Messages, function
  tools, image input, API-key lifecycle, usage and billing, and Codex setup.
- Reworked Quickstart into an install-to-output workflow with one credential
  policy: saved Keiro credentials, interactive curl/Python secrets, and
  secret-file references for other runtimes.
- Reconciled API-key guidance with the console's create, staged-replacement,
  and delete/revoke workflow.
- Added contextual related-page paths throughout the documentation.
- Corrected the subprocessor description: authenticated docs are served by
  Keiro-operated services, while Netlify hosts the public website,
  early-access intake, and published status artifact.

## 2026-07-01

- Documented idempotent requests, including the `Idempotency-Key` header, the
  `X-Idempotent-Replay` and `X-Original-Request-Id` replay headers, and
  `409 idempotency_key_conflict` conflicts.
- Documented the `409` status code and clarified that the error `param` field is
  always `null`.
- Added a Responses streaming event taxonomy.
- Documented Netlify's hosting purpose for the public website, early-access
  intake, and published status artifact.

## 2026-06-25

- Added shared Keiro Labs web-surface tokens to generated docs.
- Added skip links, active sidebar navigation, canonical URLs, Open Graph URLs,
  and table scrolling to the docs shell.
- Updated docs Markdown rendering for emphasis, blockquotes, h4-h6 headings,
  and in-list code fences.
- Updated rate-limit retry guidance to honor `Retry-After`.

## 2026-06-15

- Added initial paid beta public docs surface.
- Standardized runnable examples on one public base URL.
- Documented chat completions, responses, streaming, models, rate limits,
  errors, SDKs, support, and migration guidance.
- Kept local `keiro gui` scoped to chat UX only.

## Related pages

- [API reference](api-reference.md)
- [Quickstart](quickstart.md)
- [Subprocessors](subprocessors.md)
