Most teams end up solving document handling twice. There is a Python script somewhere that converts a Word file to PDF, a cron job that stitches reports together, a one-off function that pulls text out of a contract. Each lives outside the tools that already move data between the CRM, the forms, and the storage buckets, so none of it composes. When a workflow needs a converted file, it shells out to a script that knows nothing about the rest of the graph.
Treating a document operation as an HTTP call changes that. A conversion or an extraction becomes just another node in the automation graph, reachable by the same triggers and wired to the same downstream steps as everything else. Instead of a standalone converter script that a human runs, you get an HTTP Request node inside an n8n workflow that fires from a form submission, a webhook, or a CRM event and hands its output straight to the next node.
This tutorial builds three such workflows against Foxit's cloud REST APIs, covering Office-to-PDF conversion, template-based document generation, and structural text extraction. It is written so you can follow along step by step even if you are new to n8n. One of the three ships as a ready-made Foxit template you import and inspect. The other two are patterns you assemble from the same HTTP Request node against documented endpoints, so you can judge the approach on real request shapes rather than a feature list.
Prerequisites: Run n8n Locally and Get a Free Foxit Account
Everything here runs on free, self-hosted infrastructure, so there is no n8n Cloud subscription to buy. You run n8n yourself in a container, and the only account you create is Foxit's free Developer plan.
Install Docker and start n8n
Install Docker first (Docker Desktop on macOS and Windows, Docker Engine on Linux). Then bring up n8n with the standard command from n8n's Docker docs:
docker volume create n8n_data
docker run -it --rm --name n8n -p 5678:5678 \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
The n8n_data volume keeps your workflows and credentials intact across restarts, since n8n writes them to an embedded SQLite database, and -p 5678:5678 maps the editor to a local port. Once the container is running:
- Open http://localhost:5678.
- Create the local owner account n8n prompts for on first launch. This is a login for your own instance, not an n8n Cloud account.
- You arrive at an empty canvas, ready to build.
Replace -it --rm with -d when you want n8n running detached in the background.
Get and store your Foxit credentials
Sign up at account.foxit.com/site/sign-up, confirm your email, and the free Developer plan activates with 500 credits per year and no credit card. Open the developer dashboard and copy your Client ID and Client Secret. The eSign API is a separate product with its own account and is out of scope here, so the single Developer pair is all three of these workflows need.
Every Foxit cloud call in this article carries two lowercase headers, client_id and client_secret, with no OAuth exchange to run. Store them once in n8n's credential store so you never paste raw keys into a node. Because Foxit needs two custom headers, use the Custom Auth credential type (the same type Foxit's published template uses). Go to Credentials, click Create credential, search for Custom Auth, click Continue, and paste:
{
"headers": {
"client_id": "YOUR_FOXIT_CLIENT_ID",
"client_secret": "YOUR_FOXIT_CLIENT_SECRET"
}
}
The Custom Auth credential stores both Foxit headers in one place. Every HTTP Request node in all three workflows attaches this same credential.
One host serves every call in this tutorial, https://na1.fusion.foxit.com, so you set it once per node. When you want to see a raw request and response before wiring a node, the interactive API reference in the developer portal lets you fire each endpoint directly.
Import a Finished Workflow (Optional Shortcut)
Each of the three workflows below can be built by hand, but you can also import a finished copy and study it. On any workflow canvas, open the ⋯ (Actions) menu in the top right and choose Import from URL....
The Actions menu on the workflow canvas. "Import from URL..." pulls a workflow straight from a link, so there is nothing to download first.
Paste the raw URL of the workflow you want and click Import. n8n fetches the JSON and draws the full node graph.
The Import from URL dialog. Paste any of the workflow URLs below to load that graph onto the canvas.
- Generation (Workflow 2) :
https://github.com/lucienchemaly/foxit-demo-templates/raw/main/n8n/foxit-document-generation.json - Extraction (Workflow 3) :
https://github.com/lucienchemaly/foxit-demo-templates/raw/main/n8n/foxit-pdf-extraction.json - Conversion (Workflow 1) : import the published Foxit template, or use
https://github.com/lucienchemaly/foxit-demo-templates/raw/main/n8n/foxit-office-to-pdf-conversion.json
An imported graph arrives with placeholder credentials, so you still create the Custom Auth credential above and select it on each Foxit node. The sections below explain what every node does either way.
Workflow 1 (Ready-Made): Automated Office-to-PDF Conversion
Start here because Foxit publishes a working n8n template for it. In n8n, open the workflow Import menu and import Auto-convert OneDrive Word documents to PDF with Foxit and send via Gmail. You get a real, wired graph to study before you generalize the pattern.
The published Foxit conversion template imported into the local editor. The upload, submit-task, poll, and download nodes make the asynchronous flow visible as a graph.
The important thing to understand is that PDF Services conversion is asynchronous and task-based. It is not a single call that hands back a PDF. The verified flow is four steps.
-
Upload the source file with
POST /pdf-services/api/documents/uploadasmultipart/form-dataunder the field namefile. It returns{"documentId": "..."}. -
Submit the conversion with
POST /pdf-services/api/documents/create/pdf-from-wordand a JSON body of{"documentId": "<id>"}. It returns{"taskId": "..."}. -
Poll
GET /pdf-services/api/tasks/{taskId}untilstatusreadsCOMPLETED, watching theprogressfield climb and readingresultDocumentIdoff the completed response. -
Download the finished PDF with
GET /pdf-services/api/documents/{resultDocumentId}/download.
How each step maps to a node
Every step is an HTTP Request node configured the same way you configure any Foxit call, where you set the method and URL, attach the Custom Auth credential under Authentication, and toggle Send Body on when there is a payload.
The HTTP Request config panel. The upload node sets Send Body to multipart/form-data with a binary file field; the convert, poll, and download nodes send JSON or plain GET requests.
The upload node is the one that differs from every other call, since it sends the file itself rather than JSON. Set Body Content Type to Form-Data, add a parameter named file with its type set to n8n Binary File, and point it at the incoming binary.
The upload node's multipart configuration. This is the only step that posts a binary file; every other Foxit call in this article sends JSON.
The chain is a trigger that emits a binary file (OneDrive in the template, but any file-producing trigger works), an HTTP Request node to upload, a second to submit the convert task, a polling construct such as an IF or Loop Over Items node that re-checks the task endpoint until it reports COMPLETED, and a final HTTP Request node to download. The one detail people miss is that the download path takes the resultDocumentId from the poll response, not the original documentId from the upload.
Run it once
To try it locally without wiring up OneDrive, give the upload node a file to work with directly. Download the sample invoice_simple.docx, and either point a file-reading trigger at it or execute the upload node with the file pinned as input, then click Execute workflow to watch it move through upload, task, poll, and download. When the download node runs, you get a real PDF back.
The download node's output, a real PDF produced by the four-step conversion against the sample Word file.
In practice this workflow standardizes Office attachments arriving from a CRM, bulk-converts report exports, and archives form outputs as PDF.
Workflow 2 (You Build It): Template-Based Document Generation
The second workflow is a pattern you assemble rather than a published template. The node chain is a Form Trigger or webhook that captures field values, an HTTP Request or storage node that fetches a Word template, a Code node that base64-encodes the template binary, an HTTP Request node that posts to Document Generation, and an output node that writes or forwards the rendered PDF.
The generation pattern assembled from HTTP Request and Code nodes. The template is base64-encoded in a Code node before the synchronous generation call.
The one non-HTTP step is the Code node that produces the base64 string. n8n already stores an incoming binary file as base64, so the code reads it straight off the item and emits it under base64FileString.
The Code node that base64-encodes the template. Because n8n keeps binary data base64-encoded internally, the node just reads binary.data.data and passes it to the generation call.
Configure the generation call
Add an HTTP Request node and set it up:
-
Method :
POST -
URL :
https://na1.fusion.foxit.com/document-generation/api/GenerateDocumentBase64 - Authentication : Generic Credential Type, then Custom Auth, selecting the credential from the Prerequisites.
- Send Body : on, body type JSON, with the payload below.
{
"base64FileString": "<base64-encoded invoice_simple.docx>",
"documentValues": {
"companyName": "Acme Robotics",
"invoiceNumber": "INV-2026-0042",
"invoiceDate": "2026-07-01",
"totalDue": "1875.50"
},
"outputFormat": "pdf"
}
In this request, base64FileString carries the template encoded as base64, documentValues is a flat object whose keys line up one-to-one with the template's {{ }} tags, and outputFormat is the lowercase "pdf" or "docx". Unlike the conversion endpoint, this one is synchronous, so it returns the rendered file as base64 in the same HTTP response with no task to poll. The response object carries message, fileExtension, and base64FileString, and you decode the last of those into your finished document. The base64 encoding of the template happens in the Code node just before this call, reading the fetched file's binary and emitting a base64 string.
The mistake to avoid is mixing the two upload styles. Document Generation wants the template as a base64 string inside the JSON body, not as a multipart/form-data file the way the conversion upload in Workflow 1 works. Reaching for the multipart pattern here is the most common reason a first generation call fails.
There is also a size ceiling. Document Generation rejects a .docx payload over 4 MB after base64 encoding, which is roughly a 3 MB raw file, and it surfaces the rejection as a plain HTTP 500 rather than a clear message. Keep templates lean by compressing images through Word's Picture Format settings, dropping embedded fonts and OLE objects, and splitting a large template into parts. Fetch a ready template at the storage step, for example invoice_simple.docx, whose tags {{ companyName }}, {{ invoiceNumber }}, {{ invoiceDate \@ MM/dd/yyyy }}, and {{ totalDue \# "$#,##0.00" }} map straight to the documentValues keys above. Job postings, contracts, invoices, and compliance reports all fit this shape.
Workflow 3 (You Build It): Text Extraction and Downstream Pipeline Integration
The third workflow reuses the upload-task-poll-download rhythm from Workflow 1 and swaps in the extraction operation.
The extraction pattern. It mirrors the conversion flow but downloads a ZIP, which a Code node unpacks to reach the structured JSON.
Upload the PDF with POST /pdf-services/api/documents/upload, then submit extraction with POST /pdf-services/api/documents/pdf-structural-extract, which returns 202 and a taskId. Poll GET /pdf-services/api/tasks/{taskId} until COMPLETED to read the resultDocumentId, then call GET /pdf-services/api/documents/{resultDocumentId}/download, which returns a ZIP rather than a single file. At minimum that ZIP contains StructureInfo.json, whose top-level object wraps everything under analyzeResult, and image-bearing documents also include per-page PNG renders. A Code node using n8n's binary helpers unpacks the archive and parses the JSON.
Pin the schema when you parse. Structural extraction classifies content into twelve typed element types, and the payload is versioned, so the parsing Code node should read analyzeResult.version.schema (currently 1.0.7) and branch on it rather than assuming a fixed shape that a later version could change. Reading the version defensively is the difference between a parser that survives an upgrade and one that breaks silently.
Once the text and tables are in hand, route them to whatever comes next. That downstream step is your choice, not a Foxit-documented chain, and it might be an OpenAI summarization node, an HTTP Request to an entity-recognition or enrichment service, a database write, or an email. The useful cases are feeding extracted contract text into an AI pipeline, populating a BI tool from scanned invoices, or indexing document content into a search system.
Production Considerations: Polling, Error Handling, Retries, and Scale
A few things separate a demo from something you would run unattended.
- Polling discipline : PDF Services is task-based with no webhook callback, so each conversion or extraction workflow owns its own poll loop. Bound the loop with a max-attempts counter and a wait between checks so a stuck task cannot spin forever. The eSign API is the Foxit product that offers native callbacks, which is worth knowing when you extend beyond these three workflows.
- Error handling : wrap each Foxit HTTP Request node with an Error Trigger workflow and log the response body, since Foxit returns structured error payloads that make debugging fast. Treat a 4xx as a payload problem to fix and a 5xx as a transient failure to retry with backoff.
- Credentials : keep the Client ID and Secret in n8n's credential store rather than hardcoding them in node expressions, and drive them from environment variables in a self-hosted deployment.
- Scale : split large file sets with a Loop Over Items (Split in Batches) node to stay within per-request limits and keep memory bounded, and let n8n's execution queue pace the work instead of firing one giant batch.
- Compliance : Foxit's cloud APIs are SOC 2 Type II certified, support GDPR requirements, and offer HIPAA alignment under a BAA, with TLS 1.2 or higher in transit and AES-256 at rest, per the Foxit API Security and Compliance page. Note that posture in your team's data-flow diagram when the documents carry PII or PHI.
Common Mistakes and Troubleshooting
-
Conversion is not one call. PDF Services conversion and extraction are asynchronous. If you expect a PDF back from the convert call itself, you get a
taskIdinstead. Poll the task, then download. -
Downloading with the wrong id. The download step uses
resultDocumentIdfrom the completed task, not thedocumentIdfrom the upload. Using the upload id returns nothing useful. -
Polling too early.
GET /tasks/{taskId}reportsIN_PROGRESSuntil the work finishes. Loop with a short wait and a max-attempts cap rather than reading it once. -
base64 vs multipart. Document Generation takes the template as a base64 string in the JSON body; PDF Services upload takes a
multipart/form-datafile. Swapping the two is the most common first-call failure. -
Credential not attached. A
401almost always means an HTTP Request node left Authentication on None. Attach the Custom Auth credential. -
Template over the cap. An HTTP 500 with a "cannot be larger than 4 MB" body means the encoded
.docxexceeded the Document Generation limit. Slim the template.
Start With One Workflow Today
Pick the smallest useful piece and run it end to end before building anything larger. Spin up the local n8n container, register for the free Foxit Developer plan at account.foxit.com/site/sign-up, and copy your Client ID and Client Secret from the dashboard.
Then import the published Office-to-PDF n8n template, point it at a sample .docx, and run it once to watch the upload-task-poll-download flow work before you change anything. From there, choose the workflow that matches your current pain. Reach for Workflow 1 if you are standardizing file formats, Workflow 2 if you are generating documents from form or CRM data, and Workflow 3 if you are feeding document content into an AI or BI pipeline.
If you want to test the calls before building the full workflow, sign up for Foxit's free Developer plan and import the conversion template into your local n8n to watch the flow run end to end. Create your free account and grab your Client ID and Secret from the dashboard. Which of these three patterns fits a problem you are solving now, and what downstream system are you routing the output into?
FAQ
Does Foxit's Document Generation API support DOCX output as well as PDF?
Yes. Set outputFormat to "docx" in the request body to receive a rendered Word file. The same base64 template and documentValues structure applies to both output formats, so you can generate editable Word files from the same template used for PDF output.
How do I handle the poll loop if a task never completes?
Build a max-attempts counter into your Loop Over Items node and set a Wait node between each poll request. If the counter hits its limit before status equals COMPLETED, route the execution to an Error Trigger that logs the taskId for investigation. A loop without a ceiling will tie up your n8n instance.
Can I use n8n Cloud instead of self-hosting with Docker?
Yes, but this tutorial uses the self-hosted Community Edition specifically because it requires no paid plan. The HTTP Request node behavior and Foxit credential handling are identical between Community Edition and n8n Cloud. The Docker setup described here takes under five minutes and gives you full control over your execution environment.
Where can I find more details on Foxit's API credit usage?
The Foxit API credits reference provides a full breakdown of how credits apply across different API operations. The free Developer tier includes enough credits to validate all three workflow patterns described in this tutorial.
What file types does Foxit's PDF Services API support for conversion?
Foxit's PDF Services API converts Microsoft Word (.docx), Excel (.xlsx), and PowerPoint (.pptx) to PDF via the create/pdf-from-word, create/pdf-from-excel, and create/pdf-from-ppt endpoints respectively. All three follow the same four-step asynchronous pattern, where you upload the file, submit the task, poll for completion, then download the result.
Why does my generated document come back with blank fields or a server error?
Two issues account for most generation problems, and neither surfaces the way you might expect. A key in documentValues that does not exactly match a {{ }} placeholder does not raise an error at all. The call returns HTTP 200 and that field simply renders blank, since the merge performs a case-sensitive lookup, so confirm your placeholder names with the Analyze endpoint first. Separately, a .docx payload that exceeds 4 MB after base64 encoding is rejected with an HTTP 500 and a message that it cannot be larger than 4 MB, so keep the raw template under roughly 3 MB.
How does n8n PDF workflow automation compare to running Python scripts for document processing?
Python scripts cannot natively respond to webhooks, branch on CRM conditions, or hand off to a downstream database write without additional glue code. An n8n HTTP Request node calling Foxit's REST API sits inside a workflow already connected to triggers, conditional logic, and output nodes, so document processing becomes one step in a larger automated pipeline rather than a standalone process.
Is it possible to extract structured table data from PDFs using Foxit's Structural Extraction API?
Yes. The StructureInfo.json output from PDF Structural Extraction includes typed element types that cover tables alongside text blocks, headings, and other document components. After downloading and unzipping the result, parse analyzeResult in a Code node to access table data separately from prose content and route it to a database, spreadsheet, or BI tool.










Top comments (0)