Editing Overview

Editing fills PDF form fields programmatically and returns a completed document. You give it a PDF and either natural-language instructions or a schema describing the fields and values, and Extend detects the form’s fields, fills them, and returns a downloadable PDF along with the values it wrote. Use it to auto-fill applications, pre-populate documents with customer data, and generate filled forms at scale.

Quick start

We’ll fill a blank IRS Form 1040 from natural-language instructions. For this quick-start we’ve uploaded the file here.

First page of IRS Form 1040

Grab a key from the Developers page and store it as the EXTEND_API_KEY environment variable. If you’re using an SDK, see the installation instructions.

export EXTEND_API_KEY="your_api_key_here"

The /edit endpoint takes a file and a config with instructions (or a schema).

from extend_ai import Extend
client = Extend()
result = client.edit(
file={
"url": "https://extend-public-files.s3.us-east-2.amazonaws.com/f1040.pdf",
},
config={
"engineVersion": "1.0.0",
"instructions": (
"Fill the taxpayer's first name as Jordan and last name as Avery. "
"Set the Single filing status. Leave all other fields blank."
),
"advancedOptions": {"flattenPdf": True},
},
)
print(result)

Want to edit your own document? Upload it first, then pass the returned file id instead of a url (reusing the same config).

with open("f1040.pdf", "rb") as f:
uploaded = client.files.upload(file=f)
result = client.edit(file={"id": uploaded.id}, config=config)

Example response

After you run the code snippet above, you’ll see a response like this. Extend detects the form’s fields, fills the ones your instructions describe, and returns an output with the completed PDF in editedFile and the written values in filledValues.

{
"object": "edit_run",
"id": "edr_xK9mLPqRtN3vS8wF5hB2cQ",
"status": "PROCESSED",
"output": {
"editedFile": {
"id": "file_Ab3cDE45Fg6hIj7KlM8nO",
"presignedUrl": "https://extend-files.s3.amazonaws.com/..."
},
"filledValues": {
"Your first name and middle initial": "Jordan",
"Last name": "Avery",
"filing_status_single": true
}
},
"metrics": { "processingTimeMs": 1234, "pageCount": 2, "fieldCount": 3 },
"usage": { "credits": 1 }
}

Key fields

FieldWhat it contains
output.editedFile.idThe Extend file id of the completed PDF, reusable as input to other endpoints.
output.editedFile.presignedUrlA download URL for the completed PDF. Expires after 15 minutes.
output.filledValuesThe values written into the form, keyed by schema property name.
statusPROCESSING, PROCESSED, or FAILED.

For full request/response details, see the Create Edit Run API reference.

Use the output

Read the download link off output.editedFile, and inspect output.filledValues to see what was written.

edited = result.output.edited_file
print("Download:", edited.presigned_url) # expires after 15 minutes
for field, value in (result.output.filled_values or {}).items():
print(f"{field}: {value}")

For the full response shape and status values, see Response Format.

Sync vs async

The example above calls the synchronous /edit endpoint. We also have an asynchronous /edit_runs endpoint that should be used for large files and high volume use cases.

See Async Processing for the full comparison, polling options, and webhook setup.

Reuse a saved template

If you’ve saved an edit template — a source file paired with a default config — you can pass its ID as templateId in place of file:

{ "templateId": "edt_xK9mLPqRtN3vS8wF5hB2cQ" }

Extend runs the edit against the template’s saved file, using the template’s saved schema, instructions, engine version, and advanced options as defaults. Any config values you also include in the request take precedence over the template’s saved values, so you can override just what’s different for a given run:

{
"templateId": "edt_xK9mLPqRtN3vS8wF5hB2cQ",
"config": { "instructions": "Use today's date for the signature date field." }
}

Exactly one of file or templateId must be provided — a request either supplies a file directly or references a template, not both. If the template ID doesn’t exist the request fails with a 404; if it belongs to another workspace or organization it fails with a 403.

Configuration

The quick start sends file and config.instructions. To control how the form is filled, pass more options inside config. Here are the most commonly used ones; for the full reference, see Configuration.

Instructions

Natural-language guidance describing the values to fill and any special handling. The fastest way to start — Extend detects the form’s fields and fills the ones you describe.

{ "config": { "instructions": "Fill the applicant's name and today's date. Leave optional fields blank." } }

Schema

A JSON Schema that pins each field’s PDF type, value, and position using extend_edit:* keywords. Use it for exact, repeatable control over what gets filled and where.

{
"config": {
"schema": {
"type": "object",
"properties": {
"applicant_name": {
"type": ["string", "null"],
"extend_edit:field_type": "text",
"extend_edit:value": "Jane Smith"
}
}
}
}
}

Full schema reference →

Flatten the PDF

Flatten the document after editing so the filled fields become non-editable. Use it when generating final documents.

{ "config": { "advancedOptions": { "flattenPdf": true } } }

Don’t have a schema yet? Detect Form detects a form’s fields and returns a starter schema with positions annotated. For every config option, see the Configuration reference.


Tutorial video

Next steps