Changelog
This changelog covers public developer-docs and API-contract changes.
On this page 1 of 28
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-09-25#
- When a platform dependency is temporarily unavailable, the
503provider_unavailableresponse now advertises a retry horizon between 5 and 15 seconds inRetry-After,retry-after-ms, and the stream frame'sretry_after_seconds, instead of one second. The value varies per request so clients refused together do not retry together. A stream that fails mid-response for the same reason now ends with the sameprovider_unavailableframe instead ofinternal_error. - Every other retriable response that carries
Retry-Afternow advertises a horizon that varies per request, so clients refused together do not retry together. The value is the previous horizon lengthened by up to a quarter, and by at most 30 seconds; it is never shorter than before, and a horizon of 60 seconds or less stays at or below 60 seconds so the OpenAI and Anthropic SDKs keep honoring it.retry-after-ms,error.details.retry_after_seconds, and the stream frame'sretry_after_secondscarry the same per-request value.Retry-Afterrounds it up to a whole second, so a response that sentRetry-After: 1now almost always sends2; readretry-after-msfor the spread. A503raised by a platform lookup outage now carriesretry-after-msalongsideRetry-After, and a503for a request that timed out waiting for routing capacity advertises at least the time it already waited instead of one second. See Retry-After. eb1-frontier-previewnow reports acontext_window(andmax_input_tokens) of869811in/v1/models, up from400000, and accepts prompts up to that size on every request: a prompt too long for the model the router would otherwise pick is now served by a model that holds it, instead of being refused. The other public eb1 models stay at400000. The figure is a floor the API honors whatevermax_output_tokensyou set, and a prompt past it returnscontext_length_exceededwith the limit. Requests remain subject to the organization's per-minute token budget (request_exceeds_capacity). Existing Codex, OpenCode, and Pi setups pick up the new window on their next setup run; Claude Code sessions keep the default model's400000window.
2026-09-10#
- Reasoning tokens on eb1 models are now itemized inside the output count on every surface:
output_tokens/completion_tokensis the delivered text plus the reasoning tokens,total_tokensis input plus output, and the reasoning share appears inoutput_tokens_details.reasoning_tokens(Responses) andcompletion_tokens_details.reasoning_tokens(Chat Completions); on Messages it is insideoutput_tokensas on Anthropic's own API. The reasoning count is the serving model's own report and is no longer clamped to the length of the reply, so the four counts on a record multiply by the rate card to exactly the amount billed. See "Reasoning tokens" under Token counting on the usage and billing page.
2026-09-09#
- A request whose body does not arrive in full within 60 seconds of the gateway starting to read it is now refused with
408and the new error coderequest_body_timeout. The error is retriable, and the OpenAI and Anthropic SDKs retry a408by default. Before this change a stalled upload held its connection open until the server restarted.
2026-09-07#
- Token counts on every eb1 model are now reported and billed in one unit, the
o200k_basemeter, independent of which model served the request. The same request body yields the sameprompt_tokens/input_tokenson every call,completion_tokens/output_tokensis the meter count of the delivered output, andtotal_tokensis their sum. Cache-read and cache-write counts are reported as proportional subsets of the metered prompt. The 400,000-token input window,/v1/messages/count_tokens, and rate-limit token accounting use the same unit. Counts you can reproduce locally withtiktoken'so200k_baseencoding. - Follow-up corrections to the meter: image and file requests now report the same prompt count that is billed (the per-part media minimum), tool results sent as content-part lists and custom tool outputs are counted, and a safety refusal the gateway authors carries zero usage on streams as it already did on synchronous requests.
POST /v1/messages/count_tokensnow counts an accepted body exactly as the request would be billed, tool definitions and tool history included; a body the Messages endpoint would reject still receives an advisory estimate.- A streamed request that ends early after delivering output (client disconnect or provider error) is billed for the delivered output and its prompt, in meter units, whether or not the provider reported usage; a stream that delivered nothing is not billed.
2026-09-06#
- Content-limit refusals now return
400 invalid_request_errorwith media-removal or compaction wording recognized by Claude Code. Image, PDF, replay-byte, and content-node limits are unchanged; depth-only errors remain count-free. - A request that reaches the platform while an internal service is restarting now completes on a live instance of that service when one is reachable within the request's retry budget. When several instances are down at once and none of them has yet been re-probed, the retries can still all land on down instances and the request fails. When no instance can take the request, the response is
503 server_errorwith the new coderoute_unavailable, a retriable condition carrying aRetry-Afterhorizon and the message "A platform service is restarting. Retry the request shortly." These failures previously surfaced as503 provider_unavailablewith "Capacity is temporarily limited", wrongly implying an upstream dependency and a capacity condition; no upstream is involved and an unchanged retry succeeds once the restart completes.provider_unavailableremains reserved for genuine upstream unavailability. - The 400,000-token eb1 input window uses unpadded cl100k prompt counts, including tool definitions and replay estimates. Gateway context-overflow errors now report their input count and binding limit in that same unit, so clients can compact and retry using consistent counts. Messages keeps the native
prompt is too long: N tokens > M maximumgrammar; provider rejections retain the provider's own counts.
2026-09-04#
- Function tools declared with
strict: truenow reach Claude-served legs withstrict: true, so the served model's tool-call arguments are validated against your schema there just as they already were on OpenAI-served legs; previously the flag was dropped on Claude legs without notice. This applies on/v1/responses,/v1/chat/completions, and/v1/messagesalike, and to thecustom+input_schematool spelling. Claude requires a strict schema to setadditionalProperties: falseand to list every property underrequired; a strict declaration whose schema does not meet that now returns400from a Claude-served leg instead of running without the guarantee. Tool declarations lead the prompt-cache prefix, so the first strict request after this change writes a new cache entry on Claude legs.
2026-09-03#
- Replayed tool history is validated once per request before any model is called. A duplicated
call_id, a result for an unknown call, a second result for the same call, or a call left unanswered before the next user turn now returns400with codeconversation_invariantand the offendingcall_id, on/v1/responses,/v1/chat/completions, and/v1/messagesalike, instead of a provider-specific error from whichever model was routed. - Streaming requests that replay function-call history are now served by Gemini-backed routes as well; they previously routed around Gemini.
parallel_tool_calls: falseroutes around Gemini instead, since Gemini has no single-call mode. - Tool names longer than 64 characters or using characters outside
[A-Za-z0-9_.:-](long MCP names, for example) now work on Gemini-backed routes; the model sees a stable alias and every emitted call carries the name you declared. - Freeform
apply_patchcalls served through the compatibility path now carry the samecall_eba1_…identity every other tool call carries. Ids issued under the earliercall_eb2.…format keep working for one release.
2026-09-02#
previous_response_idis now honored on/v1/responsesfor every eb1 model. Each response is retained for 24 hours, scoped to your organization, unless the request setstore: false; a follow-up request that names the id continues the conversation without resending earlier turns. An unknown or expired id returns400with codeprevious_response_not_found, matching the OpenAI contract. Responses larger than 1 MiB are served normally but not retained for continuation./v1/messagesnow forwardsoutput_config.effortandthinking: {"type": "adaptive"}as reasoning effort to the served model instead of dropping them; effort above a model's ceiling is lowered to that ceiling./v1/responsesacceptstool_choice: {"type": "allowed_tools"}, assistantrefusalcontent on replayed turns, array-valuedcustom_tool_call_output, andinput_image.detail: "original".item_referenceitems andconversationreturn a400naming the parameter.- Tool-call identities are now gateway-issued on every surface. A Responses
call_id, a Chat Completionstool_calls[].id, and a Messagestool_use.idfor the same call all render as the samecall_eba1_…alias; hosted web-search correlation ids render ashist_eba1_…and output item ids asitem_eba1_…. Replay them verbatim in continuation turns exactly as before; ids issued by earlier responses keep working. Provider-private continuation fields (such asthought_signature) no longer appear in customer payloads; the gateway carries them across turns for you. /v1/messagesnow serves Anthropic-native web search with both current spellings,web_search_20250305andweb_search_20260209, on every eb1 model; the search runs on the served Claude leg and itsserver_tool_useandweb_search_tool_resultblocks come back in place. Previously the native declaration was refused.- Anthropic's client-executed agent tools (
bash_20250124, thetext_editor_*versions, andmemory_20250818) are accepted on/v1/messagesand served natively when the route lands on Claude; the model's version support still applies. Previously these declarations were refused as unknown tools.
2026-08-27#
eb1-fast-previewnow reports acontext_window(andmax_input_tokens) of400000in/v1/models, up from240000. A routing refresh raised the largest window reachable by fast-tier requests, and the published figure tracks the enforced serving bound (capped at the product-wide400000ceiling shared by every eb1 model). As before, the figure is a floor the API honors on every request. Existing Codex setups pick up the new window on their next setup run.
2026-08-21#
- A platform-internal admission refusal that previously surfaced as
500 internal_errornow returns503 server_errorwith coderoute_capacityand aRetry-Afterhorizon, the same retriable contract introduced on 2026-08-05. No upstream is involved and an unchanged retry usually succeeds immediately; clients that already honorroute_capacityneed no changes.
2026-08-20#
- The Codex model catalog written by the Keiro installer now declares the one reasoning level eb1 models accept. In stock Codex, choosing a model from
/modelpreviously applied the change but left the picker on screen until Esc; the picker now closes on selection. Existing installations pick this up by rerunning the installer, which rewrites~/.codex/keiro.jsonin place. See Use eb1 with Codex.
2026-08-10#
- New setup guides for two additional coding agents: OpenCode registers Keiro as an OpenAI-compatible provider in
opencode.json, and Pi 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/messagesusage adopts Anthropic's native disjoint input-side semantics for all callers, effective with the next deployment:input_tokensexcludes the cached portions of the prompt, andinput_tokens + cache_read_input_tokens + cache_creation_input_tokensequals the full prompt. The previous additive-subset shape — the full inclusive count ininput_tokenswith the cache fields as subsets of it — is retired. Clients that readinput_tokensas the inclusive total should sum the three input-side fields to recover it; responses with zero cache activity are unchanged. See Messages.- 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.
2026-08-05#
- Requests refused by a platform-internal capacity gate now return
503 server_errorwith the new coderoute_capacity, a retriable condition carrying aRetry-Afterhorizon. These refusals previously surfaced as502 upstream_server_error, wrongly implying an upstream dependency; no upstream is involved and an unchanged retry usually succeeds within seconds.provider_unavailableremains reserved for genuine upstream unavailability.
2026-08-02#
eb1-previewandeb1-efficient-previewnow report acontext_window(andmax_input_tokens) of400000in/v1/models, up from120000;eb1-fast-previewreports240000. 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-previewis unchanged at400000. Existing Codex setups pick up the new windows on their next setup run.- Context-overflow errors now report the enforced bound. The
Minprompt is too long: {N} tokens > {M} maximum(anddetails.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_foundthat names the public IDs, with403 model_not_availablereserved for public models your plan does not include. Previously some unknown IDs surfaced as availability errors. - Streamed Messages responses carry
thinkingsummary blocks, delivered throughthinking_deltaevents, 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_tokensnow 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/messagesnow name fields in Messages coordinates (messages[i].content[j]) instead of the Responses spelling. /v1/messageserror bodies now carryerror.request_id, matching theX-Request-Idheader, 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-previewnow reports acontext_windowof400000in/v1/models, up from128000. 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. The120000windows oneb1-preview,eb1-fast-preview, andeb1-efficient-previeware 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_errorwithcodecontext_length_exceeded, matching every other context-overflow rejection. Previously this one path reported the genericrequest_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
xhighand above) or on the wall-clock ceiling for the requested reasoning effort (5 minutes atnone/minimalup to 60 minutes atmax/ultra). Requests that do not set a reasoning effort resolve no lower than themediumrow (10 minutes);eb1-frontier-previewdefaults to themaxrow. 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.incompletewithincomplete_details.reasonofstream_idle_timeoutorstream_ceiling_timeout; Chat Completions reportsfinish_reasonlengthand Messages reportsstop_reasonmax_tokens. Tokens consumed before the stop are billed; the terminal event is truthful about why the run stopped. See Streaming.
2026-07-22#
- The discoverable model catalog is
eb1-preview,eb1-frontier-preview,eb1-fast-preview, andeb1-efficient-preview, superseding the naming contract published on 2026-07-20. Theeb1-preview-efficient,eb1-preview-fast, andeb1-preview-deltaidentifiers 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 toeb1-preview-deltarequests nameeb1-delta-preview, which remains callable but does not appear in discovery. - Invalid model-exclusion inputs now return the governed, non-retriable
400 invalid_request_errorenvelope withcodebad_request. Previously these caller-fixable requests could be serialized as a retriable502 upstream_error. Synchronous responses now carryx-should-retry: false; synchronous bodies and streaming error frames carryretryable: falsewith 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, andeb1-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_tokensandcache_write_tokens, instead of always reporting zero. Both are subsets ofinput_tokensand do not changetotal_tokens. The Console chat tester preserves those reported cache-read counts andoutput_tokens_details.reasoning_tokensin 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, andeb1-fast-previewreport acontext_windowof120000in/v1/models, down from the previously published128000;eb1-frontier-previewis unchanged at128000. 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_errorwithcoderequest_exceeds_capacity, instead of a429rate limit. The old429carried aRetry-Afterheader even though no unchanged retry could ever succeed, trapping status-driven clients in an infinite retry loop. The new response carriesx-should-retry: false, no retry horizon, and nox-ratelimit-reset-*-tokensheader; the message anddetails.dimension: "token_budget_request"are unchanged. Reduce the input ormax_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(withreasoning_tokens), andtotal_tokensalways equalsprompt_tokens + completion_tokens, with reasoning counted insidecompletion_tokens. Previously, reasoning-heavy requests could report atotal_tokenslarger than the visible sum with no breakdown. - Responses usage now matches the standard
ResponseUsageschema:input_tokens,input_tokens_details.cached_tokens,output_tokens,output_tokens_details.reasoning_tokens, andtotal_tokens(= input_tokens + output_tokens). The former non-standard flatreasoning_tokenskey and theprompt_tokens/completion_tokensaliases 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/messagesoutput_tokensnow includes reasoning tokens, matching the Anthropic convention that thinking is part of output.usagedetail objects reportcached_tokens: 0for now; prompt-cache accounting is not yet reflected in usage counts.
2026-07-17#
- Retired the
/v24bversioned endpoint path. It no longer differs from the current default deployment, so requests to/v24b/v1/*now return410 endpoint_retiredinstead of routing to current-default weights under a versioned label. Use the default API (/v1). - The Keiro CLI no longer offers a
v24bendpoint 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_foundenvelope withx-should-retry: false. - Chat Completions stream error frames now nest a full
errorobject (code, type, message, retry signals,retryable,request_id, anddetailson 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 samedetailsobject on limit denials. /v1/messagesresponses now also carry arequest-idheader (an alias ofX-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"withincomplete_details.reason: "max_output_tokens"and awarningnaming the fix, instead of claiming success; Chat Completions reportfinish_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
502withcodeupstream_auth_error. Previously an upstream401could pass through as your fault; SDKs raisedAuthenticationErrorand stopped retrying for a platform-side condition. Your API key is valid when you see this code. - Replaced the
401codeauthentication_error(which duplicatedtype) with three specific codes:missing_authorization,bearer_scheme_required, andinvalid_api_key(with a redacteddetails.key_hint). Code-matching clients keep working: the old code's value remains as the errortype. All401responses now carryWWW-Authenticate: Bearer. error.paramis now populated with the offending field name where known; previously documented as alwaysnull.- Documented every error code with per-code anchors, added
413and415to the status table, and removed the never-emitted408row. - Added retry-signal headers to error responses:
retry-after-ms(milliseconds, fractional precision) on retriable denials andx-should-retry: falseon denials an unchanged retry cannot clear. Deterministic denials also carry"retryable": falsein the error body. - Error responses now include
error.request_id, matching theX-Request-Idheader; 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-Keyheader, theX-Idempotent-ReplayandX-Original-Request-Idreplay headers, and409 idempotency_key_conflictconflicts. - Documented the
409status code and clarified that the errorparamfield is alwaysnull. - 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 guiscoped to chat UX only.