from retab import Retab
client = Retab()
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
limit=50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
target_block_id="block_extract_invoice",
limit=20,
)
print(f"Workflow has {len(evals.data)} evals")
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const evals = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
limit: 50,
});
const evalsForBlock = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
targetBlockId: "block_extract_invoice",
limit: 20,
});
console.log(`Workflow has ${evals.data.length} evals`);
package main
import (
"context"
"fmt"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
// All evals for a workflow.
evals, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
PaginationParams: retab.PaginationParams{
Limit: ptr(50),
},
})
if err != nil {
log.Fatal(err)
}
// Only evals for one specific block.
evalsForBlock, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
TargetBlockID: ptr("block_extract_invoice"),
PaginationParams: retab.PaginationParams{
Limit: ptr(20),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Workflow has %d evals\n", len(evals.Data))
_ = evalsForBlock
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
limit: 50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
target_block_id: 'block_extract_invoice',
limit: 20,
)
puts "Workflow has #{evals.data.length} evals"
use retab::resources::workflow_evals::ListParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
// All evals for a workflow.
let evals = client
.workflows()
.evals()
.list(ListParams {
limit: Some(50),
..ListParams::new("wf_abc123xyz")
})
.await?;
// Only evals for one specific block.
let _evals_for_block = client
.workflows()
.evals()
.list(ListParams {
target_block_id: Some("block_extract_invoice".into()),
limit: Some(20),
..ListParams::new("wf_abc123xyz")
})
.await?;
println!("Workflow has {} evals", evals.data.len());
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->list(
workflowId: 'wf_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.ListAsync(new WorkflowEvalsListOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).list("wf_abc123", null, null, null, 10L, null);
System.out.println(result);
}
}
# All evals
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&limit=50' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
# Filtered by target block
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&target_block_id=block_extract_invoice&limit=20' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
{
"data": [
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"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"
},
"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": "none",
"schema_drift_detail": null,
"validation_status": "valid",
"validation_issues": [],
"latest_run_summary": {
"run_record_id": "wfnodeevalrun_abc123",
"status": "completed",
"outcome": "passed",
"started_at": "2026-05-01T13:55:00Z",
"completed_at": "2026-05-01T13:55:18Z",
"duration_ms": 18221,
"workflow_draft_fingerprint": "ddd95baadce6045f",
"block_execution_fingerprint": "0ff93ddc7cefcb42",
"assertions_passed": 1,
"assertions_failed": 0,
"blocked_assertions": 0
},
"latest_passing_run_summary": { "...": "as above" },
"latest_failing_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-04-08T14:27:52Z"
}
],
"list_metadata": {
"before": null,
"after": null
}
}
Evals
List Workflow Evals
List workflow evals.
Requires workflow_id and returns its saved evals as a cursor-paginated
list, each with its latest-run summaries and drift status. Optionally
filter to one block with target_block_id. Returns 404 if the workflow
does not exist.
GET
/
v1
/
workflows
/
evals
from retab import Retab
client = Retab()
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
limit=50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
target_block_id="block_extract_invoice",
limit=20,
)
print(f"Workflow has {len(evals.data)} evals")
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const evals = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
limit: 50,
});
const evalsForBlock = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
targetBlockId: "block_extract_invoice",
limit: 20,
});
console.log(`Workflow has ${evals.data.length} evals`);
package main
import (
"context"
"fmt"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
// All evals for a workflow.
evals, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
PaginationParams: retab.PaginationParams{
Limit: ptr(50),
},
})
if err != nil {
log.Fatal(err)
}
// Only evals for one specific block.
evalsForBlock, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
TargetBlockID: ptr("block_extract_invoice"),
PaginationParams: retab.PaginationParams{
Limit: ptr(20),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Workflow has %d evals\n", len(evals.Data))
_ = evalsForBlock
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
limit: 50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
target_block_id: 'block_extract_invoice',
limit: 20,
)
puts "Workflow has #{evals.data.length} evals"
use retab::resources::workflow_evals::ListParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
// All evals for a workflow.
let evals = client
.workflows()
.evals()
.list(ListParams {
limit: Some(50),
..ListParams::new("wf_abc123xyz")
})
.await?;
// Only evals for one specific block.
let _evals_for_block = client
.workflows()
.evals()
.list(ListParams {
target_block_id: Some("block_extract_invoice".into()),
limit: Some(20),
..ListParams::new("wf_abc123xyz")
})
.await?;
println!("Workflow has {} evals", evals.data.len());
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->list(
workflowId: 'wf_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.ListAsync(new WorkflowEvalsListOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).list("wf_abc123", null, null, null, 10L, null);
System.out.println(result);
}
}
# All evals
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&limit=50' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
# Filtered by target block
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&target_block_id=block_extract_invoice&limit=20' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
{
"data": [
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"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"
},
"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": "none",
"schema_drift_detail": null,
"validation_status": "valid",
"validation_issues": [],
"latest_run_summary": {
"run_record_id": "wfnodeevalrun_abc123",
"status": "completed",
"outcome": "passed",
"started_at": "2026-05-01T13:55:00Z",
"completed_at": "2026-05-01T13:55:18Z",
"duration_ms": 18221,
"workflow_draft_fingerprint": "ddd95baadce6045f",
"block_execution_fingerprint": "0ff93ddc7cefcb42",
"assertions_passed": 1,
"assertions_failed": 0,
"blocked_assertions": 0
},
"latest_passing_run_summary": { "...": "as above" },
"latest_failing_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-04-08T14:27:52Z"
}
],
"list_metadata": {
"before": null,
"after": null
}
}
List all workflow evals for a workflow. Optionally filter by
target_block_id to
get only the evals that target a specific block.
Each entry in data is a full WorkflowEval (target, source, assertion,
schema-drift state, latest run summaries). Use this to populate an Evals page
or to check whether a workflow has any evals before offering to run them.
The response uses the canonical Retab list envelope:
{ "data": [...], "list_metadata": { "before": null, "after": null } }.
from retab import Retab
client = Retab()
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
limit=50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id="wf_abc123xyz",
target_block_id="block_extract_invoice",
limit=20,
)
print(f"Workflow has {len(evals.data)} evals")
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const evals = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
limit: 50,
});
const evalsForBlock = await client.workflows.evals.list({
workflowId: "wf_abc123xyz",
targetBlockId: "block_extract_invoice",
limit: 20,
});
console.log(`Workflow has ${evals.data.length} evals`);
package main
import (
"context"
"fmt"
"log"
retab "github.com/retab-dev/retab/clients/go"
)
func ptr[T any](v T) *T { return &v }
func main() {
ctx := context.Background()
client, err := retab.NewClient("")
if err != nil {
log.Fatal(err)
}
// All evals for a workflow.
evals, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
PaginationParams: retab.PaginationParams{
Limit: ptr(50),
},
})
if err != nil {
log.Fatal(err)
}
// Only evals for one specific block.
evalsForBlock, err := client.Workflows.Evals.List(ctx, &retab.WorkflowEvalsListParams{
WorkflowID: "wf_abc123xyz",
TargetBlockID: ptr("block_extract_invoice"),
PaginationParams: retab.PaginationParams{
Limit: ptr(20),
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Workflow has %d evals\n", len(evals.Data))
_ = evalsForBlock
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
# All evals for a workflow.
evals = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
limit: 50,
)
# Only evals for one specific block.
evals_for_block = client.workflows.evals.list(
workflow_id: 'wf_abc123xyz',
target_block_id: 'block_extract_invoice',
limit: 20,
)
puts "Workflow has #{evals.data.length} evals"
use retab::resources::workflow_evals::ListParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
// All evals for a workflow.
let evals = client
.workflows()
.evals()
.list(ListParams {
limit: Some(50),
..ListParams::new("wf_abc123xyz")
})
.await?;
// Only evals for one specific block.
let _evals_for_block = client
.workflows()
.evals()
.list(ListParams {
target_block_id: Some("block_extract_invoice".into()),
limit: Some(20),
..ListParams::new("wf_abc123xyz")
})
.await?;
println!("Workflow has {} evals", evals.data.len());
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->evals()->list(
workflowId: 'wf_abc123',
);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var result = await client.Workflows.Evals.ListAsync(new WorkflowEvalsListOptions());
Console.WriteLine(result);
import com.retab.RetabClient;
import com.retab.workflowevals.WorkflowEvalsApi;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = new WorkflowEvalsApi(client).list("wf_abc123", null, null, null, 10L, null);
System.out.println(result);
}
}
# All evals
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&limit=50' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
# Filtered by target block
curl -X 'GET' \
'https://api.retab.com/v1/workflows/evals?workflow_id=wf_abc123xyz&target_block_id=block_extract_invoice&limit=20' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <your-api-key>'
{
"data": [
{
"id": "wfnodeeval_hsLEQiM61ez9Piv147MWk",
"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"
},
"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": "none",
"schema_drift_detail": null,
"validation_status": "valid",
"validation_issues": [],
"latest_run_summary": {
"run_record_id": "wfnodeevalrun_abc123",
"status": "completed",
"outcome": "passed",
"started_at": "2026-05-01T13:55:00Z",
"completed_at": "2026-05-01T13:55:18Z",
"duration_ms": 18221,
"workflow_draft_fingerprint": "ddd95baadce6045f",
"block_execution_fingerprint": "0ff93ddc7cefcb42",
"assertions_passed": 1,
"assertions_failed": 0,
"blocked_assertions": 0
},
"latest_passing_run_summary": { "...": "as above" },
"latest_failing_run_summary": null,
"created_at": "2026-04-08T14:22:26Z",
"updated_at": "2026-04-08T14:27:52Z"
}
],
"list_metadata": {
"before": null,
"after": null
}
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Query Parameters
Required range:
1 <= x <= 100Available options:
asc, desc Response
Successful Response
A page of WorkflowEval resources. data holds the items and list_metadata carries the before/after cursors; pass after to fetch the next page.
⌘I