X Enterprises
fastify-xpdf

fillForm

Fill PDF form fields (text, checkbox, radio, dropdown) using pdf-lib and optionally flatten the result.

fillForm

Fill PDF form fields using pdf-lib. Accepts a PDF buffer with embedded form fields and a key-value map of field names to values. Supports text, checkbox, radio, and dropdown fields. Optionally flattens the form (removes editability) after filling.

Signature

fastify.xPDF.fillForm(
  pdfBuffer: Buffer,
  fieldValues: Record<string, string | boolean>,
  options?: FormOptions,
): Promise<PdfResult>

interface FormOptions {
  flatten?: boolean       // flatten after filling (default: true)
  filename?: string
  saveToStorage?: boolean
  folder?: string
}

interface PdfResult {
  buffer: Buffer
  filename: string
  size: number
  storageKey?: string
  url?: string
}

Params

NameTypeRequiredDescription
pdfBufferBufferYesSource PDF containing form fields (must start with %PDF header)
fieldValuesobjectYes{ fieldName: value } — strings for text/dropdown/radio, booleans for checkboxes
options.flattenbooleanNoFlatten form after filling — makes fields non-editable (default: true)
options.filenamestringNoOutput filename
options.saveToStoragebooleanNoUpload result to xStorage
options.folderstringNoStorage folder override

Returns

PdfResult: { buffer, filename, size, storageKey?, url? }.

Throws

ErrorWhen
[xPDF] Invalid PDF bufferpdfBuffer doesn't start with %PDF
[xPDF] fieldValues must be an objectfieldValues is not a plain object

Examples

Fill an employment application form

fastify.post("/applications/:id/form", async (request, reply) => {
  const application = await fastify.prisma.application.findUnique({
    where: { id: request.params.id },
    include: { applicant: true },
  });

  const templateBuffer = await fetchTemplateBuffer("employment-application.pdf");

  const { buffer, filename } = await fastify.xPDF.fillForm(
    templateBuffer,
    {
      firstName: application.applicant.firstName,
      lastName: application.applicant.lastName,
      email: application.applicant.email,
      position: application.position,
      startDate: application.startDate,
      fullTime: application.employmentType === "full-time",
      agreeToTerms: true,
    },
    { flatten: true, filename: `application-${application.id}.pdf` },
  );

  return reply
    .header("Content-Type", "application/pdf")
    .header("Content-Disposition", `attachment; filename="${filename}"`)
    .send(buffer);
});

Fill without flattening (keep form editable)

// Generate a pre-filled but still-editable draft for review
const { buffer } = await fastify.xPDF.fillForm(
  templateBuffer,
  { companyName: "Acme Corp", contractDate: "2025-03-01" },
  { flatten: false },
);

See Also

AI Context

package: "@xenterprises/fastify-xpdf"
method: fastify.xPDF.fillForm(pdfBuffer, fieldValues, options?)
use-when: Fill PDF form fields using pdf-lib — optionally flatten the form to prevent further editing
params: pdfBuffer (Buffer), fieldValues ({ fieldName: value }), options ({ flatten: boolean })
returns: { buffer, size }
Copyright © 2026