Skip to main content
POST
/
v1
/
workflows
/
reviews
/
{run_id}
/
{block_id}
/
versions
from retab import Retab
from retab.exceptions import ConflictError

client = Retab()

overlay = client.workflows.runs.reviews.get("run_abc123", "block_extract")

try:
    overlay = client.workflows.runs.reviews.edit(
        "run_abc123",
        "block_extract",
        snapshot={"total_amount": 325, "vendor_name": "Acme Corp"},
        version_stamp=overlay.version_stamp,
        origin="human_edit",
        note="Corrected total to match ATM + checks subtotal.",
    )
    print("new effective version:", overlay.versions[-1].seq)
except ConflictError:
    # Overlay moved on — re-read and retry with the fresh stamp.
    overlay = client.workflows.runs.reviews.get("run_abc123", "block_extract")
{
  "_id": "run_abc123:block_extract",
  "workflow_run_id": "run_abc123",
  "block_run_id": "run_abc123:block_extract",
  "block_id": "block_extract",
  "workflow_id": "wf_1",
  "status": "awaiting_review",
  "rev": 4,
  "claim": {
    "holder": {
      "kind": "human",
      "id": "user_42",
      "display_name": "Dana Rivera"
    },
    "claimed_at": "2026-05-13T08:55:00.000Z",
    "expires_at": "2026-05-13T09:55:00.000Z"
  },
  "versions": [
    {
      "seq": 0,
      "origin": "model_output",
      "author": { "kind": "model", "id": "retab-small", "display_name": "Retab Small" },
      "snapshot": { "total_amount": 505, "vendor_name": "Acme Corp" },
      "note": null,
      "created_at": "2026-05-13T08:14:02.341Z"
    },
    {
      "seq": 1,
      "origin": "human_edit",
      "author": { "kind": "human", "id": "user_42", "display_name": "Dana Rivera" },
      "snapshot": { "total_amount": 325, "vendor_name": "Acme Corp" },
      "note": "Corrected total to match ATM + checks subtotal.",
      "created_at": "2026-05-13T09:02:51.118Z"
    }
  ],
  "decisions": [],
  "audit": [
    {
      "event": "version_appended",
      "actor": { "kind": "human", "id": "user_42", "display_name": "Dana Rivera" },
      "at": "2026-05-13T09:02:51.118Z"
    }
  ]
}

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.

Append a corrective edit version to a review overlay. This records a new version of the gated block’s output without submitting a verdict. The overlay’s full version history is preserved — the model’s original stays at sequence 0, and your edit is appended as the next sequence. The newly appended version becomes the effective output that a subsequent approved decision will flow downstream. The request body carries:
FieldNotes
snapshotThe corrected output payload. Required.
version_stampThe overlay rev you last read. Required — see the conflict note below.
originProvenance label for the version, e.g. "human_edit" (default).
noteOptional free-text note explaining the correction. Recorded in the audit trail.
command_idOptional idempotency key — a retried call with the same command_id is deduplicated.
version_stamp is a compare-and-swap token. Send the value you last read from Get Review. If the overlay has advanced (another actor edited or decided in the meantime), the call returns 409 — re-read the overlay and retry with the fresh stamp. A stale stamp raises retab.exceptions.ConflictError in Python and surfaces as an APIError with .status === 409 in JavaScript.
If you want to record a correction and approve it in one step, use Submit Decision with edited_output instead — the server appends the version and then approves it atomically.
from retab import Retab
from retab.exceptions import ConflictError

client = Retab()

overlay = client.workflows.runs.reviews.get("run_abc123", "block_extract")

try:
    overlay = client.workflows.runs.reviews.edit(
        "run_abc123",
        "block_extract",
        snapshot={"total_amount": 325, "vendor_name": "Acme Corp"},
        version_stamp=overlay.version_stamp,
        origin="human_edit",
        note="Corrected total to match ATM + checks subtotal.",
    )
    print("new effective version:", overlay.versions[-1].seq)
