# Changelog

This page is for an agent checking what changed in the Zaun API and documentation before it
writes or updates an integration. Entries are newest first and list only changes a customer
can see. If you are the person, this is the page to watch for changes that need action; those
entries say what to do.

## 2026-10-13: Documentation for agents

- The docs are published for agents: `/llms.txt` lists every page with its Markdown URL,
  `/llms-full.txt` holds every page in one file, and each page is served as Markdown at
  `/docs/<page>.md`, including the API reference at `/docs/openapi.md`.
- New pages: [Set up with your agent](agent-setup.md), [Try it](try-it.md),
  [Choose a capture path](capture-paths.md), one page each for [Claude Code](claude-code.md),
  [Claude Cowork](claude-cowork.md), [Codex](codex.md), [Cursor](cursor.md) and
  [OpenTelemetry for custom agents](opentelemetry.md), and
  [Hex v1.3 known limits](known-limits.md).
- [Limits](limits.md) and [Responses](responses.md) state the `POST /v1/responses` time
  budget: a non-streaming response must finish within 180 seconds, and a stream must release
  its first text within 180 seconds, or the request returns 504 `deadline_exceeded`. Action:
  send `stream: true` for long generations and high reasoning effort.

## 2026-10-13: Scans that could not be assessed are not billed

- A scan Hex v1.3 could not complete, which returns as an alert for review, is no longer
  charged: its `usage` reports zero tokens. Images read for such a scan are still charged.

## 2026-10-13: Session calls are billed once, with cached tokens

- A scan with a `session_uuid` is billed for the tokens it assesses for the first time at the
  scan rate ($0.20 per million) and for the session's earlier tokens, read back as context, at
  $0.02 per million. Before, every session call was billed for the session's whole count at
  the scan rate.
- `usage.input_tokens` now reports only the new tokens, and the new
  `usage.cached_input_tokens` reports the earlier tokens. A resend with nothing new bills zero
  new tokens. Requests without a session and document scans are unchanged. Action: if you
  total usage yourself, add `cached_input_tokens` at its own rate.

## 2026-10-13: GPT-6 reasoning effort

- The GPT-6 routes on `POST /v1/responses` accept every `reasoning.effort` level; `gpt-6-sol`
  and `gpt-6-luna` default to `medium`, and `gpt-6-astra` has no documented default, so its
  `zaun.effort.default` is null. On `gpt-6-sol` and `gpt-6-luna`, send function tools or an
  effort, not both. See [Responses](responses.md).

## 2026-10-13: Detection samples and the test string

- `GET /v1/detection-samples` lists Zaun-written sample requests, one or more per category
  plus benign ones, each with the outcome expected under the default controls of a new
  self-serve project. No key is needed. The console Playground offers the same samples as
  one-click runs, up to 30 runs a minute per organization.
- The test string `ZAUN-TEST-VIOLATION-7f3a9c` is always reported as a blocked input check
  named `zaun_test`, in prompts and inside tool arguments. No project setting can lower it. Use
  it to prove a key, a hook, a gateway or an alert; see [Try it](try-it.md).

## 2026-10-13: One assessment path for every project

- Project configurations no longer accept `classifier.mode: reference`. Projects that selected
  it receive a new configuration version that selects `cascade_v1`, the default. Projects on
  `primary` are unchanged. Action: if you publish configurations through the administration
  API, stop sending `reference`.
- Results keep `stages.embed` and `stages.knn`, now always `skipped`, so existing clients keep
  parsing them. New results never carry `signals.knn`.
- The error codes `embedder_unavailable`, `vector_search_unavailable` and `embedding_invalid`
  are no longer returned.
- A new organization's keys can scan as soon as the organization is enabled, and the console
  Playground no longer waits for setup.

## 2026-10-05: Completion assessment usage and interrupted completions

- Input and tool-call assessments on `POST /v1/responses` report the tokens they are charged in
  `zaun.scan.usage`, `zaun.output_scan.usage` and `GET /v1/result`, instead of zero. What you
  pay is unchanged: they were always billed at the scan rate. Assessments recorded before this
  change keep reporting zero until they expire.
- A completion that stops before the model call finishes now settles its credit hold. Usage the
  model already reported is charged when the input assessment blocks or fails, a streaming
  client stops reading, or held text exceeds its cap. A request that never reached the model,
  or that was refused before generating, releases its hold without a charge.

## 2026-09-30: `/v1/docs` redirects to the console

- `GET /v1/docs` returns a 308 redirect to `https://console.zaun.ai/docs`, and the API reference
  documents it.

## 2026-09-26: GPT-6 models on `POST /v1/responses`

- `gpt-6-astra`, `gpt-6-sol` and `gpt-6-luna` are available through `POST /v1/responses` and
  listed by `GET /v1/models`. See [models](models.md) for limits and prices.
- Requests large enough to reach the provider's higher long-context price are rejected before
  any charge.

## 2026-09-22: Generation moves to the Responses API

- `POST /v1/responses` is compatible with the OpenAI Responses API and its official SDKs. It
  takes `input` as a string or as message, `function_call` and `function_call_output` items,
  plus `instructions`, function `tools`, `tool_choice`, `max_output_tokens` and `stream`.
- `POST /v1/chat/completions` and `POST /v1/completions` are removed and return 404. Action:
  move callers to [Responses](responses.md).
- Responses are stateless: `store: true` and `previous_response_id` return 422. Send the full
  conversation as input items on every call.
- Streams send typed Responses events with `sequence_number` and end with `response.completed`,
  `response.incomplete` or `error`; there is no `[DONE]` line.
- A blocked output ends as `status: incomplete` with `incomplete_details.reason:
  content_filter`; a token cutoff reports `max_output_tokens`.
- `usage` uses the Responses spelling: `input_tokens`, `output_tokens`,
  `input_tokens_details.cached_tokens` and `cache_write_tokens`.

## 2026-09-22: Results no longer name models or vendors

- `GET /v1/result`, `GET /v1/sessions/{session_uuid}` and completion assessments no longer
  return `signals.classifier`, `signals.path`, `usage[].model`, `revisions.model` or
  `revisions.corpus`. `revisions.pipeline` is an opaque fingerprint that changes whenever the
  assessment changes.
- Only `latency_ms.total` is reported; per-stage timings are gone.
- Document results drop `extraction_evidence.provider` and `extraction_evidence.model_version`
  and report `coverage.extraction_source: ocr` for recognized text. OCR regions and confidence
  remain.
- `usage` on results is the billed `{input_tokens, output_tokens}`, matching the scan response.
- `GET /v1/usage` no longer accepts `group_by=model` or `group_by=stage`. Day grouping is
  unchanged. Action: remove those parameters from usage queries.

## 2026-09-22: Faster, fail-soft document scans

- A PDF whose own text layer covers every page is read from that layer
  (`extraction_source: pdf_text_layer`) in milliseconds. Scanned or partly scanned PDFs are
  read with OCR, page by page.
- TXT, Markdown, CSV and HTML are scored exactly as uploaded. DOC, DOCX, XLS and XLSX go through
  a native parser first.
- A document with no text anywhere is refused.
- A transcription that is refused, times out or comes back empty is reported inside an HTTP
  200 body with `status: failed`, `error.stage`, `review_recommended` and `review_reason`.
  HTTP 4xx is reserved for requests rejected before any processing. Idempotent replays return
  the same body. See [document scans](async-documents.md).
