from retab import Retab
client = Retab()
edge = client.workflows.edges.create(
workflow_id="wf_abc123xyz",
id="edge-start-to-extract",
source_block="start-1",
target_block="extract-1",
source_handle="output-file-0",
target_handle="input-file-0",
)
print(edge.id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const edge = await client.workflows.edges.create("wf_abc123xyz", "start-1", "extract-1", "edge-start-to-extract", "output-file-0", "input-file-0");
console.log(edge.id);
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)
}
edge, err := client.Workflows.Edges.Create(ctx, &retab.WorkflowEdgesCreateParams{
WorkflowID: "wf_abc123xyz",
ID: ptr("edge-start-to-extract"),
SourceBlock: "start-1",
TargetBlock: "extract-1",
SourceHandle: ptr("output-file-0"),
TargetHandle: ptr("input-file-0"),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(edge.ID)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
edge = client.workflows.edges.create(
workflow_id: 'wf_abc123xyz',
id: 'edge-start-to-extract',
source_block: 'start-1',
target_block: 'extract-1',
source_handle: 'output-file-0',
target_handle: 'input-file-0',
)
puts edge.id
use retab::models::WorkflowEdgeCreateRequest;
use retab::resources::workflow_edges::CreateParams;
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 edge = client
.workflows().edges()
.create(CreateParams::new(WorkflowEdgeCreateRequest {
workflow_id: "wf_abc123xyz".into(),
id: Some("edge-start-to-extract".into()),
source_block: "start-1".into(),
target_block: "extract-1".into(),
source_handle: Some("output-file-0".into()),
target_handle: Some("input-file-0".into()),
}))
.await?;
println!("{}", edge.id);
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->edges()->create(
workflowId: 'wf_abc123',
sourceBlock: 'value',
targetBlock: 'value',
);
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.Edges.CreateAsync(new WorkflowEdgesCreateOptions());
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().edges().create("wf_abc123", null, null, null, null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/edges' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"workflow_id": "wf_abc123xyz",
"id": "edge-start-to-extract",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0"
}'
{
"id": "edge-start-to-extract",
"workflow_id": "wf_abc123xyz",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0",
"updated_at": "2026-05-01T14:30:00Z"
}
{
"detail": "Source or target block does not exist in this workflow"
}
{
"detail": "Workflow not found"
}
{
"detail": "Edge ID already exists in this workflow"
}
Edges
Create Edge
Create a new edge connecting two blocks.
Validates that:
- Both source and target blocks exist in the workflow
- The connection is semantically valid (type compatibility, container rules, etc.)
POST
/
v1
/
workflows
/
edges
from retab import Retab
client = Retab()
edge = client.workflows.edges.create(
workflow_id="wf_abc123xyz",
id="edge-start-to-extract",
source_block="start-1",
target_block="extract-1",
source_handle="output-file-0",
target_handle="input-file-0",
)
print(edge.id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const edge = await client.workflows.edges.create("wf_abc123xyz", "start-1", "extract-1", "edge-start-to-extract", "output-file-0", "input-file-0");
console.log(edge.id);
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)
}
edge, err := client.Workflows.Edges.Create(ctx, &retab.WorkflowEdgesCreateParams{
WorkflowID: "wf_abc123xyz",
ID: ptr("edge-start-to-extract"),
SourceBlock: "start-1",
TargetBlock: "extract-1",
SourceHandle: ptr("output-file-0"),
TargetHandle: ptr("input-file-0"),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(edge.ID)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
edge = client.workflows.edges.create(
workflow_id: 'wf_abc123xyz',
id: 'edge-start-to-extract',
source_block: 'start-1',
target_block: 'extract-1',
source_handle: 'output-file-0',
target_handle: 'input-file-0',
)
puts edge.id
use retab::models::WorkflowEdgeCreateRequest;
use retab::resources::workflow_edges::CreateParams;
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 edge = client
.workflows().edges()
.create(CreateParams::new(WorkflowEdgeCreateRequest {
workflow_id: "wf_abc123xyz".into(),
id: Some("edge-start-to-extract".into()),
source_block: "start-1".into(),
target_block: "extract-1".into(),
source_handle: Some("output-file-0".into()),
target_handle: Some("input-file-0".into()),
}))
.await?;
println!("{}", edge.id);
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->edges()->create(
workflowId: 'wf_abc123',
sourceBlock: 'value',
targetBlock: 'value',
);
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.Edges.CreateAsync(new WorkflowEdgesCreateOptions());
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().edges().create("wf_abc123", null, null, null, null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/edges' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"workflow_id": "wf_abc123xyz",
"id": "edge-start-to-extract",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0"
}'
{
"id": "edge-start-to-extract",
"workflow_id": "wf_abc123xyz",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0",
"updated_at": "2026-05-01T14:30:00Z"
}
{
"detail": "Source or target block does not exist in this workflow"
}
{
"detail": "Workflow not found"
}
{
"detail": "Edge ID already exists in this workflow"
}
Connect two blocks by creating an edge.
The create route is flat: send
workflow_id in the request body.
You provide the edge ID — it must be unique within the workflow. Use a readable convention (e.g. edge-start-to-extract) so the graph stays inspectable.
source_handle and target_handle reference handles declared by each block. The handle naming convention is direction + slot:
output-file-0,output-json-0,output-file-booking-confirmation,output-json-needs-review, …input-file-0,input-json-0, …
handle_key, not
the display label. Inspect the source block before wiring those edges.
from retab import Retab
client = Retab()
edge = client.workflows.edges.create(
workflow_id="wf_abc123xyz",
id="edge-start-to-extract",
source_block="start-1",
target_block="extract-1",
source_handle="output-file-0",
target_handle="input-file-0",
)
print(edge.id)
import { Retab } from "@retab/node";
const client = new Retab({ apiKey: process.env.RETAB_API_KEY });
const edge = await client.workflows.edges.create("wf_abc123xyz", "start-1", "extract-1", "edge-start-to-extract", "output-file-0", "input-file-0");
console.log(edge.id);
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)
}
edge, err := client.Workflows.Edges.Create(ctx, &retab.WorkflowEdgesCreateParams{
WorkflowID: "wf_abc123xyz",
ID: ptr("edge-start-to-extract"),
SourceBlock: "start-1",
TargetBlock: "extract-1",
SourceHandle: ptr("output-file-0"),
TargetHandle: ptr("input-file-0"),
})
if err != nil {
log.Fatal(err)
}
fmt.Println(edge.ID)
}
require 'retab'
client = Retab::Client.new(api_key: ENV['RETAB_API_KEY'])
edge = client.workflows.edges.create(
workflow_id: 'wf_abc123xyz',
id: 'edge-start-to-extract',
source_block: 'start-1',
target_block: 'extract-1',
source_handle: 'output-file-0',
target_handle: 'input-file-0',
)
puts edge.id
use retab::models::WorkflowEdgeCreateRequest;
use retab::resources::workflow_edges::CreateParams;
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 edge = client
.workflows().edges()
.create(CreateParams::new(WorkflowEdgeCreateRequest {
workflow_id: "wf_abc123xyz".into(),
id: Some("edge-start-to-extract".into()),
source_block: "start-1".into(),
target_block: "extract-1".into(),
source_handle: Some("output-file-0".into()),
target_handle: Some("input-file-0".into()),
}))
.await?;
println!("{}", edge.id);
Ok(())
}
<?php
require 'vendor/autoload.php';
use Retab\Client;
$client = new Client(apiKey: getenv('RETAB_API_KEY'));
$result = $client->workflows()->edges()->create(
workflowId: 'wf_abc123',
sourceBlock: 'value',
targetBlock: 'value',
);
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.Edges.CreateAsync(new WorkflowEdgesCreateOptions());
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().edges().create("wf_abc123", null, null, null, null, null);
System.out.println(result);
}
}
curl -X 'POST' \
'https://api.retab.com/v1/workflows/edges' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-api-key>' \
-d '{
"workflow_id": "wf_abc123xyz",
"id": "edge-start-to-extract",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0"
}'
{
"id": "edge-start-to-extract",
"workflow_id": "wf_abc123xyz",
"source_block": "start-1",
"target_block": "extract-1",
"source_handle": "output-file-0",
"target_handle": "input-file-0",
"updated_at": "2026-05-01T14:30:00Z"
}
{
"detail": "Source or target block does not exist in this workflow"
}
{
"detail": "Workflow not found"
}
{
"detail": "Edge ID already exists in this workflow"
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Create a new edge connecting two blocks in a workflow.
Response
Successful Response
Public live workflow edge object.
Foreign key to workflow
ID of the source block
ID of the target block
Output handle on source block
Input handle on target block
⌘I