Skip to main content
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

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json

Body carrying a workflow's full YAML definition for validate, plan, apply, or export.

yaml_definition
string
required

Workflow YAML definition

project_id
string | null

Project that should own a workflow created from this spec. Required when applying a spec that creates a new workflow.

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.

workflow_id
string
required
action
enum<string>
required
Available options:
create,
update,
noop
block_count
integer
required
edge_count
integer
required
diagnostics
Diagnostics · object
required
format_version
string
default:workflows-plan/v1
summary
DeclarativePlanSummary · object
resource_changes
DeclarativePlanResourceChange · object[]
rendered_plan
string
default:No changes. Workflow spec is up to date.