Migration Guides2026-02-09

Workflow Runs Migration

What You Get

  • Single-file runs β€” Each request processes one file, giving you a single WorkflowRun back instead of an array
  • Typed step runs β€” stepRuns now includes all step types (extraction, classification, splitting, etc.) with typed results, replacing the old outputs array
  • Cleaner request/response format β€” Simpler property names, unwrapped responses, predictable nullable fields
  • Polling helpers β€” createAndPoll / create_and_poll handles polling with exponential backoff

The old /workflow_runs request and response shapes from 2025-04-21 are not carried forwardβ€”you’ll need to update your integration to use the new format.


Quick Start: Common Patterns

Running a Workflow

Before (2025-04-21)
1const response = await client.workflowRun.create({
2 workflowId: "workflow_abc123",
3 files: [{ fileUrl: "https://example.com/invoice.pdf", fileName: "invoice.pdf" }],
4 version: "3",
5 metadata: { customerId: "cust_123" }
6});
7if (response.success) {
8 const run = response.workflowRuns[0]; // Array of runs, one per file
9 console.log(run.outputs); // ProcessorRun[]
10}
After (2026-02-09)
1const run = await client.workflowRuns.create({
2 workflow: { id: "workflow_abc123", version: "3" },
3 file: { url: "https://example.com/invoice.pdf", name: "invoice.pdf" },
4 metadata: { customerId: "cust_123" }
5});
6console.log(run.stepRuns); // Typed StepRun[] with all step types

Using Polling Helpers

The SDK provides createAndPoll / create_and_poll methods that handle polling automatically, returning when the run reaches a terminal state (PROCESSED, FAILED, CANCELLED, NEEDS_REVIEW, or REJECTED):

1const result = await client.workflowRuns.createAndPoll({
2 workflow: { id: "workflow_abc123" },
3 file: { url: "https://example.com/invoice.pdf" }
4});
5console.log(result.status);
6console.log(result.stepRuns);
Workflow runs can take a long time. Complex workflows may run for hours. For long-running workflows, consider using webhooks instead of polling.

Processing Multiple Files

The old API accepted an array of files in a single request. The new API processes one file at a time. To process multiple files, make separate requests or use the batch endpoint:

Before (2025-04-21) β€” multiple files in one request
1const response = await client.workflowRun.create({
2 workflowId: "workflow_abc123",
3 files: [
4 { fileUrl: "https://example.com/file1.pdf" },
5 { fileUrl: "https://example.com/file2.pdf" },
6 { fileUrl: "https://example.com/file3.pdf" }
7 ]
8});
9const runs = response.workflowRuns; // 3 runs
After (2026-02-09) β€” one file per request
1// Option 1: Separate requests
2const run1 = await client.workflowRuns.create({
3 workflow: { id: "workflow_abc123" },
4 file: { url: "https://example.com/file1.pdf" }
5});
6
7// Option 2: Batch endpoint for bulk processing
8const batch = await client.workflowRuns.createBatch({
9 workflow: { id: "workflow_abc123" },
10 inputs: [
11 { file: { url: "https://example.com/file1.pdf" } },
12 { file: { url: "https://example.com/file2.pdf" } },
13 { file: { url: "https://example.com/file3.pdf" } }
14 ]
15});
16console.log(batch.batchId); // Use to track via webhooks or list endpoint

Listing Workflow Runs

Before
1const response = await client.workflowRun.list({
2 workflowId: "workflow_abc123",
3 status: "PROCESSED"
4});
5const runs = response.workflowRuns;
After
1const response = await client.workflowRuns.list({
2 workflowId: "workflow_abc123",
3 status: "PROCESSED"
4});
5const runs = response.data;

Getting a Workflow Run

Before
1const response = await client.workflowRun.get("workflow_run_abc123");
2const run = response.workflowRun;
3console.log(run.outputs);
After
1const run = await client.workflowRuns.retrieve("workflow_run_abc123");
2console.log(run.stepRuns);

