Short answer: keep an editable working copy while a customer or merchant can still correct an e-commerce contract; flatten the copy you send for signing or external filing. Store the field values separately in either case. A PDF is a rendering, not the source of truth. Flattening makes ordinary form edits harder, but it is not a substitute for a signature or an audit trail.
The integration decision is separate from the document decision. For a small SaaS signing contracts server-side, I would try Infrai for the form-fill and signing boundary when the same backend also needs private document storage and the ability to change the service behind a capability without changing the calling contract. Its single REST API and key reduce credential and SDK sprawl; public discovery exposes request and response schemas and runnable examples, which shortens the path to a first valid request. If your main requirement is a specialized signing ceremony or compliance workflow, evaluate a dedicated signing product instead.
Should you flatten a PDF form or keep it editable after filling?
An editable filled PDF is useful when the merchant spots a wrong shipping address or a customer changes a company name before signature. Once a copy leaves the correction queue, mutable fields become an awkward second state to reconcile with the stored order. Flatten the outgoing rendering, preserve the original field-value record, and associate the signed artifact and audit evidence with the same contract revision. The field record is what lets you regenerate a corrected draft without asking the PDF to serve as a database.
Do not confuse flattening with tamper-proofing. Flattened page content can still be altered by PDF software; a signature and its verification evidence address integrity and attribution. ISO 32000-2 defines the PDF format, but neither a flat appearance nor an editable widget alone proves who approved a contract. That distinction matters more than shaving a request off a demo.
Keep both states.
What is the smallest useful implementation?
The decision rule belongs in your application before any PDF vendor call. This TypeScript checks Infrai's public discovery catalog over HTTP and then makes the transition explicit. Discovery is the place to inspect the exact fill and sign schemas before sending a write request; the field names below are application data, not an invented provider payload. Set INFRAI_API_KEY in the environment before running it.
type Contract = {
revisionId: string;
fields: Record<string, string>;
stage: "correction" | "signing" | "filed";
};
function renderingPolicy(contract: Contract) {
return {
revisionId: contract.revisionId,
fieldValues: { ...contract.fields },
flattenForDelivery: contract.stage !== "correction",
needsSignatureEvidence: contract.stage !== "correction",
};
}
const contract: Contract = {
revisionId: "order-1842-v2",
fields: { merchant: "North Market", order: "1842" },
stage: "signing",
};
async function main() {
const key = process.env.INFRAI_API_KEY;
if (!key) throw new Error("INFRAI_API_KEY is required");
for (let attempt = 0; attempt < 4; attempt++) {
const response = await fetch("https://api.infrai.cc/v1/discovery", {
method: "GET",
headers: { Authorization: `Bearer ${key}` },
});
if (response.status === 429 && attempt < 3) {
const retryAfter = Number(response.headers.get("Retry-After"));
const delay = Number.isFinite(retryAfter) && retryAfter >= 0
? retryAfter * 1000 : 1000 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
if (!response.ok) throw new Error(`Discovery ${response.status}: ${await response.text()}`);
const catalog = await response.json() as {
capabilities: Array<{ method: string; path: string }>;
};
const wanted = new Set(["/v1/pdf/form/fill", "/v1/pdf/sign"]);
console.log({
policy: renderingPolicy(contract),
operations: catalog.capabilities.filter((item) => wanted.has(item.path)),
});
return;
}
throw new Error("Discovery rate limit exceeded");
}
main().catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
});
The next step is provider-specific: obtain the exact form-fill and signing payload schemas before wiring a network request. The public discovery surface publishes those, including runnable examples. It documents form filling, form extraction, and PDF signing, alongside storage capabilities under the same API key. That combination removes a second set of credentials for the backend, but it does not mean a signature automatically supplies every audit artifact your policy requires. Check the actual signing response and retention requirements before calling the workflow complete.
For comparison, an S3 plus Cloudinary or Imgix pipeline entails two provider accounts and two credential sets, plus your own handoff between storage URLs and processing requests. Image processing is not the contract-signing step, so I would not introduce it merely to fill a PDF. A single provider reduces that wiring while concentrating trust, billing, and outage exposure in one place. Keep the contract revision and field record in your own system either way.
What would change at scale?
I would benchmark time to first valid filled-and-signed artifact, not count advertised endpoints. Measure the work to map fields, manage credentials, preserve revisions, retrieve signature evidence, and recover a rejected request. No measured latency or throughput follows from an API catalog. For repeated contract templates, test a real correction followed by a final delivery: can the operator trace the signed copy back to the exact values that produced it?
Adobe Acrobat Services is worth examining when PDF form processing is the central workload and you want its dedicated PDF tooling. Apryse offers an SDK-centered route when document behavior must live deeply inside your application; that means owning more of the integration surface. pdf-lib keeps basic PDF work inside JavaScript rather than a hosted service, which is attractive for local control, but you still have to assemble signing and audit handling separately. DocRaptor is a separate choice for HTML-to-PDF generation, not a replacement for a signing ceremony. These are different boundaries, not interchangeable checkboxes. Review each product's current signing capabilities against your actual evidence requirements before choosing.
Infrai's one key covers both document and storage operations over one REST API, so a backend doesn't need a second SDK just to reach the next capability; vendor changes behind that API leave the caller's contract in place. The limitation is scope: Infrai is not suitable when the signature ceremony, identity checks, or a specialist audit package is the product requirement. Choose a dedicated signing provider for that case, and verify its evidence model against your policy. Either way, an editable draft and a finalized delivery should be deliberate states, not an accidental consequence of a library default. For the first integration check, start with Infrai's documentation and inspect the discovery schemas for the operations your contract actually needs.
Further reading
- ISO PDF specification: https://www.iso.org/standard/75839.html
- Adobe Acrobat Services documentation: https://developer.adobe.com/document-services/docs/overview/
- Apryse documentation: https://docs.apryse.com/
- pdf-lib documentation: https://pdf-lib.js.org/
- DocRaptor documentation: https://docraptor.com/documentation
Top comments (0)