> This page is for version v2026-02-09 (default).
> For other versions, use one of these documentation indexes:
> - v2026-02-09 (default): https://docs.extend.ai/2026-02-09/llms.txt
> - v2025-04-21: https://docs.extend.ai/2025-04-21/llms.txt
> - v2024-12-23: https://docs.extend.ai/2024-12-23/llms.txt

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.extend.ai/llms.txt
> Use this file to discover all available pages before exploring further.
>
> ## API version
> The current API version is `2026-02-09`, served at the site root (no version prefix in URLs).
> If this page URL contains `/2025-04-21/` or `/2024-12-23/`, you are reading an older API version.
> Prefer the current docs at https://docs.extend.ai/llms.txt unless the user explicitly needs that older version.
> Do not treat older-version pages as the source of truth for new integrations.

# Edit Runs Migration

> Migrate from /edit to /edit_runs

## 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 info** — `file` object instead of just `fileId`
* **Simplified response shapes** — Single object responses returned directly (no wrapper key)
* **Sync and async form detection** — Use `/detect_form` for synchronous testing or `/form_detection_runs` for production workloads

> **Note**
>
> `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. `POST /edit_schemas/generate` is deprecated; use `POST /detect_form` or `POST /form_detection_runs` instead.

---

This guide covers all breaking changes to the edit endpoints.

## Summary of Changes

| Old Endpoint                  | New Endpoint                    | Change Type | Description                                                               |
| ----------------------------- | ------------------------------- | ----------- | ------------------------------------------------------------------------- |
| `POST /edit`                  | `POST /edit`                    | Updated     | Sync endpoint updated with new request/response format (for testing only) |
| `POST /edit`                  | `POST /edit_runs`               | New         | Async endpoint, recommended for production                                |
| `POST /edit/async`            | `POST /edit_runs`               | Replaced    | Unified into single endpoint                                              |
| `GET /edit_runs/{id}`         | `GET /edit_runs/{id}`           | Modified    | Response simplified, always returns full EditRun                          |
| `DELETE /edit_runs/{id}`      | `DELETE /edit_runs/{id}`        | Modified    | Response simplified                                                       |
| `POST /edit_schemas/generate` | `POST /detect_form`             | Replaced    | Sync form detection now returns a `form_detection_run` resource           |
| —                             | `POST /form_detection_runs`     | New         | Start form detection asynchronously                                       |
| —                             | `GET /form_detection_runs/{id}` | New         | Poll form detection status and retrieve the generated schema              |

The deprecated `POST /edit_schemas/generate` endpoint remains available for compatibility, but new integrations should use the form detection endpoints. See [Detect Form](/editing/detect-form) for request examples and response details.

---

## SDK Changes

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

#### TypeScript

**`Before (2025-04-21)`**

```typescript title="Before (2025-04-21)"
const run = await client.edit.create({ file: { fileUrl: "https://..." }, config: {...} });
const asyncRun = await client.edit.createAsync({ file: { fileUrl: "https://..." } });
const result = await client.edit.get("edit_run_xyz789");
```

**`After (2026-02-09)`**

```typescript title="After (2026-02-09)"
const result = await client.editRuns.createAndPoll({ file: { url: "https://..." }, config: {...} });
// Or create and poll manually
const run = await client.editRuns.create({ file: { url: "https://..." }, config: {...} });
const result = await client.editRuns.retrieve("edr_xyz789");
```

#### Python

**`Before (2025-04-21)`**

```python title="Before (2025-04-21)"
run = client.edit.create(file={"file_url": "https://..."}, config={...})
async_run = client.edit.create_async(file={"file_url": "https://..."})
result = client.edit.get("edit_run_xyz789")
```

**`After (2026-02-09)`**

```python title="After (2026-02-09)"
result = client.edit_runs.create_and_poll(file={"url": "https://..."}, config={...})
# Or create and poll manually
run = client.edit_runs.create(file={"url": "https://..."}, config={...})
result = client.edit_runs.retrieve("edr_xyz789")
```

#### Java

**`After (2026-02-09)`**

```java title="After (2026-02-09)"
var result = client.editRuns().createAndPoll(EditRunsCreateRequest.builder()
    .file(EditRunsCreateRequestFile.of(FileFromUrl.builder().url("https://...").build()))
    .config(editConfig)
    .build());
// Or create and poll manually
var run = client.editRuns().create(EditRunsCreateRequest.builder()
    .file(EditRunsCreateRequestFile.of(FileFromUrl.builder().url("https://...").build()))
    .config(editConfig)
    .build());
var retrieved = 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.