Using Raw Text Instead of Files

Before (2025-04-21)
1const response = await client.workflowRun.create({
2 workflowId: "workflow_abc123",
3 rawTexts: ["Invoice #123\nVendor: Acme Corp\nTotal: $500"]
4});
After (2026-02-09)
1const run = await client.workflowRuns.create({
2 workflow: { id: "workflow_abc123" },
3 file: { text: "Invoice #123\nVendor: Acme Corp\nTotal: $500" }
4});

Endpoint Changes Summary

Old EndpointNew EndpointNotes
POST /workflow_runsPOST /workflow_runsRequest/response shape changed significantly
GET /workflow_runsGET /workflow_runsResponse shape changed
GET /workflow_runs/{workflowRunId}GET /workflow_runs/{id}Path param renamed
POST /workflow_runs/{workflowRunId}POST /workflow_runs/{id}Path param renamed
DELETE /workflow_runs/{workflowRunId}DELETE /workflow_runs/{id}Path param renamed, response simplified
POST /workflow_runs/{workflowRunId}/cancelPOST /workflow_runs/{id}/cancelPath param renamed
POST /workflow_runs/{workflowRunId}/outputs/{outputId}(removed)Correct Outputs endpoint removed
POST /workflow_runs/batchPOST /workflow_runs/batchRequest shape changed

Request Changes

File Properties (All Endpoints)

OldNew
fileUrlurl
fileIdid
fileNamename
rawTexts (array)file.text (single string via FileFromText)

Creating a Workflow Run

OldNewNotes
workflowIdworkflow.idNested in workflow object
versionworkflow.versionNested in workflow object
files (array)file (single object)One file per request. Use batch endpoint for multiple files
files[].fileUrlfile.urlRenamed
files[].fileIdfile.idRenamed
files[].fileNamefile.nameRenamed
rawTextsfile.textUse FileFromText input
files[].outputsoutputsMoved to top-level
files[].outputs[].processorIdoutputs[].processorIdNow references extractor/classifier/splitter IDs (e.g., ex_, cl_, sp_ prefixed)
β€”secretsNew. Pass secrets to processors in the workflow

Breaking change: The files array has been replaced with a single file object. If you previously processed multiple files in one request, you’ll need to either make separate requests or use the Batch Run Workflow endpoint.

Example: Create Request

1{
2 "workflowId": "workflow_abc123",
3 "version": "3",
4 "files": [
5 {
6 "fileUrl": "https://example.com/invoice.pdf",
7 "fileName": "invoice.pdf"
8 }
9 ],
10 "metadata": { "customerId": "cust_123" }
11}

Batch Run Request

1{
2 "workflowId": "workflow_abc123",
3 "version": "2",
4 "inputs": [
5 {
6 "file": { "fileUrl": "https://example.com/file1.pdf", "fileName": "file1.pdf" },
7 "metadata": { "source": "upload" }
8 },
9 {
10 "rawText": "Raw invoice data here...",
11 "metadata": { "source": "email" }
12 }
13 ]
14}

Response Changes

Response shape changes: Single object responses are now returned directly (no wrapper key), and list responses use { "object": "list", "data": [...] } format. See Simplified Response Shapes for details.

Key Differences

OldNewNotes
success: true(removed)Use HTTP status codes
{ workflowRuns: [...] } (create)Direct WorkflowRun objectSingle file = single response
{ workflowRun: {...} } (get/update)Direct WorkflowRun objectUnwrapped
{ workflowRuns: [...] } (list){ object: "list", data: [...] }Standardized list format
run.urlrun.dashboardUrlRenamed
run.name(removed)No longer on the run object
run.workflow (flat object)run.workflow + run.workflowVersionSplit into two objects
run.workflow.versionrun.workflowVersion.versionMoved to separate object
run.outputs (ProcessorRun[])(removed)Replaced by stepRuns
run.stepRuns (validation only)run.stepRuns (all step types)Now includes extraction, classification, splitting, etc.
run.reviewedByrun.reviewedByUserRenamed
Optional fields (may be absent)Required but nullable (always present)Predictable response shape

