Migration Guides2026-02-09

Edit Runs Migration

What You Get

  • Unified async endpoint/edit/async merged into /edit_runs, plus a new sync /edit endpoint for testing
  • createAndPoll() helper — Easy polling with client.editRuns.createAndPoll()
  • Cleaner output structure — Edited file and filled values organized under output
  • Better file infofile object instead of just fileId
  • Simplified response shapes — Single object responses returned directly (no wrapper key)

POST /edit/async has been replaced by POST /edit_runs and is no longer available. The sync POST /edit endpoint has been updated with a new request/response format.


This guide covers all breaking changes to the edit endpoints.

Summary of Changes

Old EndpointNew EndpointChange TypeDescription
POST /editPOST /editUpdatedSync endpoint updated with new request/response format (for testing only)
POST /editPOST /edit_runsNewAsync endpoint, recommended for production
POST /edit/asyncPOST /edit_runsReplacedUnified into single endpoint
GET /edit_runs/{id}GET /edit_runs/{id}ModifiedResponse simplified, always returns full EditRun
DELETE /edit_runs/{id}DELETE /edit_runs/{id}ModifiedResponse simplified

SDK Changes

The SDK group and method names have been updated for consistency:

Before (2025-04-21)
1const run = await client.edit.create({ file: { fileUrl: "https://..." }, config: {...} });
2const asyncRun = await client.edit.createAsync({ file: { fileUrl: "https://..." } });
3const result = await client.edit.get("edit_run_xyz789");
After (2026-02-09)
1const result = await client.editRuns.createAndPoll({ file: { url: "https://..." }, config: {...} });
2// Or create and poll manually
3const run = await client.editRuns.create({ file: { url: "https://..." }, config: {...} });
4const result = await client.editRuns.retrieve("edr_xyz789");

EditRun Schema

The EditRun schema has been restructured with file references changed from string IDs to objects, and output structure reorganized. Status-dependent fields are now required but nullable for a predictable response structure.

PropertyOld (EditRun)New (EditRun)Change
objectRequired "edit_run"Required "edit_run"No change
idRequired stringRequired stringNo change
fileIdRequired stringRemoved, see file
fileRequired FileSummaryNew (replaces fileId)
statusRequired (ref to EditRunStatus)Required RunStatus enumNow inline enum
failureReasonOptional stringRequired string | nullNow required but nullable (null unless FAILED)
configRequired object (inline)Required EditConfigNow uses named schema
editedFileOptional object (top-level)Moved to output.editedFile
editedFile.fileIdOptional stringRenamed to output.editedFile.id
editedFile.downloadUrlOptional stringRenamed to output.editedFile.presignedUrl
outputOptional object (field values only)Required object | nullRestructured, now required but nullable (null when not PROCESSED)
output.editedFileRequired objectNew (moved from top-level)
output.filledValuesRequired objectNew (renamed from output)
metricsRequired objectRequired object | nullNow required but nullable (null when not PROCESSED)
metrics.fieldsDetectedCountRequired integerNew
metrics.fieldsAnnotatedCountRequired integerNew
usageOptional objectRequired RunUsage | nullNow required but nullable

EditRun Response Example

