Skip to main content
POST
/
v1
/
workflows
/
{workflow_id}
/
tests
from retab import Retab

client = Retab()

# Manual inputs: hand-write the handle inputs the block should run with.
test = client.workflows.tests.create(
    workflow_id="wf_abc123xyz",
    target={"type": "block", "block_id": "block_extract_invoice"},
    source={
        "type": "manual",
        "handle_inputs": {
            "input-document-0": {
                "type": "file",
                "file_id": "file_invoice_q1",
            },
        },
    },
    assertion={
        "target": {"output_handle_id": "output-json-0", "path": "total"},
        "condition": {"kind": "equals", "expected": 1234.56},
    },
    name="Q1 invoice total",
)

# Run-step inputs: replay the inputs the block ACTUALLY received in a run.
test = client.workflows.tests.create(
    workflow_id="wf_abc123xyz",
    target={"type": "block", "block_id": "block_extract_invoice"},
    source={
        "type": "run_step",
        "run_id": "wfrun_def456",
        "step_id": "block_extract_invoice",
    },
    assertion={
        "target": {"output_handle_id": "output-json-0", "path": "vendor.name"},
        "condition": {"kind": "contains", "expected": "Acme"},
    },
)

print(f"Test created: {test.id}")
{
  "id": "wfnodetest_hsLEQiM61ez9Piv147MWk",
  "workflow_id": "wf_abc123xyz",
  "target": {
    "type": "block",
    "block_id": "block_extract_invoice"
  },
  "source": {
    "type": "manual",
    "handle_inputs": {
      "input-document-0": {
        "type": "file",
        "file_id": "file_invoice_q1"
      }
    }
  },
  "name": "Q1 invoice total",
  "assertion": {
    "id": "assert_xyz",
    "target": { "output_handle_id": "output-json-0", "path": "total" },
    "condition": { "kind": "equals", "expected": 1234.56 },
    "label": null
  },
  "assertion_schema_dep": {
    "schema_path": "total",
    "subtree_hash": "7d79dd764ab6548d",
    "depends_on_root": false
  },
  "assertion_drift_status": null,
  "schema_drift": "unknown",
  "schema_drift_detail": null,
  "validation_status": "valid",
  "validation_issues": [],
  "latest_run_summary": null,
  "latest_passing_run_summary": null,
  "latest_failing_run_summary": null,
  "created_at": "2026-05-01T14:30:00Z",
  "updated_at": "2026-05-01T14:30:00Z"
}

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.

Create a new workflow test against a single block in the workflow. A workflow test freezes a set of inputs (either captured from a previous run or provided manually) and asserts something about the block’s output the next time it runs. The request body has three parts:
  • target — the block the test runs against.
  • source — where the inputs come from. manual carries an explicit handle_inputs map; run_step references a previous workflow run plus the optional step inside it whose inputs to capture.
  • assertion — required. One assertion per test against one declared output handle (see Workflow Tests for the assertion shape and the available operators).
from retab import Retab

client = Retab()

# Manual inputs: hand-write the handle inputs the block should run with.
test = client.workflows.tests.create(
    workflow_id="wf_abc123xyz",
    target={"type": "block", "block_id": "block_extract_invoice"},
    source={
        "type": "manual",
        "handle_inputs": {
            "input-document-0": {
                "type": "file",
                "file_id": "file_invoice_q1",
            },
        },
    },
    assertion={
        "target": {"output_handle_id": "output-json-0", "path": "total"},
        "condition": {"kind": "equals", "expected": 1234.56},
    },
    name="Q1 invoice total",
)

# Run-step inputs: replay the inputs the block ACTUALLY received in a run.
test = client.workflows.tests.create(
    workflow_id="wf_abc123xyz",
    target={"type": "block", "block_id": "block_extract_invoice"},
    source={
        "type": "run_step",
        "run_id": "wfrun_def456",
        "step_id": "block_extract_invoice",
    },
    assertion={
        "target": {"output_handle_id": "output-json-0", "path": "vendor.name"},
        "condition": {"kind": "contains", "expected": "Acme"},
    },
)

print(f"Test created: {test.id}")
{
  "id": "wfnodetest_hsLEQiM61ez9Piv147MWk",
  "workflow_id": "wf_abc123xyz",
  "target": {
    "type": "block",
    "block_id": "block_extract_invoice"
  },
  "source": {
    "type": "manual",
    "handle_inputs": {
      "input-document-0": {
        "type": "file",
        "file_id": "file_invoice_q1"
      }
    }
  },
  "name": "Q1 invoice total",
  "assertion": {
    "id": "assert_xyz",
    "target": { "output_handle_id": "output-json-0", "path": "total" },
    "condition": { "kind": "equals", "expected": 1234.56 },
    "label": null
  },
  "assertion_schema_dep": {
    "schema_path": "total",
    "subtree_hash": "7d79dd764ab6548d",
    "depends_on_root": false
  },
  "assertion_drift_status": null,
  "schema_drift": "unknown",
  "schema_drift_detail": null,
  "validation_status": "valid",
  "validation_issues": [],
  "latest_run_summary": null,
  "latest_passing_run_summary": null,
  "latest_failing_run_summary": null,
  "created_at": "2026-05-01T14:30:00Z",
  "updated_at": "2026-05-01T14:30:00Z"
}

Authorizations

Api-Key
string
header
required

Path Parameters

workflow_id
string
required

Body

application/json
target
WorkflowTestBlockTarget · object
required

Public workflow-test target.

The storage layer remains block-scoped today, but the API shape names the tested entity explicitly so workflow-level targets can be added later.

source
ManualWorkflowTestSource · object
required
assertion
AssertionSpec · object
required

Block-test assertion against one declared output handle.

target is the only supported shape: an output handle id and an optional relative path inside that handle's payload.

name
string | null

Response

Successful Response

id
string
required
workflow_id
string
required
target
WorkflowTestBlockTarget · object
required

Public workflow-test target.

The storage layer remains block-scoped today, but the API shape names the tested entity explicitly so workflow-level targets can be added later.

source
ManualWorkflowTestSource · object
required
created_at
string<date-time>
required
updated_at
string<date-time>
required
name
string | null
assertion
AssertionSpec · object

Block-test assertion against one declared output handle.

target is the only supported shape: an output handle id and an optional relative path inside that handle's payload.

assertion_schema_dep
AssertionSchemaDep · object

Single-rule schema dependency for Level 2 drift detection.

assertion_drift_status
enum<string> | null
Available options:
valid,
drifted,
broken
schema_drift
enum<string>
default:unknown
Available options:
none,
partial,
drifted,
unknown
schema_drift_detail
string | null
validation_status
string
default:valid
validation_issues
any[]
latest_run_summary
LatestBlockTestRunSummary · object
latest_passing_run_summary
LatestBlockTestRunSummary · object
latest_failing_run_summary
LatestBlockTestRunSummary · object