Detect Form

Detect Form detects the fields in a PDF form and returns a form_detection_run whose output.schema you can pass straight to /edit or /edit_runs. The returned schema has field positions annotated, so you don’t have to write extend_edit:bbox coordinates by hand. Optionally, supply your own schema and Extend maps it onto the detected fields. Set advancedOptions.conditionalGenerationEnabled to true to also generate JSON Schema validation rules from requirements stated in the form.

Reach for it when you:

  • Need a starter schema for a new PDF form.
  • Want to map an existing schema onto a vendor-specific layout.
  • Need annotated field locations before running edits at scale.
  • Want Extend to generate conditional form validation rules from the form’s content.

Use POST /detect_form for synchronous testing. For production workloads, use POST /form_detection_runs and poll GET /form_detection_runs/{id} to avoid request timeout issues.

Quick start

We’ll detect the fields in a PDF form. 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"
1from extend_ai import Extend
2
3client = Extend()
4
5run = client.detect_form(
6 file={"url": "https://example.com/form.pdf"},
7 config={
8 "instructions": "Detect the form fields and use human-readable field names.",
9 "advancedOptions": {"radioEnumsEnabled": True},
10 },
11)
12
13print(run.output.schema)

Response

The response is a form_detection_run. A successful synchronous request returns after the run reaches PROCESSED; the asynchronous endpoint usually returns it with status: "PROCESSING".

FieldTypeDescription
object"form_detection_run"The resource type.
idstringThe form detection run ID. Use it with GET /form_detection_runs/{id}.
statusstringPROCESSING, PROCESSED, or FAILED.
outputobject | nullPresent when processing succeeds. Contains schema, annotatedSchema, and mappingResult.
output.schemaobjectThe final generated schema after mapping. If no inputSchema was provided, this is the same as output.annotatedSchema. Pass it to /edit or /edit_runs.
output.annotatedSchemaobject | nullThe original schema detected from the file, annotated with field locations.
output.mappingResultobject | nullPresent when you provide an inputSchema. Contains matches, unmatchedInputPaths, and unusedFormFieldKeys.
metricsobject | nullPage, field, and processing-time metrics. Present when processing succeeds.
usageobject | nullCredits consumed by the run when usage data is available.

Asynchronous processing

For production workloads, create a form detection run and poll it by ID:

$curl -X POST https://api.extend.ai/form_detection_runs \
> -H "Authorization: Bearer $EXTEND_API_KEY" \
> -H "x-extend-api-version: 2026-02-09" \
> -H "Content-Type: application/json" \
> -d '{
> "file": { "url": "https://example.com/form.pdf" },
> "config": {
> "instructions": "Detect the form fields and use human-readable field names.",
> "advancedOptions": { "conditionalGenerationEnabled": true }
> }
> }'
$
$curl https://api.extend.ai/form_detection_runs/sgr_xK9mLPqRtN3vS8wF5hB2cQ \
> -H "Authorization: Bearer $EXTEND_API_KEY" \
> -H "x-extend-api-version: 2026-02-09"

Poll until status is PROCESSED or FAILED. See Async Processing for retry and polling guidance.

Request configuration

The config object is shared by the sync and async form detection endpoints:

FieldTypeDescription
inputSchemaobjectAn existing edit schema to map onto the detected form fields. When provided, the response includes a mappingResult.
instructionsstringCustom instructions for field detection and naming.
advancedOptions.tableParsingEnabledbooleanParse table regions as arrays of objects. Defaults to false.
advancedOptions.radioEnumsEnabledbooleanModel radio fields as enums so only one widget in a group is selected. Defaults to false.
advancedOptions.nativeFieldsOnlybooleanOnly use native AcroForm fields from the PDF and skip object detection. Defaults to false.
advancedOptions.conditionalGenerationEnabledbooleanGenerate root-level JSON Schema conditional validation rules from requirements explicitly stated in the form. Defaults to false.

Generate conditional validation rules

When advancedOptions.conditionalGenerationEnabled is true, Extend reads the form content together with the detected field schema and adds validation rules that the form explicitly asks for. For example, a form that says “If Yes, provide an explanation” can produce an if / then rule that requires the explanation field only when the answer is true.

Generated rules are added to output.schema using supported root-level JSON Schema keywords: dependentRequired, if / then / else, allOf, oneOf, anyOf, and not. Extend only generates rules for fields present in the detected schema; it does not infer requirements from layout, proximity, or general knowledge about the form.

To learn how these keywords work, see Conditional schema validation in the JSON Schema documentation.

These conditionals act as validation rules for the form data. When you pass the generated schema to /edit or /edit_runs, Extend checks generated field values against the rules and can retry generated values that do not satisfy them. If the values still fail validation, the Edit run fails with SCHEMA_VALIDATION_ERROR—in the HTTP error body’s code for /edit, or in the run’s failureReason for /edit_runs. They do not add interactive UI behavior such as showing or hiding fields in a browser.

Conditional generation is model-based. Review the generated rules before using the schema in production, especially for high-stakes forms.

A common workflow

The generated schema uses the same format as edit runs, including support for root-level JSON Schema conditionals. A common workflow is:

  1. Generate a schema from the PDF form with conditionalGenerationEnabled: true.
  2. Review and, if needed, refine the generated validation rules.
  3. Use the schema with /edit or /edit_runs.

For the exact request and response schemas, see Detect Form (Sync), Detect Form (Async), and Get Form Detection Run.