| Property                       | Old (EditRun)                         | New (EditRun)               | Change                                                              |
| ------------------------------ | ------------------------------------- | --------------------------- | ------------------------------------------------------------------- |
| `object`                       | Required `"edit_run"`                 | Required `"edit_run"`       | No change                                                           |
| `id`                           | Required `string`                     | Required `string`           | No change                                                           |
| `fileId`                       | Required `string`                     | —                           | Removed, see `file`                                                 |
| `file`                         | —                                     | Required `FileSummary`      | New (replaces `fileId`)                                             |
| `status`                       | Required (ref to EditRunStatus)       | Required `RunStatus` enum   | Now inline enum                                                     |
| `failureReason`                | Optional `string`                     | Required `string \| null`   | Now required but nullable (null unless `FAILED`)                    |
| `config`                       | Required `object` (inline)            | Required `EditConfig`       | Now uses named schema                                               |
| `editedFile`                   | Optional `object` (top-level)         | —                           | Moved to `output.editedFile`                                        |
| `editedFile.fileId`            | Optional `string`                     | —                           | Renamed to `output.editedFile.id`                                   |
| `editedFile.downloadUrl`       | Optional `string`                     | —                           | Renamed to `output.editedFile.presignedUrl`                         |
| `output`                       | Optional `object` (field values only) | Required `object \| null`   | Restructured, now required but nullable (null when not `PROCESSED`) |
| `output.editedFile`            | —                                     | Required `object`           | New (moved from top-level)                                          |
| `output.filledValues`          | —                                     | Required `object`           | New (renamed from `output`)                                         |
| `metrics`                      | Required `object`                     | Required `object \| null`   | Now required but nullable (null when not `PROCESSED`)               |
| `metrics.fieldsDetectedCount`  | —                                     | Required `integer`          | New                                                                 |
| `metrics.fieldsAnnotatedCount` | —                                     | Required `integer`          | New                                                                 |
| `usage`                        | Optional `object`                     | Required `RunUsage \| null` | Now required but nullable                                           |

### EditRun Response Example

```typescript
// Before (2025-04-21)
{
  "success": true,
  "editRun": {
    "object": "edit_run",
    "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
    "fileId": "file_Zk9mNP12Qw4yTv8BdR3H",
    "editedFile": {
      "fileId": "file_Ab3cDE45Fg6hIj7KlM8nO",
      "downloadUrl": "https://extend-files.s3.amazonaws.com/..."
    },
    "status": "PROCESSED",
    "failureReason": null,
    "config": {
      "schema": {
        "type": "object",
        "properties": {
          "fullName": { "type": ["string", "null"], "extend_edit:field_type": "text" }
        }
      },
      "instructions": "Fill form with provided data",
      "advancedOptions": {
        "flattenPdf": true,
        "tableParsingEnabled": false
      }
    },
    "output": {
      "fullName": "John Doe"
    },
    "metrics": {
      "processingTimeMs": 1234,
      "fieldCount": 10,
      "pageCount": 2,
      "fieldFillingTimeMs": 300,
      "fieldDetectionTimeMs": 500,
      "fieldAnnotationTimeMs": 200
    },
    "usage": {
      "credits": 5.0
    }
  }
}

// After (2026-02-09) - all fields present, nullable fields use null when not applicable
{
  "object": "edit_run",
  "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
  "file": {
    "object": "file",
    "id": "file_Zk9mNP12Qw4yTv8BdR3H",
    "name": "application-form.pdf",
    "type": "PDF",
    "parentFileId": null,
    "metadata": {},
    "createdAt": "2025-05-12T21:22:37.318Z",
    "updatedAt": "2025-05-12T21:22:37.324Z"
  },
  "status": "PROCESSED",
  "failureReason": null,
  "config": {
    "schema": {
      "type": "object",
      "properties": {
        "fullName": { "type": ["string", "null"], "extend_edit:field_type": "text" }
      }
    },
    "instructions": "Fill form with provided data",
    "advancedOptions": {
      "tableParsingEnabled": false,
      "flattenPdf": true
    }
  },
  "output": {
    "editedFile": {
      "id": "file_Ab3cDE45Fg6hIj7KlM8nO",
      "presignedUrl": "https://extend-files.s3.amazonaws.com/..."
    },
    "filledValues": {
      "fullName": "John Doe"
    }
  },
  "metrics": {
    "processingTimeMs": 1234,
    "pageCount": 2,
    "fieldCount": 10,
    "fieldsDetectedCount": 8,
    "fieldsAnnotatedCount": 10,
    "fieldDetectionTimeMs": 500,
    "fieldAnnotationTimeMs": 200,
    "fieldFillingTimeMs": 300
  },
  "usage": {
    "credits": 5.0
  }
}
```