Example: Create Response

1{
2 "success": true,
3 "workflowRuns": [
4 {
5 "object": "workflow_run",
6 "id": "workflow_run_abc123",
7 "name": "invoice.pdf",
8 "url": "https://dashboard.extend.ai/workflows/workflow_abc?workflowRunId=workflow_run_abc123",
9 "status": "PENDING",
10 "metadata": {},
11 "batchId": "batch_xyz",
12 "files": [{ "id": "file_123", "name": "invoice.pdf", "type": "PDF" }],
13 "outputs": [],
14 "stepRuns": [],
15 "workflow": {
16 "object": "workflow",
17 "id": "workflow_abc",
18 "version": "3",
19 "name": "Invoice Processing"
20 }
21 }
22 ]
23}

Example: Completed Response with Step Runs

The biggest change is how processor results are returned. Previously, results lived in the outputs array as ProcessorRun objects. Now, results are in stepRuns as typed StepRun objects:

1{
2 "success": true,
3 "workflowRun": {
4 "id": "workflow_run_abc123",
5 "status": "PROCESSED",
6 "outputs": [
7 {
8 "object": "document_processor_run",
9 "id": "dpr_extract1",
10 "type": "EXTRACT",
11 "status": "PROCESSED",
12 "output": {
13 "value": { "vendorName": "Acme Corp", "total": 500.00 }
14 }
15 },
16 {
17 "object": "document_processor_run",
18 "id": "dpr_classify1",
19 "type": "CLASSIFY",
20 "status": "PROCESSED",
21 "output": {
22 "type": "INVOICE",
23 "confidence": 0.98
24 }
25 }
26 ],
27 "stepRuns": []
28 }
29}

Example: List Response

1{
2 "success": true,
3 "workflowRuns": [
4 {
5 "id": "workflow_run_abc123",
6 "status": "PROCESSED",
7 "workflowId": "workflow_abc",
8 "workflowName": "Invoice Processing",
9 "workflowVersionId": "workflow_version_xyz",
10 "createdAt": "2024-03-21T15:29:55Z",
11 "updatedAt": "2024-03-21T16:45:00Z"
12 }
13 ],
14 "nextPageToken": "..."
15}

Example: Delete Response

1{
2 "success": true,
3 "workflowRunId": "workflow_run_abc123",
4 "message": "Workflow run data has been successfully deleted."
5}

Removed Endpoint: Correct Workflow Run Outputs

The POST /workflow_runs/{workflowRunId}/outputs/{outputId} endpoint for submitting corrected outputs has been removed. This was deprecated in the 2025-04-21 API.


SDK Method Reference

Old MethodNew Method
client.workflowRun.create()client.workflowRuns.create()
client.workflowRun.get()client.workflowRuns.retrieve()
client.workflowRun.list()client.workflowRuns.list()
client.workflowRun.update()client.workflowRuns.update()
client.workflowRun.delete()client.workflowRuns.delete()
client.workflowRun.cancel()client.workflowRuns.cancel()
client.batchWorkflowRun.create()client.workflowRuns.createBatch()
client.workflowRunOutput.update()(removed)
β€”client.workflowRuns.createAndPoll() (new)

WorkflowRun Schema