1// Before (2025-04-21)
2{
3 "success": true,
4 "editRun": {
5 "object": "edit_run",
6 "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
7 "fileId": "file_Zk9mNP12Qw4yTv8BdR3H",
8 "editedFile": {
9 "fileId": "file_Ab3cDE45Fg6hIj7KlM8nO",
10 "downloadUrl": "https://extend-ai-files.s3.amazonaws.com/..."
11 },
12 "status": "PROCESSED",
13 "failureReason": null,
14 "config": {
15 "schema": {
16 "type": "object",
17 "properties": {
18 "fullName": { "type": ["string", "null"], "extend_edit:field_type": "text" }
19 }
20 },
21 "instructions": "Fill form with provided data",
22 "advancedOptions": {
23 "flattenPdf": true,
24 "tableParsingEnabled": false
25 }
26 },
27 "output": {
28 "fullName": "John Doe"
29 },
30 "metrics": {
31 "processingTimeMs": 1234,
32 "fieldCount": 10,
33 "pageCount": 2,
34 "fieldFillingTimeMs": 300,
35 "fieldDetectionTimeMs": 500,
36 "fieldAnnotationTimeMs": 200
37 },
38 "usage": {
39 "credits": 5.0
40 }
41 }
42}
43
44// After (2026-02-09) - all fields present, nullable fields use null when not applicable
45{
46 "object": "edit_run",
47 "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
48 "file": {
49 "object": "file",
50 "id": "file_Zk9mNP12Qw4yTv8BdR3H",
51 "name": "application-form.pdf",
52 "type": "PDF",
53 "parentFileId": null,
54 "metadata": {},
55 "createdAt": "2025-05-12T21:22:37.318Z",
56 "updatedAt": "2025-05-12T21:22:37.324Z"
57 },
58 "status": "PROCESSED",
59 "failureReason": null,
60 "config": {
61 "schema": {
62 "type": "object",
63 "properties": {
64 "fullName": { "type": ["string", "null"], "extend_edit:field_type": "text" }
65 }
66 },
67 "instructions": "Fill form with provided data",
68 "advancedOptions": {
69 "tableParsingEnabled": false,
70 "flattenPdf": true
71 }
72 },
73 "output": {
74 "editedFile": {
75 "id": "file_Ab3cDE45Fg6hIj7KlM8nO",
76 "presignedUrl": "https://extend-ai-files.s3.amazonaws.com/..."
77 },
78 "filledValues": {
79 "fullName": "John Doe"
80 }
81 },
82 "metrics": {
83 "processingTimeMs": 1234,
84 "pageCount": 2,
85 "fieldCount": 10,
86 "fieldsDetectedCount": 8,
87 "fieldsAnnotatedCount": 10,
88 "fieldDetectionTimeMs": 500,
89 "fieldAnnotationTimeMs": 200,
90 "fieldFillingTimeMs": 300
91 },
92 "usage": {
93 "credits": 5.0
94 }
95}

EditConfig Schema

The config object now uses a named EditConfig schema with updated advanced options.

PropertyOld (inline config)New (EditConfig)Change
schemaOptional EditRootJSONSchemaOptional EditRootJSONSchemaNo change
instructionsOptional stringOptional stringNo change
advancedOptionsOptional objectOptional objectNew field added
advancedOptions.flattenPdfOptional booleanOptional booleanDefault now documented as true
advancedOptions.tableParsingEnabledOptional booleanOptional booleanDefault now documented as false

File Input Changes

The file input format has been updated to use a oneOf schema with renamed properties.

Old PropertyNew PropertyChange
file.fileUrlfile.urlRenamed
file.fileIdfile.idRenamed
file.fileNamefile.nameRenamed

Request Example

1// Before (2025-04-21) - Using URL
2{
3 "file": {
4 "fileUrl": "https://example.com/form.pdf",
5 "fileName": "application-form.pdf"
6 },
7 "config": {
8 "schema": { ... },
9 "instructions": "Fill with provided data"
10 }
11}
12
13// After (2026-02-09) - Using URL
14{
15 "file": {
16 "url": "https://example.com/form.pdf",
17 "name": "application-form.pdf"
18 },
19 "config": {
20 "schema": { ... },
21 "instructions": "Fill with provided data"
22 }
23}
24
25// Before (2025-04-21) - Using File ID
26{
27 "file": {
28 "fileId": "file_xK9mLPqRtN3vS8wF5hB2cQ"
29 },
30 "config": { ... }
31}
32
33// After (2026-02-09) - Using File ID
34{
35 "file": {
36 "id": "file_xK9mLPqRtN3vS8wF5hB2cQ"
37 },
38 "config": { ... }
39}

POST /edit_runs (Create Edit Run)

Sync and Async Options

The 2026-02-09 API provides two ways to run edits:

  1. Sync (POST /edit) — Returns the completed result directly. Intended for testing and onboarding only.
  2. Async (POST /edit_runs) — Returns immediately, poll GET /edit_runs/{id} or use webhooks. Recommended for production. See Async Processing for details on polling helpers.
1// Sync (for testing) — client.edit() returns the completed result
2const result = await client.edit({
3 file: { url: "https://..." },
4 config: { schema: { ... } }
5});
6console.log(result.output);
7
8// Async with polling (recommended for production)
9const result = await client.editRuns.createAndPoll({
10 file: { url: "https://..." },
11 config: { schema: { ... } }
12});
13console.log(result.output);

Response Changes

Old ResponseNew ResponseChange
success: trueRemoved
Returns EditRun (sync)Returns EditRunAlways async, poll for results
Returns EditRunStatus (async)Returns EditRunNow always returns full EditRun

GET /edit_runs/{id} (Get Edit Run)

