from retab import Retab
client = Retab()
plan = client.workflows.plan(yaml_definition)
print(plan.action)
print(plan.rendered_plan)
for change in plan.resource_changes:
print(change.actions, change.target, change.target_id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const plan = await client.workflows.plan(yamlDefinition);
console.log(plan.action);
console.log(plan.renderedPlan);
for (const change of plan.resourceChanges) {
console.log(change.actions, change.target, change.targetId);
}
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)
}
yamlDefinition := `apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
`
plan, err := client.Workflows.Plan(ctx, &retab.WorkflowsPlanParams{
YamlDefinition: yamlDefinition,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(plan.Action)
fmt.Println(plan.RenderedPlan)
fmt.Println(plan.ResourceChanges)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
plan = client.workflows.plan(yaml_definition: yaml_definition)
puts plan.action
puts plan.rendered_plan
plan.resource_changes.each do |change|
puts "#{change.actions} #{change.target} #{change.target_id}"
end
use retab::models::DeclarativeWorkflowRequest;
use retab::resources::workflows::PlanParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let yaml_definition = r#"apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
"#;
let plan = client
.workflows()
.plan(PlanParams::new(DeclarativeWorkflowRequest::new(
yaml_definition,
)))
.await?;
println!("{}", plan.action);
println!("{}", plan.rendered_plan.as_deref().unwrap_or(""));
for change in plan.resource_changes.unwrap_or_default() {
println!("{:?} {} {}", change.actions, change.target, change.target_id);
}
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$yamlDefinition = <<<'YAML'
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
YAML;
$result = $client->workflows()->plan(yamlDefinition: $yamlDefinition);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var yamlDefinition = """
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
""";
var result = await client.Workflows.PlanAsync(
new WorkflowsPlanOptions { YamlDefinition = yamlDefinition }
);
Console.WriteLine(result);
import com.retab.RetabClient;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = client.workflows().plan("metadata:\n id: invoice-workflow\n", null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/spec/plan' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"yaml_definition": "apiVersion: workflows.retab.com/v1alpha2\nkind: Workflow\nmetadata:\n id: wf_invoice_demo\n name: Invoice Workflow\nspec:\n blocks:\n start:\n type: start_json\n label: Input JSON\n config:\n json_schema:\n type: object\n required:\n - value\n properties:\n value:\n type: string\n edges: []\n"
}'
{
"workflow_id": "wf_abc123",
"action": "update",
"block_count": 2,
"edge_count": 1,
"diagnostics": {
"issues": []
},
"format_version": "workflows-plan/v1",
"summary": {
"add": 0,
"change": 1,
"destroy": 0,
"replace": 0,
"noop": 0,
"total": 1,
"has_changes": true
},
"resource_changes": [
{
"address": "workflow.wf_abc123.block.block_extract",
"target": "block",
"target_id": "block_extract",
"name": "Extract Fields",
"type": "extract",
"actions": ["update"],
"summary": "Update block 'Extract Fields'",
"change": {
"before": {
"label": "Extract Fields",
"config": {
"model": "gpt-4.1"
}
},
"after": {
"label": "Extract Fields",
"config": {
"model": "gpt-5.1"
}
},
"before_sensitive": {},
"after_sensitive": {},
"field_changes": [
{
"path": ["config", "model"],
"path_display": "config.model",
"action": "update",
"before": "gpt-4.1",
"after": "gpt-5.1",
"before_sensitive": false,
"after_sensitive": false,
"unified_diff": null
}
]
},
"path": "extract-node"
}
],
"rendered_plan": "Workflow: wf_abc123\nPlan: 0 to add, 1 to change, 0 to destroy.\n\n~ workflow.wf_abc123.block.block_extract\n block \"Extract Fields\" will be updated\n ~ config.model\n - 'gpt-4.1'\n + 'gpt-5.1'"
}
Spec
Plan Workflow Spec
Preview the changes a declarative YAML spec would make to the draft workflow.
Compares the spec against the current draft and returns the resulting changes without applying them. A spec that already matches the draft plans as a no-op.
POST
/
v1
/
workflows
/
spec
/
plan
from retab import Retab
client = Retab()
plan = client.workflows.plan(yaml_definition)
print(plan.action)
print(plan.rendered_plan)
for change in plan.resource_changes:
print(change.actions, change.target, change.target_id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const plan = await client.workflows.plan(yamlDefinition);
console.log(plan.action);
console.log(plan.renderedPlan);
for (const change of plan.resourceChanges) {
console.log(change.actions, change.target, change.targetId);
}
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)
}
yamlDefinition := `apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
`
plan, err := client.Workflows.Plan(ctx, &retab.WorkflowsPlanParams{
YamlDefinition: yamlDefinition,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(plan.Action)
fmt.Println(plan.RenderedPlan)
fmt.Println(plan.ResourceChanges)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
plan = client.workflows.plan(yaml_definition: yaml_definition)
puts plan.action
puts plan.rendered_plan
plan.resource_changes.each do |change|
puts "#{change.actions} #{change.target} #{change.target_id}"
end
use retab::models::DeclarativeWorkflowRequest;
use retab::resources::workflows::PlanParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let yaml_definition = r#"apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
"#;
let plan = client
.workflows()
.plan(PlanParams::new(DeclarativeWorkflowRequest::new(
yaml_definition,
)))
.await?;
println!("{}", plan.action);
println!("{}", plan.rendered_plan.as_deref().unwrap_or(""));
for change in plan.resource_changes.unwrap_or_default() {
println!("{:?} {} {}", change.actions, change.target, change.target_id);
}
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$yamlDefinition = <<<'YAML'
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
YAML;
$result = $client->workflows()->plan(yamlDefinition: $yamlDefinition);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var yamlDefinition = """
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
""";
var result = await client.Workflows.PlanAsync(
new WorkflowsPlanOptions { YamlDefinition = yamlDefinition }
);
Console.WriteLine(result);
import com.retab.RetabClient;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = client.workflows().plan("metadata:\n id: invoice-workflow\n", null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/spec/plan' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"yaml_definition": "apiVersion: workflows.retab.com/v1alpha2\nkind: Workflow\nmetadata:\n id: wf_invoice_demo\n name: Invoice Workflow\nspec:\n blocks:\n start:\n type: start_json\n label: Input JSON\n config:\n json_schema:\n type: object\n required:\n - value\n properties:\n value:\n type: string\n edges: []\n"
}'
{
"workflow_id": "wf_abc123",
"action": "update",
"block_count": 2,
"edge_count": 1,
"diagnostics": {
"issues": []
},
"format_version": "workflows-plan/v1",
"summary": {
"add": 0,
"change": 1,
"destroy": 0,
"replace": 0,
"noop": 0,
"total": 1,
"has_changes": true
},
"resource_changes": [
{
"address": "workflow.wf_abc123.block.block_extract",
"target": "block",
"target_id": "block_extract",
"name": "Extract Fields",
"type": "extract",
"actions": ["update"],
"summary": "Update block 'Extract Fields'",
"change": {
"before": {
"label": "Extract Fields",
"config": {
"model": "gpt-4.1"
}
},
"after": {
"label": "Extract Fields",
"config": {
"model": "gpt-5.1"
}
},
"before_sensitive": {},
"after_sensitive": {},
"field_changes": [
{
"path": ["config", "model"],
"path_display": "config.model",
"action": "update",
"before": "gpt-4.1",
"after": "gpt-5.1",
"before_sensitive": false,
"after_sensitive": false,
"unified_diff": null
}
]
},
"path": "extract-node"
}
],
"rendered_plan": "Workflow: wf_abc123\nPlan: 0 to add, 1 to change, 0 to destroy.\n\n~ workflow.wf_abc123.block.block_extract\n block \"Extract Fields\" will be updated\n ~ config.model\n - 'gpt-4.1'\n + 'gpt-5.1'"
}
Compute the reconcile plan for a declarative workflow YAML spec against the current draft workflow. This does not mutate workflow state.
Use this before
apply() to see whether the spec will create a workflow, update blocks and edges, or no-op.
from retab import Retab
client = Retab()
plan = client.workflows.plan(yaml_definition)
print(plan.action)
print(plan.rendered_plan)
for change in plan.resource_changes:
print(change.actions, change.target, change.target_id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const plan = await client.workflows.plan(yamlDefinition);
console.log(plan.action);
console.log(plan.renderedPlan);
for (const change of plan.resourceChanges) {
console.log(change.actions, change.target, change.targetId);
}
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)
}
yamlDefinition := `apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
`
plan, err := client.Workflows.Plan(ctx, &retab.WorkflowsPlanParams{
YamlDefinition: yamlDefinition,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(plan.Action)
fmt.Println(plan.RenderedPlan)
fmt.Println(plan.ResourceChanges)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
plan = client.workflows.plan(yaml_definition: yaml_definition)
puts plan.action
puts plan.rendered_plan
plan.resource_changes.each do |change|
puts "#{change.actions} #{change.target} #{change.target_id}"
end
use retab::models::DeclarativeWorkflowRequest;
use retab::resources::workflows::PlanParams;
use retab::Retab;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Retab::new(std::env::var("RETAB_API_KEY")?);
let yaml_definition = r#"apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
"#;
let plan = client
.workflows()
.plan(PlanParams::new(DeclarativeWorkflowRequest::new(
yaml_definition,
)))
.await?;
println!("{}", plan.action);
println!("{}", plan.rendered_plan.as_deref().unwrap_or(""));
for change in plan.resource_changes.unwrap_or_default() {
println!("{:?} {} {}", change.actions, change.target, change.target_id);
}
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$yamlDefinition = <<<'YAML'
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
YAML;
$result = $client->workflows()->plan(yamlDefinition: $yamlDefinition);
print_r($result);
using Retab;
using RetabClient = Retab.Retab;
var apiKey = Environment.GetEnvironmentVariable("RETAB_API_KEY")!;
var client = new RetabClient(apiKey);
var yamlDefinition = """
apiVersion: workflows.retab.com/v1alpha2
kind: Workflow
metadata:
id: wf_invoice_demo
name: Invoice Workflow
spec:
blocks:
start:
type: start_json
label: Input JSON
config:
json_schema:
type: object
required:
- value
properties:
value:
type: string
edges: []
""";
var result = await client.Workflows.PlanAsync(
new WorkflowsPlanOptions { YamlDefinition = yamlDefinition }
);
Console.WriteLine(result);
import com.retab.RetabClient;
public final class Example {
public static void main(String[] args) throws Exception {
RetabClient client = new RetabClient(System.getenv("RETAB_API_KEY"));
var result = client.workflows().plan("metadata:\n id: invoice-workflow\n", null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/spec/plan' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"yaml_definition": "apiVersion: workflows.retab.com/v1alpha2\nkind: Workflow\nmetadata:\n id: wf_invoice_demo\n name: Invoice Workflow\nspec:\n blocks:\n start:\n type: start_json\n label: Input JSON\n config:\n json_schema:\n type: object\n required:\n - value\n properties:\n value:\n type: string\n edges: []\n"
}'
{
"workflow_id": "wf_abc123",
"action": "update",
"block_count": 2,
"edge_count": 1,
"diagnostics": {
"issues": []
},
"format_version": "workflows-plan/v1",
"summary": {
"add": 0,
"change": 1,
"destroy": 0,
"replace": 0,
"noop": 0,
"total": 1,
"has_changes": true
},
"resource_changes": [
{
"address": "workflow.wf_abc123.block.block_extract",
"target": "block",
"target_id": "block_extract",
"name": "Extract Fields",
"type": "extract",
"actions": ["update"],
"summary": "Update block 'Extract Fields'",
"change": {
"before": {
"label": "Extract Fields",
"config": {
"model": "gpt-4.1"
}
},
"after": {
"label": "Extract Fields",
"config": {
"model": "gpt-5.1"
}
},
"before_sensitive": {},
"after_sensitive": {},
"field_changes": [
{
"path": ["config", "model"],
"path_display": "config.model",
"action": "update",
"before": "gpt-4.1",
"after": "gpt-5.1",
"before_sensitive": false,
"after_sensitive": false,
"unified_diff": null
}
]
},
"path": "extract-node"
}
],
"rendered_plan": "Workflow: wf_abc123\nPlan: 0 to add, 1 to change, 0 to destroy.\n\n~ workflow.wf_abc123.block.block_extract\n block \"Extract Fields\" will be updated\n ~ config.model\n - 'gpt-4.1'\n + 'gpt-5.1'"
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Response
Successful Response
A preview of the changes a workflow YAML definition would make, with a per-resource diff and a human-readable rendered_plan.
Available options:
create, update, noop Show child attributes
Show child attributes
Show child attributes
Show child attributes
⌘I