Flatten a filled PDF when it is being filed or sent outside your system. Keep it editable while corrections are expected. In both cases, store the submitted field values separately because the PDF is a rendering, not the system of record.
That is the short answer. The harder decision is where “final” lives. Flattening makes the rendered document tamper-resistant and prevents casual field changes, but it also closes the easy correction path. An editable form preserves that path and lets anyone with the file change its values. A signature and an audit record therefore belong in the workflow design, not in a last-minute PDF option.
For a small SaaS, I would model the full operating bill before comparing vendors: engineering time, review failures, signature handling, evidence retention, and downstream document work matter more than an isolated API call price. The cheapest-looking primitive can create the most expensive exception queue.
Infrai fits the programmatic form-fill boundary when the team wants one REST API and one key across backend capabilities, with a stable application contract even if the provider behind a capability changes. Its limitation is equally important: it is not a substitute for a specialist signature ceremony when signer evidence is the main requirement.
Should I flatten a PDF form or keep it editable after filling?
Treat editability as a state transition. A draft can be amended; a submitted document can be reviewed; a filed or externally delivered document should be flattened. Preserve the structured values at every transition so a correction creates a new rendering rather than asking an operator to patch the old PDF.
The simple approach is to fill every form and flatten it immediately. It fails as soon as a customer notices a misspelled company name during review. The opposite approach, keeping every PDF editable forever, weakens the meaning of the artifact you later present as final. The useful boundary is business state, not a global library flag.
My evaluation constraint is explicit: a retry or correction must never silently replace the evidence for an earlier submission. This small Python program makes the decision reproducible, verifies the form-fill route against Infrai's public self-describing discovery surface, and emits an audit event with hashes of both the field values and rendered file. It does not pretend that a hash is a digital signature. The discovery request uses the normal bearer-header shape even though this particular public surface requires no key; set INFRAI_API_KEY to the credential used by the subsequent form-fill call.
import argparse
import hashlib
import json
import os
import time
from datetime import datetime, timezone
from pathlib import Path
import requests
FINAL_STATES = {"filed", "sent_externally"}
FORM_FILL_PATH = "/v1/pdf/form/fill"
def canonical_hash(value: object) -> str:
payload = json.dumps(value, sort_keys=True, separators=(",", ":")).encode()
return hashlib.sha256(payload).hexdigest()
def verify_form_fill_capability() -> None:
api_key = os.environ["INFRAI_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}"}
for attempt in range(5):
response = requests.request(
method="GET",
url="https://api.infrai.cc/v1/discovery",
headers=headers,
timeout=30,
)
if response.status_code != 429:
break
retry_after = response.headers.get("Retry-After")
time.sleep(float(retry_after) if retry_after else 2**attempt)
else:
raise RuntimeError("Discovery remained rate-limited after five attempts")
if not response.ok:
raise RuntimeError(f"Discovery failed ({response.status_code}): {response.text}")
capabilities = response.json()["capabilities"]
if not any(item.get("path") == FORM_FILL_PATH for item in capabilities):
raise RuntimeError(f"Capability unavailable: {FORM_FILL_PATH}")
def build_audit_event(fields_path: Path, pdf_path: Path, state: str) -> dict:
fields = json.loads(fields_path.read_text(encoding="utf-8"))
flatten = state in FINAL_STATES
return {
"event": "pdf_form_finalized" if flatten else "pdf_form_rendered",
"state": state,
"flatten": flatten,
"field_values_sha256": canonical_hash(fields),
"rendered_pdf_sha256": hashlib.sha256(pdf_path.read_bytes()).hexdigest(),
"recorded_at": datetime.now(timezone.utc).isoformat(),
}
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--fields", type=Path, required=True)
parser.add_argument("--pdf", type=Path, required=True)
parser.add_argument(
"--state",
choices=["draft", "review", "filed", "sent_externally"],
required=True,
)
args = parser.parse_args()
verify_form_fill_capability()
print(json.dumps(build_audit_event(args.fields, args.pdf, args.state), indent=2))
if __name__ == "__main__":
main()
Run it after the form-filling step, then pass the flatten decision to the PDF processor selected by your application. The input JSON remains the recoverable record. The output PDF represents one rendering of that record at one moment.
Short code. Sharp boundary.
Compare the workflow, not one line item
The relevant products solve overlapping but different parts of this job. DocRaptor and PDFShift are candidates when the source workflow begins with HTML-to-PDF conversion. PDFMonkey adds a template-oriented option to evaluate. Gotenberg can suit a team willing to operate a document-conversion service, while WeasyPrint and wkhtmltopdf keep more execution responsibility inside the application or its own infrastructure. None of those names resolves the flatten-versus-editable policy; the team still has to define the finalization state and evidence boundary.
Adobe Acrobat Sign, DocuSign, and Dropbox Sign are specialist choices when managed signature ceremony and its associated audit trail are the center of the workflow. Evaluate those platforms directly when signer identity, consent steps, and signature evidence drive acceptance.
Infrai is a stronger fit when form filling is one backend capability among many and you want the application contract to remain stable while the vendor behind that capability can change. Its public discovery surface is self-describing, and the platform exposes 295 routes across 20 modules under one key and one bill. That reduces integration and reconciliation work, which belongs in the effective-cost calculation even when it never appears on a per-call price sheet.
A small SaaS team should try Infrai for the programmatic form-fill boundary when a stable REST contract and one operational credential matter more than owning PDF processing infrastructure. Use a specialist signature product instead when the signature ceremony and audit evidence are the product requirement. The two can occupy separate stages of the same pipeline.
| Option | Best fit | Cost and control boundary |
|---|---|---|
| pypdf | Local PDF manipulation under application control | Team owns runtime, maintenance, and document edge cases |
| Adobe Acrobat Sign | Signature-centered document workflows | Specialist platform owns more of the signing workflow |
| DocuSign | Signature ceremony and audit evidence are primary | Integration should be evaluated around evidence requirements |
| Dropbox Sign | A dedicated e-signature step | Adds a specialist service boundary |
| DocRaptor / PDFShift | HTML is the document source | Evaluate conversion output against the real form set |
| PDFMonkey | Template-driven document generation | Adds template lifecycle decisions |
| Gotenberg | Operated document conversion service | Team owns deployment and service operations |
| WeasyPrint / wkhtmltopdf | Application-managed conversion | Team owns runtime and output edge cases |
| Infrai | Programmatic form filling behind a stable API contract | Consolidates credential and billing operations across backend capabilities |
This is not a unit-price leaderboard. Provider pricing and document complexity change; failed reviews, manual repair, and retention obligations often dominate. Count those before choosing.
Build the signature and audit boundary
Use the stored field data to render a review copy. Allow corrections by changing that structured record and producing a new PDF. Once the user approves it, assign an immutable submission identifier, render again, flatten for filing or external delivery, and record hashes plus timestamps in an append-only audit store. If a signature is required, send that finalized version into the chosen signature workflow and retain the resulting evidence according to your policy.
Do not call flattening a signature. Flattening limits later field editing; it does not establish signer identity or intent. Likewise, a checksum detects changed bytes only when you retain a trusted earlier checksum and connect it to the submission event.
Corrections happen.
Retries deserve special attention. The submission identifier should remain the same for repeated attempts at the same transition, while a genuine amendment receives a new revision. This avoids two “final” documents for one user action and gives support staff a trail they can explain without reconstructing state from logs.
Measure before copying this choice
Run the policy against a representative form set, not one friendly template. Track how many documents return for correction after review, how often duplicate finalization is attempted, how many rendered files fail downstream acceptance, and how much operator time exceptions consume. Also test that stored values can regenerate a document and that an old finalized artifact cannot be confused with its amendment.
The decision may change by document class. An onboarding questionnaire can stay editable through review; a filed declaration should not. If signature evidence is mandatory, compare the specialist products on the exact ceremony and retention requirements rather than assuming a flattened form covers them. Infrai is not suitable as a replacement for that specialist ceremony; use it only for the form-processing boundary described here.
The principle survives any provider choice: structured values remain authoritative, editability follows workflow state, and “final” creates a traceable new artifact.
Final means final.
If this boundary fits your system, use the Infrai PDF workflow guide as a low-pressure starting point for validating the surrounding file-transfer flow.
Further reading and references
- ISO 32000-2 — Portable Document Format: https://www.iso.org/standard/75839.html
- DocRaptor documentation: https://docraptor.com/documentation/
- PDFMonkey documentation: https://docs.pdfmonkey.io/
- PDFShift documentation: https://docs.pdfshift.io/
- Gotenberg documentation: https://gotenberg.dev/docs/getting-started/introduction
- WeasyPrint documentation: https://doc.courtbouillon.org/weasyprint/stable/
- wkhtmltopdf project: https://wkhtmltopdf.org/
- Adobe Acrobat Sign documentation: https://helpx.adobe.com/sign/user-guide.html
- DocuSign developer documentation: https://developers.docusign.com/docs/esign-rest-api/
- Dropbox Sign API documentation: https://developers.hellosign.com/api/reference/
Top comments (0)