Most PDFs are dead ends once they leave a template folder. Someone builds a contract, an intake sheet, or an onboarding packet, exports it, and the only way to collect data back is printing it, scanning it, or pasting a wall of instructions above a blank line and hoping the recipient types neatly inside the margins. Turning that static page into something a person can click into and fill out usually means opening the file in a desktop PDF editor and dropping fields by hand, one template at a time.
PDF4me's Add Form Fields to PDF API does that step with a single call: send a PDF, a set of coordinates, and a field definition, and get back the same PDF with an interactive field sitting exactly where you told it to sit. That part works exactly as advertised. What's less consistent is how PDF4me's own docs, sample repo, and internal indexes describe the endpoint that does it, and what field types actually make it into the finished PDF.
The endpoint has three names across three PDF4me-owned sources
The live REST docs page states the route plainly:
Method: POST
Endpoint: /api/v2/AddFormField
That matches exactly what the actual working Python sample in PDF4me's own pdf4me-api-samples repository builds its request URL from. Two other PDF4me-owned references disagree. This project's separate documentation index lists the same endpoint as AddFormFieldToPdf. That same GitHub sample folder's own README.md describes it a third way, as AddFormFieldsToPdf. None of the three spellings match each other, and the working code is the one that actually resolves against the live API.
If you're wiring this up from a cached list of endpoint names rather than the live docs page or the sample script itself, double check the exact route before you ship it.
Nine required parameters, one flag with two different names
Every call needs:
-
docContent, the source PDF, Base64-encoded -
docName, the output file name with a.pdfextension -
initialValue, the text that pre-populates the field -
positionXandpositionY, integer coordinates for where the field sits on the page -
fieldName, the internal name PDF4me assigns the field, which is what any later fill or extraction call will reference -
Size, the field's font and box size -
pages, which page or pages the field applies to, using PDF4me's usual range syntax ("1", "1,3,5", "2-5", "1,3,7-10", "1-") -
formFieldType, the field type itself
One parameter controls sync versus async processing, and it has two names depending which PDF4me source you trust. The docs page's own parameter table calls it async. The actual request payload inside the working Python sample sends isAsync instead, and that's the spelling that gets a real response back from the live API. Here's the sample adapted down to the core call, with the field name it actually uses:
import base64
import requests
api_key = "YOUR_BASE64_ENCODED_API_KEY"
url = "https://api.pdf4me.com/api/v2/AddFormField"
with open("contract.pdf", "rb") as f:
doc_content = base64.b64encode(f.read()).decode("utf-8")
payload = {
"docContent": doc_content,
"docName": "contract.pdf",
"initialValue": "",
"positionX": 300,
"positionY": 300,
"fieldName": "ClientSignatureDate",
"Size": 4,
"pages": "1",
"formFieldType": "TextBox",
"isAsync": False
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Basic {api_key}"
}
response = requests.post(url, headers=headers, json=payload, timeout=30)
if response.status_code == 200:
with open("contract_fillable.pdf", "wb") as f:
f.write(response.content)
A 200 comes back as the finished PDF, straight binary, no Base64 decoding needed. A 202 means the job queued, and the polling URL lives in the response's Location header, the same async pattern PDF4me uses across the rest of its API surface.
The field type list is shorter than it sounds
Here's the finding worth building an actual workflow decision around. PDF4me describes this feature, on the docs site and in the sample repo's own README, as supporting "text boxes, checkboxes, radio buttons, and dropdowns," or more broadly "all standard AcroForm field types." The live REST parameter table lists exactly two accepted values for formFieldType: TextBox and CheckBox. The sample script backs that up in practice. Its request payload only ever sends TextBox, and nothing in the working code exercises a radio button or a dropdown, despite the README listing both as supported.
That's a real, current limit, not a typo waiting to be fixed. If a workflow needs a radio button group, a dropdown, a date picker, or a signature field added programmatically, this specific endpoint isn't the tool for that job today. A row of individually named checkboxes can approximate a "pick one" choice if the consuming application enforces that rule after the fact, but that's an application-layer workaround, not a native substitute.
Worth knowing before promising a five-field intake form with a dropdown for department and a radio group for urgency. The text fields and checkboxes ship in one call each. The rest needs a different plan.
Positioning is exact, not automatic
There's no auto-layout. positionX and positionY are integers you supply directly, and Size controls how large the field renders. That means the coordinate system needs figuring out before the first production call, not after. In practice that's a one-time cost per template: render a test PDF, note where the field lands, adjust, and the coordinates stay stable for every future document built from that same template. pages accepting ranges means one call can target every page of a multi-page document, or a single page specifically, which matters when a signature block belongs on the last page and an initials box belongs on every page before it.
One endpoint in a four-step lifecycle
Adding a field is rarely the whole job. PDF4me splits the rest of the form lifecycle into its own dedicated endpoints rather than one do-everything call.
Once fields exist on a template, Fill a PDF Form populates them from a JSON data object keyed by field name, returning a completed PDF either still editable or flattened depending on how it's called. That's a separate step from creating the fields, which matters for a "generate a blank fillable template once, fill it a thousand times" pipeline.
After someone submits a filled form, Extract Form Data from PDF reads every submitted field's name and value back out as structured JSON, whether a person filled it by hand or another automated process did.
Once a form has served its purpose, Flatten PDF merges the AcroForm fields, annotations, and any signatures into the static page content, so the result can't be edited further, the right last step for any "final" filled document that needs to stop being fillable the moment it's final.
Add, fill, extract, flatten. Four endpoints, four distinct jobs.
Same feature, inconsistent name depending which platform
Working through Make, Zapier, or Power Automate instead of the raw REST API, the equivalent action is titled Add Form Field to PDF in Make, Add Form Field to PDF in Zapier, and Add Form Field to PDF in Power Automate, all three singular. The REST page, the n8n node, and the interactive API Tester all use the plural "Fields." Functionally identical, five different surfaces, a naming split straight down the middle. Worth searching both the singular and plural term before concluding an automation platform doesn't have this action.
Where this fits
This endpoint earns its keep anywhere a business generates the same document shape repeatedly and needs it to arrive interactive instead of flat: HR onboarding packets that need a name and start-date field, contract templates that need an initials box on every page, intake forms where the questions never change but the recipient does. Where the field set is genuinely dynamic per document, or the form needs a field type beyond a text box or checkbox, this is the wrong layer to solve that problem in. Better to know that before the integration code gets written than after a stakeholder asks where the dropdown went.
Try the live API Tester first to see the exact request and response shape before writing a line of integration code.
Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com
Top comments (0)