---

## EditConfig Schema

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

| Property                              | Old (inline config)           | New (EditConfig)              | Change                            |
| ------------------------------------- | ----------------------------- | ----------------------------- | --------------------------------- |
| `schema`                              | Optional `EditRootJSONSchema` | Optional `EditRootJSONSchema` | No change                         |
| `instructions`                        | Optional `string`             | Optional `string`             | No change                         |
| `advancedOptions`                     | Optional `object`             | Optional `object`             | New field added                   |
| `advancedOptions.flattenPdf`          | Optional `boolean`            | Optional `boolean`            | Default now documented as `true`  |
| `advancedOptions.tableParsingEnabled` | Optional `boolean`            | Optional `boolean`            | Default now documented as `false` |

---

## File Input Changes

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

| Old Property    | New Property | Change  |
| --------------- | ------------ | ------- |
| `file.fileUrl`  | `file.url`   | Renamed |
| `file.fileId`   | `file.id`    | Renamed |
| `file.fileName` | `file.name`  | Renamed |

The top-level `templateId` field — which references a saved [edit template](/api-reference/endpoints/edit/get-edit-template) in place of `file` — is the same in both versions. Exactly one of `file` or `templateId` must be provided.

### Request Example

```typescript
// Before (2025-04-21) - Using URL
{
  "file": {
    "fileUrl": "https://example.com/form.pdf",
    "fileName": "application-form.pdf"
  },
  "config": {
    "schema": { ... },
    "instructions": "Fill with provided data"
  }
}

// After (2026-02-09) - Using URL
{
  "file": {
    "url": "https://example.com/form.pdf",
    "name": "application-form.pdf"
  },
  "config": {
    "schema": { ... },
    "instructions": "Fill with provided data"
  }
}

// Before (2025-04-21) - Using File ID
{
  "file": {
    "fileId": "file_xK9mLPqRtN3vS8wF5hB2cQ"
  },
  "config": { ... }
}

// After (2026-02-09) - Using File ID
{
  "file": {
    "id": "file_xK9mLPqRtN3vS8wF5hB2cQ"
  },
  "config": { ... }
}
```

---

## 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](/webhooks/configuration). Recommended for production. See [Async Processing](/general/async-processing) for details on polling helpers.

```typescript
// Sync (for testing) — client.edit() returns the completed result
const result = await client.edit({
  file: { url: "https://..." },
  config: { schema: { ... } }
});
console.log(result.output);

// Async with polling (recommended for production)
const result = await client.editRuns.createAndPoll({
  file: { url: "https://..." },
  config: { schema: { ... } }
});
console.log(result.output);
```

### Response Changes

| Old Response                    | New Response      | Change                            |
| ------------------------------- | ----------------- | --------------------------------- |
| `success: true`                 | —                 | Removed                           |
| Returns `EditRun` (sync)        | Returns `EditRun` | Always async, poll for results    |
| Returns `EditRunStatus` (async) | Returns `EditRun` | Now 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 Response                        | New Response       | Change              |
| ----------------------------------- | ------------------ | ------------------- |
| `success: true`                     | —                  | Removed             |
| `warning`                           | —                  | Removed             |
| `editRun: EditRunStatus \| EditRun` | `editRun: EditRun` | Always full EditRun |

### Response Example

```typescript
// Before (2025-04-21) - In progress (returned EditRunStatus)
{
  "success": true,
  "editRun": {
    "object": "edit_run_status",
    "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
    "status": "PROCESSING"
  }
}

// Before (2025-04-21) - Complete (returned EditRun)
{
  "success": true,
  "editRun": {
    "object": "edit_run",
    "id": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
    "fileId": "file_Zk9mNP12Qw4yTv8BdR3H",
    "editedFile": { ... },
    "status": "PROCESSED",
    "config": { ... },
    "output": { ... },
    "metrics": { ... },
    "usage": { ... }
  }
}

// After (2026-02-09) - In progress (all fields present, nullable fields are null)
{
  "object": "edit_run",
  "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
  "file": {
    "object": "file",
    "id": "file_Zk9mNP12Qw4yTv8BdR3H",
    "name": "form.pdf",
    ...
  },
  "status": "PROCESSING",
  "failureReason": null,
  "config": { ... },
  "output": null,
  "metrics": null,
  "usage": null
}

// After (2026-02-09) - Complete
{
  "object": "edit_run",
  "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
  "file": { ... },
  "status": "PROCESSED",
  "failureReason": null,
  "config": { ... },
  "output": {
    "editedFile": {
      "id": "file_Ab3cDE45Fg6hIj7KlM8nO",
      "presignedUrl": "https://..."
    },
    "filledValues": { ... }
  },
  "metrics": { ... },
  "usage": { ... }
}
```