except ConflictError:
    # Overlay moved on — re-read and retry with the fresh stamp.
    overlay = client.workflows.runs.reviews.get("run_abc123", "block_extract")
{
  "_id": "run_abc123:block_extract",
  "workflow_run_id": "run_abc123",
  "block_run_id": "run_abc123:block_extract",
  "block_id": "block_extract",
  "workflow_id": "wf_1",
  "status": "awaiting_review",
  "rev": 4,
  "claim": {
    "holder": {
      "kind": "human",
      "id": "user_42",
      "display_name": "Dana Rivera"
    },
    "claimed_at": "2026-05-13T08:55:00.000Z",
    "expires_at": "2026-05-13T09:55:00.000Z"
  },
  "versions": [
    {
      "seq": 0,
      "origin": "model_output",
      "author": { "kind": "model", "id": "retab-small", "display_name": "Retab Small" },
      "snapshot": { "total_amount": 505, "vendor_name": "Acme Corp" },
      "note": null,
      "created_at": "2026-05-13T08:14:02.341Z"
    },
    {
      "seq": 1,
      "origin": "human_edit",
      "author": { "kind": "human", "id": "user_42", "display_name": "Dana Rivera" },
      "snapshot": { "total_amount": 325, "vendor_name": "Acme Corp" },
      "note": "Corrected total to match ATM + checks subtotal.",
      "created_at": "2026-05-13T09:02:51.118Z"
    }
  ],
  "decisions": [],
  "audit": [
    {
      "event": "version_appended",
      "actor": { "kind": "human", "id": "user_42", "display_name": "Dana Rivera" },
      "at": "2026-05-13T09:02:51.118Z"
    }
  ]
}

Authorizations

Api-Key
string
header
required

Path Parameters

run_id
string
required
block_id
string
required

Body

application/json

Append an edit (a new OutputVersion) without deciding.

snapshot
Snapshot · object
required

The FULL corrected output JSON — a complete replacement object, not a partial diff.

version_stamp
integer
required

CAS token: the overlay rev the client last read. The server returns 409 on mismatch so the client can re-read and rebase.

Required range: x >= 0
origin
enum<string>
default:human_edit

Who-shaped origin of this edit. seq=0 / 'model_output' / 'revert' are not valid here.

Available options:
agent_edit,
human_edit
note
string | null

Free-text rationale from the author.

command_id
string | null

Optional idempotency key — a retried append with the same command_id is deduplicated.

Response

Successful Response

The HIL review sidecar for one gated block run. Replaces v1 HilRunState.

Stored 1:1 in hil_overlays with _id == block_run_id.

_id
string
required

Equals block_run_id — 1:1 with the gated run.

workflow_id
string
required
workflow_version_id
string
required

Pinned at gate-fire; resume runs THIS version.

workflow_run_id
string
required
block_id
string
required
block_run_id
string
required
block_type
enum<string>
required
Available options:
extract,
classifier,
split,
conditional
triggered_by
HilAlways · object
required

Gate every run.

versions
OutputVersion · object[]
required

Ascending seq. versions[0] is always the model's seq=0 output.

Minimum array length: 1
head_seq
integer
required

seq of the newest version (== versions[-1].seq).

Required range: x >= 0
status
enum<string>
default:awaiting_review
Available options:
awaiting_review,
approved,
rejected
awaiting_since
string<date-time>
decided_at
string<date-time> | null
priority
integer
default:0

Higher sorts first in the queue.

rev
integer
default:0

Whole-document CAS token. +1 on every mutating write.

Required range: x >= 0
claim
ReviewClaim · object

A soft lease so the UI can show 'Dana is reviewing this'. NOT a lock — correctness rests entirely on the rev CAS. Claims expire.

decisions
ReviewDecision · object[]

Append-only. Empty while awaiting. len>1 means reopened.

audit
AuditEntry · object[]
effective_seq
integer | null

seq of the version downstream consumes. Set ONLY by an 'approved' decision. None while awaiting / rejected.