Overview

A Workflow orchestrates multiple processors into a single document pipeline — for example, classify a document, route it to the right extractor, validate the result, then deliver it to your webhook. Workflows are async-only and run end to end on each file you submit.

This guide walks through the full lifecycle via the API: create → configure steps → deploy → run. Prefer a visual canvas? See Prefer the dashboard? at the end.

1. Create a workflow

POST /workflows creates a workflow and initializes an empty draft.

1import os
2from extend_ai import Extend
3
4client = Extend(token=os.environ["EXTEND_API_KEY"])
5
6workflow = client.workflows.create(name="Invoice Processing")
7print(workflow.id) # workflow_...

2. Configure the steps

A workflow is a graph of steps. Each step has a name, a type, an optional config, and a next array that defines where documents flow after it completes. Every workflow begins with a TRIGGER step followed by a PARSE step.

You can’t define an extractor’s config inline in a workflow step — an EXTRACT step references a published extractor by its processor id and version, so create the extractor first. See Processors and the Extraction overview.

Update the draft’s step graph with POST /workflows/{id} (update workflow):

1{
2 "steps": [
3 { "name": "trigger", "type": "TRIGGER", "next": [{ "step": "parse" }] },
4 { "name": "parse", "type": "PARSE", "next": [{ "step": "extract" }] },
5 {
6 "name": "extract",
7 "type": "EXTRACT",
8 "config": { "extractor": { "id": "ex_abc123", "version": "latest" } },
9 "next": [{ "step": "webhook" }]
10 },
11 { "name": "webhook", "type": "WEBHOOK_RESPONSE" }
12 ]
13}

This is the heart of building a workflow. For the full catalog of step types, routing rules (classify/split branching, conditional logic, validation), and complete patterns, see Configuring Workflows.

3. Deploy a version

Steps accumulate on the workflow’s draft. To make the workflow runnable, publish an immutable version with POST /workflows/{id}/versions (create workflow version):

1# Omitting `steps` deploys the current draft as-is
2version = client.workflow_versions.create(
3 "workflow_abc123",
4 name="Initial invoice pipeline",
5)
6print(version.id)

See Workflow Versioning for how draft, latest, and pinned semver versions behave.

4. Run the workflow

Submit a file to a deployed workflow with POST /workflow_runs. Workflow runs are asynchronous — poll with the SDK helper or receive results via webhook.

1# create_and_poll waits for the run to reach a terminal state
2run = client.workflow_runs.create_and_poll(
3 workflow={"id": "workflow_abc123"},
4 file={"url": "https://extend-public-files.s3.us-east-2.amazonaws.com/freight-invoice.pdf"},
5)
6
7print(run.status) # PROCESSED, NEEDS_REVIEW, FAILED, ...

For high volume or long-running pipelines, prefer webhooks over polling. See Asynchronous Processing and Batch processing for running many files at once.

Prefer the dashboard?

Extend Studio provides a visual canvas for the same lifecycle — drag steps onto the canvas, connect them, and deploy with a button.

  1. In the Studio, open Workflows and click Create new Workflow, then give it a name.
  2. Drag step types from the Step Drawer onto the canvas and connect them. Select a step to configure it — for an Extraction step, pick your published processor and version.
  3. Changes save automatically to the workflow draft.
  4. Click Deploy in the top-right to publish a new immutable version.

Workflows built in the Studio are run the same way — via POST /workflow_runs as shown above.

Next steps