Guides

Review and Approval

Review model, approval semantics, concurrency control, and downstream eligibility for Numora documents.

Scope

This page explains how Numora handles human review after extraction completes.

It covers:

  • The difference between status and review_state
  • What the approve action means
  • When reject and retry-push should be used
  • How optimistic concurrency prevents stale approvals

Two Review Layers

The document resource uses two related but different concepts:

  • status tells you where the document is in the lifecycle.
  • review_state tells you what a reviewer has explicitly confirmed.

For example, a document can still be in review_required while already carrying a partial review_state object that records confirmed fields.

The review_state Object

The public review_state value should be either null or a normalized object:

{
  "version": 1,
  "confirmed_general_field_names": ["invoice_number", "invoice_date"],
  "confirmed_line_item_ids": ["li_1", "li_2"]
}

Rules:

  • version allows the shape to evolve without breaking clients.
  • confirmed_general_field_names stores normalized field names from the document result.
  • confirmed_line_item_ids stores stable line item row identifiers returned by the result payload.
  • If both arrays are empty, the normalized value should be null.

Current Review Semantics

The current Numora app already follows these review rules:

  • Extraction completion moves the document into internal for_review, which maps to public review_required.
  • Approving a document marks it as reviewed and finalized.
  • Editing a previously approved document sends it back to review.
  • Only reviewed and finalized documents are eligible for downstream push or manual workflow dispatch.

For the lifecycle mapping, see Document Lifecycle.

Approve Action

POST /v1/documents/{id}/actions/approve

Use this action when the extracted result is ready to become the confirmed source of truth.

Recommended request:

{
  "expected_updated_at": "2026-03-21T14:20:00.000Z",
  "review_state": {
    "version": 1,
    "confirmed_general_field_names": ["invoice_number", "invoice_date"],
    "confirmed_line_item_ids": ["li_1"]
  }
}

Recommended response:

{
  "id": "doc_01jpwq4q9m7q4q2k8dax1x1q5n",
  "status": "reviewed",
  "updated_at": "2026-03-21T14:20:03.119Z",
  "review_state": {
    "version": 1,
    "confirmed_general_field_names": ["invoice_number", "invoice_date"],
    "confirmed_line_item_ids": ["li_1"]
  }
}

Approval should be idempotent. Repeating the same request should not create duplicate downstream effects.

Reject and Retry-Push Actions

Numora reserves three action verbs on the public document resource:

  • approve finalizes a reviewed result.
  • reject reopens the document for review, clears finalized state, and blocks new downstream delivery.
  • retry-push requeues downstream delivery for a document that is already reviewed.

In the current developer preview:

  • approve finalizes the extracted result and unlocks reviewed automation.
  • reject moves the document back to review_required.
  • retry-push queues a new downstream workflow run and temporarily surfaces the document as push_pending.

Concurrency Control

Clients should protect review actions with optimistic concurrency.

Recommended pattern:

  1. Read the latest document or result resource.
  2. Store the returned updated_at.
  3. Send that value back as expected_updated_at when approving.
  4. If the server returns 409 conflict, refetch the latest document before trying again.

Recommended conflict response:

{
  "error": {
    "code": "conflict",
    "message": "approve conflict",
    "request_id": "req_01jpwqkshg6x8j9k9j29m8n0n4"
  },
  "updated_at": "2026-03-21T14:21:12.000Z"
}

Downstream Gating

Approval is not only a UI label. It is the gate that makes the document eligible for downstream execution.

For the initial CRM delivery path, this means a client may start from already reviewed documents and the delivery outbox rather than treating POST /v1/documents as a required first step.

Operationally, the recommended contract is:

  • review_required documents can still be edited or corrected.
  • reviewed documents are treated as confirmed.
  • A later edit to a previously approved document should move it back to review_required.
  • Downstream push and manual workflow dispatch should require the document to be both reviewed and finalized.