Workflows 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.

1from extend_ai import Extend
2
3client = Extend()
4
5workflow = client.workflows.create(name="Invoice Processing")
6print(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.

An EXTRACT step can reference a published extractor by its processor id and version (create the extractor first — see Processors and the Extraction overview), or embed the full extractor configuration inline with extractorConfig — no saved extractor needed. See Saved processors vs. inline configs.

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.

Pass either a single file or a package of files — see Package runs below.

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.

Package runs

When several documents belong together — an invoice with its bill of lading and delivery receipt, or a loan application split across separate PDFs — submit them as a package instead of a single file. Pass package in place of file and Extend ingests every file up front, then runs the workflow over the full set as one WorkflowRun.

1run = client.workflow_runs.create_and_poll(
2 workflow={"id": "workflow_abc123"},
3 package={
4 "files": [
5 {"url": "https://example.com/invoice.pdf"},
6 {"url": "https://example.com/bill-of-lading.pdf"},
7 {"id": "file_xK9mLPqRtN3vS8wF5hB2cQ"},
8 ]
9 },
10)
11
12print([f.name for f in run.files]) # one entry per file

Constraints

  • file and package are mutually exclusive — provide exactly one. Sending both, or neither, returns a 400.
  • package.files accepts 2–50 entries. For a single document, use file.
  • Each entry must be a { "url": ... } or { "id": ... }. Raw text and base64 inputs are not supported in packages.
  • Duplicates are rejected: the same file ID cannot appear twice, and neither can the same URL. A URL and a file ID are never treated as duplicates of each other, even if they point at the same document.
  • outputs cannot be combined with package. A package run produces a single merged result across all files, so there is nowhere to attach pre-supplied per-processor outputs.

Response

A package run returns the same WorkflowRun shape as a single-file run. The files array holds one FileSummary per input file, rather than the single entry a file run returns.

A package is one run over a set of documents. To process many files independently, use the Batch Run Workflow endpoint instead — it creates one workflow run per file. See Batch processing.

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