Response Changes

The response no longer uses a polymorphic oneOf between EditRunStatus and EditRun. It now always returns the full EditRun object.

Old ResponseNew ResponseChange
success: trueRemoved
warningRemoved
editRun: EditRunStatus | EditRuneditRun: EditRunAlways full EditRun

Response Example

1// Before (2025-04-21) - In progress (returned EditRunStatus)
2{
3 "success": true,
4 "editRun": {
5 "object": "edit_run_status",
6 "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
7 "status": "PROCESSING"
8 }
9}
10
11// Before (2025-04-21) - Complete (returned EditRun)
12{
13 "success": true,
14 "editRun": {
15 "object": "edit_run",
16 "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
17 "fileId": "file_Zk9mNP12Qw4yTv8BdR3H",
18 "editedFile": { ... },
19 "status": "PROCESSED",
20 "config": { ... },
21 "output": { ... },
22 "metrics": { ... },
23 "usage": { ... }
24 }
25}
26
27// After (2026-02-09) - In progress (all fields present, nullable fields are null)
28{
29 "object": "edit_run",
30 "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
31 "file": {
32 "object": "file",
33 "id": "file_Zk9mNP12Qw4yTv8BdR3H",
34 "name": "form.pdf",
35 ...
36 },
37 "status": "PROCESSING",
38 "failureReason": null,
39 "config": { ... },
40 "output": null,
41 "metrics": null,
42 "usage": null
43}
44
45// After (2026-02-09) - Complete
46{
47 "object": "edit_run",
48 "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
49 "file": { ... },
50 "status": "PROCESSED",
51 "failureReason": null,
52 "config": { ... },
53 "output": {
54 "editedFile": {
55 "id": "file_Ab3cDE45Fg6hIj7KlM8nO",
56 "presignedUrl": "https://..."
57 },
58 "filledValues": { ... }
59 },
60 "metrics": { ... },
61 "usage": { ... }
62}

DELETE /edit_runs/{id} (Delete Edit Run)

Response Changes

Old PropertyNew PropertyChange
success: trueRemoved
editRunIdidRenamed
messageRemoved

Response Example

1// Before (2025-04-21)
2{
3 "success": true,
4 "editRunId": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
5 "message": "Edit run data has been successfully deleted."
6}
7
8// After (2026-02-09)
9{
10 "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ"
11}

Output Structure Changes

The output structure has been reorganized to separate the edited file from the filled values.

Old LocationNew LocationChange
editRun.editedFileeditRun.output.editedFileMoved to nested output object
editRun.editedFile.fileIdeditRun.output.editedFile.idRenamed
editRun.editedFile.downloadUrleditRun.output.editedFile.presignedUrlRenamed
editRun.output (field values)editRun.output.filledValuesRenamed and moved

Migration Example

1// Before (2025-04-21)
2const editedFileUrl = editRun.editedFile?.downloadUrl;
3const editedFileId = editRun.editedFile?.fileId;
4const filledValues = editRun.output;
5
6// After (2026-02-09)
7const editedFileUrl = editRun.output?.editedFile?.presignedUrl;
8const editedFileId = editRun.output?.editedFile?.id;
9const filledValues = editRun.output?.filledValues;

Failure Reasons

The new API documents additional failure reasons that may be returned:

Failure ReasonDescription
UNABLE_TO_DOWNLOAD_FILEFailed to load the requested file
FILE_TYPE_NOT_SUPPORTEDFile type not supported (PDF required)
FILE_SIZE_TOO_LARGEFile exceeds maximum allowed size
CORRUPT_FILEFile appears corrupted
FIELD_DETECTION_ERRORError during field detection (new)
PASSWORD_PROTECTED_FILEFile is password protected
FAILED_TO_CONVERT_TO_PDFCould not convert to PDF
INTERNAL_ERRORUnexpected internal error
INVALID_OPTIONSInvalid configuration options (renamed from INVALID_CONFIG_OPTIONS)
EMPTY_SCHEMANo schema provided and no fields detected (new)
OUT_OF_CREDITSInsufficient credits (new)

SDK Method Reference

Old SDK MethodNew SDK Method
client.edit.create()client.editRuns.create()
client.edit.createAsync()client.editRuns.create()
client.edit.get()client.editRuns.retrieve()
client.edit.delete()client.editRuns.delete()

Need Help?

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


Migration Guides

GuideMigrating FromMigrating To
OverviewWhat’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.