PropertyOld (2025-04-21)New (2026-02-09)Change
object"workflow_run""workflow_run"No change
idRequired stringRequired stringNo change
nameRequired stringβ€”Removed
urlRequired stringβ€”Renamed to dashboardUrl
dashboardUrlβ€”Required stringNew (replaces url)
statusRequiredRequiredNo change
metadataOptional JsonObjectRequired RunMetadataNow required
batchIdOptional stringRequired but nullable stringNow required
filesRequired File[]Required FileSummary[]Simplified file objects
workflowWorkflow (with version)WorkflowSummary (no version)Split into two fields
workflowVersionβ€”Required WorkflowVersionSummaryNew (version info moved here)
outputsRequired ProcessorRun[]β€”Removed. Use stepRuns
stepRunsRequired (validation types only)Required (all step types)Expanded. Now includes PARSE, EXTRACT, CLASSIFY, SPLIT, MERGE_EXTRACT, CONDITIONAL_EXTRACT, RULE_VALIDATION, and EXTERNAL_DATA_VALIDATION
failureReasonOptional stringRequired but nullable stringNow required
failureMessageOptional stringRequired but nullable stringNow required
initialRunAtRequired date-timeRequired but nullable date-timeNow nullable
reviewedByOptional stringβ€”Renamed to reviewedByUser
reviewedByUserβ€”Required but nullable stringNew (replaces reviewedBy)
reviewedRequired booleanRequired booleanNo change
rejectionNoteOptional stringRequired but nullable stringNow required
reviewedAtOptional date-timeRequired but nullable date-timeNow required
startTimeOptional date-timeRequired but nullable date-timeNow required
endTimeOptional date-timeRequired but nullable date-timeNow required
usageOptional WorkflowRunCreditsRequired but nullable RunUsageNow required, type changed

WorkflowRunSummary Schema (List Response)

PropertyOld (2025-04-21)New (2026-02-09)Change
objectβ€”"workflow_run"New
idRequired stringRequired stringNo change
statusRequiredRequiredNo change
workflowIdRequired stringβ€”Removed, see workflow.id
workflowNameRequired stringβ€”Removed, see workflow.name
workflowVersionIdRequired stringβ€”Removed, see workflowVersion.id
workflowβ€”Required WorkflowSummaryNew
workflowVersionβ€”Required WorkflowVersionSummaryNew
dashboardUrlβ€”Required stringNew
createdAtRequired date-timeRequired date-timeNo change
updatedAtRequired date-timeRequired date-timeNo change
reviewedByUserOptional stringRequired but nullable stringNow required
reviewedAtOptional date-timeRequired but nullable date-timeNow required
initialRunAtOptional date-timeRequired date-timeNow required
startTimeOptional date-timeRequired date-timeNow required
endTimeOptional date-timeRequired date-timeNow required
batchIdβ€”Required but nullable stringNew
rejectionNoteβ€”Required but nullable stringNew
usageβ€”Required but nullable RunUsageNew

StepRun Schema

Old (2025-04-21)New (2026-02-09)
Simple object typeDiscriminated union (oneOf)
step.type: EXTERNAL_DATA_VALIDATION, RULE_VALIDATION onlystep.type: PARSE, EXTRACT, CLASSIFY, SPLIT, MERGE_EXTRACT, CONDITIONAL_EXTRACT, RULE_VALIDATION, EXTERNAL_DATA_VALIDATION
output fieldresult field (typed per step type)
No workflowRunIdworkflowRunId included
No filesfiles array included
Status: PENDING, PROCESSING, PROCESSED, FAILED, CANCELLEDStatus: adds WAITING

Need Help?

If you encounter any issues while migrating, please contact our support team at support@extend.app.


Migration Guides

GuideMigrating FromMigrating To
Overviewβ€”What’s new and how to upgrade
Extract Runs/processor_runs/extract_runs + /extract
Classify Runs/processor_runs/classify_runs + /classify
Split Runs/processor_runs/split_runs + /split
Parse Runs/parse, /parse/async/parse_runs + /parse
Edit Runs/edit, /edit/async/edit_runs + /edit
Extractors/processors/extractors
Classifiers/processors/classifiers
Splitters/processors/splitters
Files/files/files (breaking changes)
Evaluation Setsevaluation endpointsUpdated evaluation endpoints
Workflow Runs/workflow_runs/workflow_runs (breaking changes)
Webhooksprocessor_run.* eventsextract_run.*, classify_run.*, etc.