DEV Community

Cover image for What Extract Form Data Gives You Isn't What Fill a PDF Form Wants Back
PDF4me
PDF4me

Posted on

What Extract Form Data Gives You Isn't What Fill a PDF Form Wants Back

A form has three moments in its life on PDF4me: someone builds the fillable fields, someone (or something) fills them, and someone reads the filled values back out. Fill a PDF Form and Extract Form Data from PDF sit on either side of that middle step, and PDF4me's own documentation calls them companions. The Fill endpoint's own docs page lists Extract as a "Related action" and describes it as the way to "pull the field names and current values out of any AcroForm PDF before designing your dataArray payload." The n8n integration goes further and calls Fill "the reverse operation" of Extract. That is the right mental model for what these two endpoints do. It is not a reliable guide to what they return, because on every platform PDF4me exposes this pair through, the shape Extract hands back is not the shape Fill expects to receive. Round-tripping one into the other means writing a translation step yourself, every time.

REST: a flat string in, a typed array out

On the REST API, Fill a PDF Form (POST /api/v2/FillPdfForm) takes a dataArray field that has to be a stringified JSON object, not a nested object, with keys that match the target PDF's AcroForm field names exactly: "dataArray": "{\"firstname\": \"John\", \"lastname\": \"Doe\"}". Send a real JSON object instead of a string and the API returns a deserialization error. Extract Form Data from PDF (POST /api/v2/ExtractPdfFormData), by contrast, returns a formFields array, one object per field, each with fieldName, fieldValue, and fieldType as separate keys. Take that array straight out of Extract's response and post it back into Fill's dataArray and it will not work. Fill wants one flat object of name-to-value pairs. Extract gives you an array of three-key objects. Getting from one to the other means a short loop that drops fieldType and collapses the array into a single object, not a direct pass-through.

There is a second wrinkle worth flagging on this same pair, and it sits inside PDF4me's own documentation rather than between platforms. The REST docs page for Fill a PDF Form lists dataArray as the required field for supplying values. The Fill PDF Form entry in the interactive API Tester lists both dataArray and InputFormData, an array of {fieldName, fieldValue} objects, as required, and its own sample request sends both fields populated with the same data at once. The two pages describing the identical endpoint do not agree on what a caller has to send. Worth testing directly before assuming either page alone: the Extract Form Data from PDF tester is the fastest way to see the real output shape on a sample file before writing a single line of Fill code against it.

import requests, base64, json

# 1. Extract Form Data returns an array of typed field objects
extract_resp = requests.post(
    "https://api.pdf4me.com/api/v2/ExtractPdfFormData",
    headers={"Authorization": "Basic YOUR_API_KEY"},
    json={"docName": "filled.pdf", "docContent": base64.b64encode(open("filled.pdf", "rb").read()).decode()}
).json()

# formFields: [{"fieldName": "firstname", "fieldValue": "John", "fieldType": "text"}, ...]

# 2. Fill a PDF Form wants one flat object, stringified, no fieldType
reshaped = {f["fieldName"]: f["fieldValue"] for f in extract_resp["formFields"]}

fill_payload = {
    "templateDocName": "blank_template.pdf",
    "templateDocContent": base64.b64encode(open("blank_template.pdf", "rb").read()).decode(),
    "dataArray": json.dumps(reshaped),
    "inputDataType": "json",
    "outputType": "pdf",
    "IsAsync": False
}
Enter fullscreen mode Exit fullscreen mode

Make: two ways in, one array out

Fill a PDF Form in Make offers a choice most other platforms do not: Map fields, a repeatable list of Field Name / Field Value rows built by hand in the scenario editor, or Json, a single payload for when the data already arrives as an object from a database or API call. Extract PDF Form Data in Make returns one output field, Form Fields, described as "every extracted field name and its filled values as key-value pairs." Make's own documentation adds a detail that matters more in practice than the shape question: field names "come from whatever the PDF creator named them, often technical IDs like field_001 rather than readable labels," and recommends testing with a sample PDF before building any downstream logic around them. So even once the shape is reconciled, the field names themselves may need a lookup table before they mean anything to a human reading the scenario.

Zapier: typed conventions in, a string pair out

Fill a PDF Form in Zapier takes a single Input Data field, a JSON string, but the value conventions inside it change by field type: {"fieldName":"value"} for text, {"checkbox":true} for a checkbox, {"radio":"option2"} for a radio button, {"list":"Option 2, Option 5"} for a multi-select. Extract Form Data from PDF in Zapier does not hand back typed values at all. It returns two separate string outputs, Form Data and Form Data JSON, neither of which is documented as preserving the checkbox-as-boolean or radio-as-string conventions Fill expects on the way back in. A Zap that reads a filled form and tries to refill a second copy of the same template needs to parse Form Data JSON and rebuild the type-specific values Fill's own docs describe, not just forward the extracted string.

Power Automate: bulk-capable in, thinly documented out

Fill a PDF Form in Power Automate has a capability none of the other four surfaces advertise on their Fill page: its Data string field accepts either a single JSON object, for one filled document, or a JSON array of objects, for generating multiple filled documents from one flow run. Extract Form Data from PDF in Power Automate, on the other hand, has the thinnest documented output of any surface checked here. Its own parameter table lists exactly one output field, Trace ID, a tracking identifier, with no row for the extracted field data itself. The linked workflow example on that same page shows a flow reading a formData JSON output further downstream, so the data clearly comes back, it just is not represented in the page's own Output table the way it is on REST, Make, Zapier, or n8n. Anyone wiring this up in Power Automate should expect to find the real output field by running the action once and inspecting the raw response, not by trusting the table.

n8n: three input modes in, a nested object out

Fill a PDF Form in n8n supports the richest input surface of the five: a stringified JSON object (matching REST's dataArray convention under the hood), a JSON file passed as binary data, a base64-encoded JSON blob, or manually entered Field Name / Field Value rows for small, fixed field sets. Its own documentation is blunt about the one rule that holds across every mode: "Form Data (JSON) expects one object, not a list. Send a single JSON object. An array with one object is unwrapped; multiple objects are rejected." Extract Form Data from PDF in n8n returns a nested formData object, {"formData": {"name": "PDF4me", "email": "", "country": "USA"}}, and flags two behaviors worth knowing before building on it: an unfilled field comes back as an empty string rather than being left out of the object entirely, and a checkbox returns whatever export value the form's original designer assigned it, not a guaranteed true or false. n8n's own page for Extract even lays out a small decision table distinguishing this node from plain text extraction and from AI-based parsing, useful context for picking the right node before assuming this one applies to a scanned or flattened document, which it explicitly does not read.

The one thing that actually does carry across every platform

Field names are the connective tissue, and they are the one part of this pair that behaves consistently everywhere: whatever name a field was given when the AcroForm structure was built is the exact, case-sensitive string every platform's Fill action needs on the way in, and the exact string every platform's Extract action hands back on the way out. Every platform's own documentation says some version of "run Extract first, or inspect the template in Acrobat, to get the real field names" before attempting a Fill call blind. That is good advice, and it is also an implicit admission that the shape mismatch above is expected, not a bug: these are two operations that talk about the same fields using different data shapes, on every single surface, and the fix is always the same small piece of glue code, not a platform-specific workaround.

Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com

Top comments (0)