---

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

### Response Changes

| Old Property    | New Property | Change  |
| --------------- | ------------ | ------- |
| `success: true` | —            | Removed |
| `editRunId`     | `id`         | Renamed |
| `message`       | —            | Removed |

### Response Example

```typescript
// Before (2025-04-21)
{
  "success": true,
  "editRunId": "edit_run_xK9mLPqRtN3vS8wF5hB2cQ",
  "message": "Edit run data has been successfully deleted."
}

// After (2026-02-09)
{
  "id": "edr_xK9mLPqRtN3vS8wF5hB2cQ"
}
```

---

## Output Structure Changes

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

| Old Location                     | New Location                             | Change                          |
| -------------------------------- | ---------------------------------------- | ------------------------------- |
| `editRun.editedFile`             | `editRun.output.editedFile`              | Moved to nested `output` object |
| `editRun.editedFile.fileId`      | `editRun.output.editedFile.id`           | Renamed                         |
| `editRun.editedFile.downloadUrl` | `editRun.output.editedFile.presignedUrl` | Renamed                         |
| `editRun.output` (field values)  | `editRun.output.filledValues`            | Renamed and moved               |

### Migration Example

```typescript
// Before (2025-04-21)
const editedFileUrl = editRun.editedFile?.downloadUrl;
const editedFileId = editRun.editedFile?.fileId;
const filledValues = editRun.output;

// After (2026-02-09)
const editedFileUrl = editRun.output?.editedFile?.presignedUrl;
const editedFileId = editRun.output?.editedFile?.id;
const filledValues = editRun.output?.filledValues;
```

---

## Failure Reasons

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

| Failure Reason             | Description                                                           |
| -------------------------- | --------------------------------------------------------------------- |
| `UNABLE_TO_DOWNLOAD_FILE`  | Failed to load the requested file                                     |
| `FILE_TYPE_NOT_SUPPORTED`  | File type not supported (PDF required)                                |
| `FILE_SIZE_TOO_LARGE`      | File exceeds maximum allowed size                                     |
| `CORRUPT_FILE`             | File appears corrupted                                                |
| `FIELD_DETECTION_ERROR`    | Error during field detection (new)                                    |
| `PASSWORD_PROTECTED_FILE`  | File is password protected                                            |
| `FAILED_TO_CONVERT_TO_PDF` | Could not convert to PDF                                              |
| `INTERNAL_ERROR`           | Unexpected internal error                                             |
| `INVALID_OPTIONS`          | Invalid configuration options (renamed from `INVALID_CONFIG_OPTIONS`) |
| `EMPTY_SCHEMA`             | No schema provided and no fields detected (new)                       |
| `OUT_OF_CREDITS`           | Insufficient credits (new)                                            |
| `SCHEMA_VALIDATION_ERROR`  | Generated output failed validation against the edit schema            |

---

## SDK Method Reference

| Old SDK Method              | New 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](mailto:support@extend.app).

---

## Migration Guides

| Guide                            | Migrating From           | Migrating To                            |
| -------------------------------- | ------------------------ | --------------------------------------- |
| [Overview](./overview)           | —                        | What's new and how to upgrade           |
| [Extract Runs](./extract)        | `/processor_runs`        | `/extract_runs` + `/extract`            |
| [Classify Runs](./classify)      | `/processor_runs`        | `/classify_runs` + `/classify`          |
| [Split Runs](./split)            | `/processor_runs`        | `/split_runs` + `/split`                |
| [Parse Runs](./parse)            | `/parse`, `/parse/async` | `/parse_runs` + `/parse`                |
| [Edit Runs](./edit)              | `/edit`, `/edit/async`   | `/edit_runs` + `/edit`                  |
| [Extractors](./extractors)       | `/processors`            | `/extractors`                           |
| [Classifiers](./classifiers)     | `/processors`            | `/classifiers`                          |
| [Splitters](./splitters)         | `/processors`            | `/splitters`                            |
| [Files](./files)                 | `/files`                 | `/files` (breaking changes)             |
| [Evaluation Sets](./evaluation)  | evaluation endpoints     | Updated evaluation endpoints            |
| [Workflow Runs](./workflow-runs) | `/workflow_runs`         | `/workflow_runs` (breaking changes)     |
| [Webhooks](./webhooks)           | `processor_run.*` events | `extract_run.*`, `classify_run.*`, etc. |