Fill a PDF Form in n8n with FormRail

In n8n, a downloaded PDF lives in binary data, while FormRail expects a JSON request containing base64 PDF bytes. Getting that boundary right is most of this example.

Here's a workflow you can import, run manually and inspect before connecting your own template.

Import the example

Download the sample workflow from the FormRail docs and import its JSON into n8n. It starts with a manual trigger, downloads a sample PDF, builds the request in a Code node, and fills the file through an HTTP Request node.

The workflow is inactive when imported. It doesn't contain credentials and doesn't send anything to an email address. Create a FormRail API key and store it in an n8n Header Auth credential:

  • Name: Authorization
  • Value: Bearer YOUR_FORMRAIL_KEY

Select that credential on the fill request. Keep the actual key in the credential store, rather than pasting it into the workflow JSON.

Read the PDF's binary bytes

The download node uses Response Format: File, with the binary property named data. In the Code node, read that property with n8n's binary helper:

const pdf = await this.helpers.getBinaryDataBuffer(0, 'data');

return [{
  json: {
    pdf: pdf.toString('base64'),
    data: {
      ProjectName: 'September installation',
      Reference: 'JOB-1042',
      Service: 'Installation',
      Ready: true,
    },
    flatten: true,
  },
}];

This is the helper documented by n8n. Reading the buffer matters because n8n can store binary files separately from the execution JSON. A storage reference isn't the file's base64 content.

The sample processes one PDF. For a workflow with several items, process each item deliberately and give each intended output its own idempotency key. Don't assume the first item represents every file.

Configure the fill request

In the HTTP Request node, use:

  • Method: POST
  • URL: https://formrail.voltenworks.com/v1/fill
  • Authentication: Generic Credential Type, then Header Auth
  • Send Body: enabled, JSON, using the expression {{ $json }}
  • Header Idempotency-Key: formrail-{{ $execution.id }} for this single-file example
  • Response Format: File

Only the PDF bytes are base64. The request itself is JSON, with pdf, data and flatten properties. Don't turn the whole request into a binary attachment.

Run the workflow manually. The last node should return a binary PDF. Download it and check the visible project name, service selection and checkbox. Once that works, connect the binary output to your own storage step.

Replace the sample template

Download your own form from Drive or another source, then inspect it in the FormRail workspace. The PDF needs existing AcroForm fields. Printed text and scans don't become fillable just because they're inside a PDF.

Use the exact field names from inspection. Choice fields accept their listed values, and checkboxes take booleans. Test the data against /v1/validate before sending it to /v1/fill. A validation response can have HTTP 200 and valid: false, so check the flag and the returned issues.

For an existing system with different property names, export a JSON mapping and keep its templateHash with the template. FormRail checks that fingerprint before applying the mapping to a document.

Keep retries attached to the same job

The execution ID is convenient for a manual demonstration. In a production workflow, a whole new execution may have a new ID even when you're retrying the same business job.

Use a stable reference such as your own request ID plus a revision number. Persist it with the input so the PDF bytes, data and key remain the same on retry. FormRail will regenerate a completed request without spending another credit. Changed data needs a new key. A confirmed failed request also keeps its stored error: correct the problem and use a new key. Reuse the original key when the outcome is still unknown, such as a lost response.

The free account includes 25 fills. Inspecting and validating use no credits, within the request limits. Files are limited to 2 MiB, 50 pages and 200 fields. Unsupported templates or values produce errors you can handle before passing a document to the next step.

I'd keep the first run manual until you've reviewed the returned PDF. That's also a useful place to stop when a template changes.

More posts

MeloData Now Has 1.85 Million Tracks Ready
MeloData now includes the full AcousticBrainz archive, about 1.85 million tracks. What changed, which fields are null, and where key comes from on archive rows.
October 1, 2026
How to Handle Missing Audio Features in MeloData
Keep null values separate from zero, check analysis status, and account for source differences before ranking tracks.
September 12, 2026
Detect a Website's Booking and Payment Tools with an API
Use Voltenworks Lookup to inspect public software signals, read their supporting evidence, and handle incomplete results.
September 10, 2026