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

# Reviews

> Review, correct, and decide on gated workflow block outputs

## Overview

When a workflow reaches a block with `config.review` and the predicate fires, the run pauses and creates a review. Address the review by its opaque `id`, such as `rev_...`; workflow context like `run_id`, `block_id`, `step_id`, and `iteration_key` is metadata for filtering and grounding.

Reviews hold gate metadata and the terminal decision. Review versions hold immutable output snapshots and are managed separately through `reviews.versions.*`.

## Review Shape

| Field          | What it holds                                      |
| -------------- | -------------------------------------------------- |
| `id`           | Opaque review id.                                  |
| `run_id`       | Run that is paused for review.                     |
| `block_id`     | Workflow block that produced the reviewed output.  |
| `step_id`      | Exact execution step under review.                 |
| `decision`     | Terminal verdict, or `null` while awaiting review. |
| `triggered_by` | Review predicate that opened the gate.             |

Review queue items return the same `Review` shape. Fetch the version history for a given review with `reviews.versions.list(review_id=...)` — the runtime-created seed is the version whose `parent_id` is `null`.

## Version Shape

| Field        | What it holds                                                                              |
| ------------ | ------------------------------------------------------------------------------------------ |
| `id`         | Content-addressed version id.                                                              |
| `review_id`  | Review this version belongs to.                                                            |
| `parent_id`  | Parent version id. `null` appears only on runtime-created seed versions in read responses. |
| `snapshot`   | Complete reviewed output payload for this version.                                         |
| `note`       | Optional reviewer note.                                                                    |
| `created_at` | When the version was created.                                                              |

Versions are peers. There is no head pointer. Use `created_at` for display ordering, and approve or reject the exact `version_id` you inspected.

## The Review Loop

### 1. Find the work

```python theme={null}
queue = client.workflows.reviews.list(
    workflow_id="wf_abc123",
    decision_status="pending",
)

for item in queue.data:
    print(item.id, item.run_id, item.block_id)
```

### 2. Inspect the output

```python theme={null}
item = queue.data[0]
review = client.workflows.reviews.get(item.id)
versions = client.workflows.reviews.versions.list(review_id=review.id)
seed_version = next(v for v in versions.data if v.parent_id is None)

print(review.run_id, review.step_id)
print(seed_version.snapshot)
```

Use `run_id` and `step_id` to inspect the source step and document before deciding.

### 3. Correct if needed

Create a new version (a complete replacement snapshot) with the reviewed version as `parent_id`, then approve the returned `id`. Public clients must provide `parent_id` when creating correction versions. Versions are a flat CRUD resource at `POST /v1/workflows/reviews/versions`; the parent id lives in the body, not the URL.

```python theme={null}
version = client.workflows.reviews.versions.create(
    review_id=review.id,
    parent_id=seed_version.id,
    snapshot={"total_amount": 325, "vendor_name": "Acme Corp"},
    note="Corrected total.",
)

version_id = version.id
```

Snapshot validation is block-specific:

| Block type   | Snapshot shape                                               |
| ------------ | ------------------------------------------------------------ |
| `extract`    | Raw extracted JSON object.                                   |
| `classifier` | `{ "category": "booking_confirmation" }` only.               |
| `split`      | `{ "documents": [{ "name": "invoice", "pages": [1, 2] }] }`. |
| `for_each`   | `{ "partitions": [{ "key": "INV-001", "pages": [1, 2] }] }`. |

For split and for-each snapshots, `pages` must be positive integers, sorted, and unique within each item. The API does not support partial patches.

### 4. Decide

```python theme={null}
client.workflows.reviews.approve(review.id, version_id=version_id)

client.workflows.reviews.reject(
    review.id,
    version_id=seed_version.id,
    reason="Source document is illegible; cannot verify totals.",
)
```

`resume_status="resumed"` means the workflow accepted the signal. `resume_status="pending"` means the decision is durable and a backend reconciler will retry the resume.

## API Reference

| Endpoint                                                           | SDK method                     |
| ------------------------------------------------------------------ | ------------------------------ |
| [List Reviews](/api-reference/workflows/reviews/list)              | `reviews.list(...)`            |
| [Get Review](/api-reference/workflows/reviews/get)                 | `reviews.get(id)`              |
| [Approve Review](/api-reference/workflows/reviews/approve)         | `reviews.approve(...)`         |
| [Reject Review](/api-reference/workflows/reviews/reject)           | `reviews.reject(...)`          |
| [Create Version](/api-reference/workflows/reviews/versions/create) | `reviews.versions.create(...)` |
| [Get Version](/api-reference/workflows/reviews/versions/get)       | `reviews.versions.get(id)`     |
| [List Versions](/api-reference/workflows/reviews/versions/list)    | `reviews.versions.list(...)`   |
