> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anyformat.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# July 2026

> Changes shipped in July 2026.

### July 28, 2026

**\[New]** Download every document's markdown as one ZIP

The Results view's download menu gains **Markdown (ZIP)** — one `.md` per document, named
after the original file, plus a `manifest.csv` mapping original filename to archive entry
to status. It respects whatever the table is showing: tick documents and the menu says
"200 selected", leave the selection empty and it exports everything matching the active
filters. Unlike the extraction formats, it is available on the **Documents** tab too,
which is where the checkboxes live.

Documents whose parse hasn't completed are skipped and reported — both as a summary
("Exported 198 of 200 · 2 skipped") and per row in the manifest. Every archive is built in
the background: a small one lands in your downloads within a few seconds, and any export
also arrives in the notification bell with a download link that survives closing the tab.
Exports consume no pages or credits: the markdown already exists, this only packages it.

**\[Fixed]** Bulk downloads now honour the table's filters

Filtering the Results table by name, status or date and then downloading returned the
whole workflow rather than the filtered set. This affected CSV, Excel, JSON and JSONL.
Filters on extracted-field values were unaffected. Selecting rows and then changing a
filter also kept the stale selection; the selection now resets when the filter changes.

**\[Improved]** Slack alerts ask for narrower permissions and join the channel themselves

The Slack app now requests only the OAuth scopes a delivery needs, and joins the target channel on first delivery instead of asking you to invite it. In Studio, the Slack Alert node's preview and test-send render the template tokens with real values.

### July 13, 2026

**\[New + API]** Attach metadata to a document packet

Every v3 create path accepts an optional `metadata` object, stapled to the packet at creation time and echoed back verbatim when you read it. When the packet runs, the extract step sees the metadata inline: a top-level key whose name matches an extract-schema field is used as that field's value, in preference to anything read from the document, and the field's evidence marks it as `metadata.<key>` so you can tell the two sources apart. Use it to pass a customer reference, a batch id, or any context your own system already knows. See [Attaching metadata](/concepts/document-packets#attaching-metadata).

<Accordion title="Technical detail">
  On the multipart uploads, send `metadata` as a JSON-encoded string form field: `-F 'metadata={"customer_reference": "CR-2026-99001-ZTX"}'`. There is no schema beyond "must be a JSON object". Read it back on `GET /v3/document-packets/{document_packet_id}/`.
</Accordion>

### July 7, 2026

**\[New + API]** API v3 launched — document packets and runs as first-class resources

The public API's new stable major is live under `/v3/`, rebuilt around three resources: **workflows**, **[document packets](/concepts/document-packets)** (the runnable bundle of 1+ files — v2's "file collection", renamed and promoted), and **[runs](/concepts/runs-and-results)** (one execution attempt of a workflow against a packet, with its own id, status, and results). The full reference lives in the new [v3 API tree](/api-reference-v3/introduction); v2 users can follow the [path-by-path migration guide](/api-reference-v3/migrating-from-v2). Highlights:

* **Flat run reads, no more 412-polling** — [`GET /v3/runs/{run_id}/`](/api-reference-v3/runs/get) always returns `200` with a `status` field; `results` carries the (unchanged) results envelope inline once `status` reaches `processed`. The `/results/` sub-path is gone.
* **One upload shape** — [`POST .../upload/`](/api-reference-v3/workflows/upload) groups 1–10 files into a single packet atomically, [`.../upload/run/`](/api-reference-v3/workflows/upload-and-run) does upload + run in one call and returns a `run_id`, and [`.../upload/from-url/`](/api-reference-v3/workflows/upload-from-url) imports 1–10 HTTPS URLs all-or-nothing.
* **Re-run without re-uploading** — [`POST /v3/document-packets/{id}/run/`](/api-reference-v3/document-packets/run) creates a fresh run each call; earlier runs stay readable.
* **The workflow read is the definition** — [`GET /v3/workflows/{workflow_id}/`](/api-reference-v3/workflows/get) returns the complete typed graph with a `persistent_id` per field, and [`PATCH`](/api-reference-v3/workflows/update) echoes that shape back: echo the `persistent_id` and a renamed field keeps its identity (analytics, ground truth, and quality metrics stay attached). There is no separate `/definition/` endpoint and no `PUT` in v3.
* **Keyset pagination everywhere** — every list returns `{items, next_cursor}` with `?limit=` (max 100) and `?cursor=`; no totals or page numbers.
* **Idempotent submission** — the upload and run-trigger POSTs accept an [`Idempotency-Key` header](/api-reference-v3/introduction#idempotency); a retry with the same key replays the original response instead of creating a duplicate packet or billing a second extraction.
* **`X-API-Version: 3.0.0`** is stamped on every `/v3/` response.

v2 is unchanged and keeps serving traffic through its announced deprecation window (see the July 3 entry below). Authentication, the error envelope, the results envelope, webhooks, and rate limits are identical across both versions.

### July 6, 2026

**\[Changed + API]** Dataset membership moves to collection-keyed, idempotent endpoints

Test-set membership is being renamed to the product's **dataset** vocabulary and re-keyed onto the collection — the identity a document already carries everywhere else (the `id` in every document response). Membership now lives under the workflow: `PUT /api/v3/workflows/{workflow_id}/dataset/files/{collection_id}/` adds a document to the dataset (optionally snapshotting a chosen extraction as ground truth via `{ "extraction_id": … }`), `DELETE` the same path removes it, and `POST /api/v3/workflows/{workflow_id}/dataset/files/bulk/` adds a filtered grid selection. All three writes are **idempotent** — re-adding a member or removing a non-member is a `200`/`204` no-op instead of a `409`. The test-file list rows now include a `collection_id` so callers can address membership without a second lookup.

The previous file-scoped routes `POST /api/v3/files/{file_id}/test-set/` and `DELETE /api/v3/files/{file_id}/test-set/` still work but are **deprecated** and now idempotent too; migrate to the `dataset/` paths above.

### July 3, 2026

**\[Deprecated + API]** v2 enters its deprecation window — `Deprecation`/`Sunset` headers on every response

With v3 as the new stable major, `/v2/` is frozen: no new features, existing behavior untouched. Every `/v2/` response now carries the [RFC 8594](https://datatracker.ietf.org/doc/html/rfc8594) deprecation signals — `Deprecation: Fri, 03 Jul 2026 00:00:00 GMT` and `Sunset: Sat, 03 Oct 2026 00:00:00 GMT`. Per-route `Link: <...>; rel="successor-version"` headers pointing at the v3 equivalent follow as the mappings are wired up. `/v3/` responses carry none of these headers.

**Action recommended:** wire an alert on the `Sunset` header so migration work can't be missed — [Versioning & deprecation](/api-reference/introduction#versioning--deprecation) shows a five-line client middleware that does it. Then plan the move with the [v2 → v3 migration guide](/api-reference-v3/migrating-from-v2). No client changes are required today; v2 keeps working until the sunset date.
