n8n Integration: Automate Document Generation

Last updated March 23, 2026

The PDFMonkey n8n node lets you generate, retrieve, download, and delete documents directly from your n8n workflows. If you are setting up PDFMonkey with n8n for the first time, start with the Getting Started section below.

Getting Started

n8n is a workflow automation platform that connects different apps and services together. It is an open-source alternative to tools like Zapier and Make, offering both cloud and self-hosted options.

Before you begin, make sure you have:

For the full account creation and template setup walkthrough, see From Zero to First Document.

Setting Up Credentials

Before using the PDFMonkey node, you need to configure your API credentials:

  1. In your n8n workflow, add a PDFMonkey node
  2. Click on Create New Credentials
  3. Enter your PDFMonkey API key (found in your PDFMonkey dashboard)
  4. Click Save

Where to find your API key

Your API key is available in your PDFMonkey dashboard under Account then API. See Authentication for more details.

Your First Workflow

Let’s create a simple workflow that generates a document when triggered manually. Use the template you created in From Zero to First Document, or create a simple template with a greeting variable.

Step 1: Add a Manual Trigger

  1. Create a new workflow in n8n
  2. The Manual Trigger node should already be there
  3. This allows you to test your workflow manually

Step 2: Add the PDFMonkey Node

  1. Click the + button to add a new node
  2. Search for PDFMonkey
  3. Select the PDFMonkey node
  4. Choose Generate Document as the operation

Step 3: Configure the Generate Document Operation

In the PDFMonkey node configuration:

  1. Select your PDFMonkey credentials (or create them if you haven’t)
  2. Set your Template ID from your PDFMonkey template
  3. Set the Payload Input Method to Key-Value Pairs
  4. Add the following fields:
    • Key: name → Value: Peter Parker
    • Key: favoriteNumber → Value: 8

Payload methods

You can choose between Key-Value Pairs (simple) or JSON (for complex data structures). The JSON method is covered in the Generate a Document section below.

Variable naming

Variable names in your template must follow specific formatting rules. See the naming variables reference for correct and incorrect formats.

Step 4: Test Your Workflow

  1. Click on Execute Workflow (the play button at the bottom)
  2. Wait a few seconds for the document to generate
  3. You should see the document details in the output
  4. The file is now available at the download_url provided

Step 5: Download the File (Optional)

If you want to download the generated file as binary data in n8n:

  1. Enable Download File in the PDFMonkey node options
  2. The file is available as binary data in the next nodes

Example: Webhook to Document to Email

Let’s create a more practical workflow that:

  1. Receives data from a webhook
  2. Generates a document with PDFMonkey
  3. Sends the document by email

The Workflow Structure

  1. Webhook node: receives form data
  2. PDFMonkey node: generates the document
  3. Send Email node: sends the file as attachment

Configuration

Webhook node:

  • Set to POST method
  • Path: /generate-document

PDFMonkey node:

  • Operation: Generate Document
  • Select your template
  • Map webhook data to template variables:
    • name{{ $json.name }}
    • favoriteNumber{{ $json.favoriteNumber }}
  • Enable Download File option

Send Email node:

  • Use Gmail, SendGrid, or any SMTP service
  • In attachments, reference the PDFMonkey binary data:
    • Property Name: data
    • File Name: document.pdf

Testing webhooks

Use the Test URL provided by n8n to send POST requests with JSON data like:

{
  "name": "John Doe",
  "favoriteNumber": 42
}

You’ve successfully set up your first PDFMonkey workflow in n8n.

Generate a Document

The Generate Document operation creates a document from one of your PDFMonkey templates. You provide a template and a dynamic data payload, and PDFMonkey renders the file.

Payload Input Methods

The PDFMonkey node offers two ways to send data to your template.

Key-Value Pairs (Simple Mode) is the easiest way to send simple data structures. You add fields one by one, each with a key (the variable name in your template) and a value (static or dynamic from previous nodes).

JSON Format (Advanced Mode) handles complex data structures, nested objects, or arrays. Use JSON when your template expects structured data:

{
  "customer": {
    "name": "Acme Inc.",
    "email": "contact@acme.com",
    "address": {
      "street": "123 Main St",
      "city": "New York",
      "zip": "10001"
    }
  },
  "items": [
    {
      "product": "Widget",
      "quantity": 5,
      "price": 10.99
    },
    {
      "product": "Gadget",
      "quantity": 2,
      "price": 24.99
    }
  ],
  "total": 104.93
}

In your template, access nested data with dot notation:

<h2>Invoice for {{customer.name}}</h2>
<p>{{customer.address.street}}, {{customer.address.city}}</p>

{% for item in items %}
  <p>{{item.product}} x{{item.quantity}} = {{item.price}}</p>
{% endfor %}

For more on structuring your dynamic data, see Defining Dynamic Data.

Using Expressions

n8n expressions let you reference data from previous nodes dynamically:

{{ $json.customerName }}              // Simple field
{{ $node["Webhook"].json["email"] }}  // From specific node
{{ $json.items.length }}              // Array length
{{ new Date().toISOString() }}        // Current date

You can use expressions in Key-Value pair values, JSON payloads (as string values), the custom filename field, and metadata fields.

Custom Filename

You can specify a custom name for the generated file. This is useful when storing files in Google Drive, Dropbox, or other storage services.

In the PDFMonkey node options:

  1. Expand Additional Options
  2. Set Custom Filename
  3. Use a static name or n8n expressions:
Invoice-{{ $json.invoiceNumber }}.pdf
Report-{{ $now.format('YYYY-MM-DD') }}.pdf
{{ $json.customerName }}-Contract.pdf

Filename restrictions

  • Do not use slashes / or backslashes \
  • Avoid special characters that might cause issues on different operating systems
  • Non-latin characters may be escaped or replaced

For more details on filename options, see Custom Filename.

Metadata

Metadata is additional information attached to a document that does not appear in the generated file itself. It is useful for tracking document origin, storing reference IDs, and filtering in webhooks.

To add metadata:

  1. Expand Additional Options in the PDFMonkey node
  2. Set Metadata to Key-Value Pairs or JSON
  3. Add your metadata fields:
{
  "orderId": "ORD-12345",
  "customerEmail": "john@example.com",
  "environment": "production"
}

You can retrieve metadata later using the Get Document operation or in webhook triggers.

Metadata vs Payload

  • Payload (dynamic data): Data used to render the document content
  • Metadata: Information attached to the document but not visible in the output; included in webhook notifications

Wait for Document

By default, the Generate Document operation waits for the document to be fully generated before continuing.

Document generation time

Most documents generate in a few seconds. Complex documents with many pages, images, or JavaScript may take longer. See Document Statuses for the full generation lifecycle.

If you need to disable waiting and handle completion asynchronously, you can use the PDFMonkey Trigger or poll for completion instead.

Arrays and Complex Data

n8n makes it easy to work with arrays from previous nodes. Here is an example using Google Sheets data.

Google Sheets node output:

[
  { "product": "Widget", "qty": 5, "price": 10 },
  { "product": "Gadget", "qty": 2, "price": 25 }
]

In PDFMonkey node (JSON mode):

{
  "customerName": "{{ $json.customerName }}",
  "items": {{ $node["Google Sheets"].json }}
}

The array is passed directly to your template where you can loop over it:

{% for item in items %}
  <tr>
    <td>{{item.product}}</td>
    <td>{{item.qty}}</td>
    <td>{{item.price}}</td>
  </tr>
{% endfor %}

For more on loops and conditional rendering, see Conditions and Loops.

Handling Multiple Items

If your workflow processes multiple items (like multiple customers or orders), use n8n’s Split In Batches node:

1. Get Data (returns 100 items)
2. Split In Batches (batch size: 1)
3. PDFMonkey - Generate Document (runs 100 times)
4. Store files

Or use the Loop Over Items node for more control.

Rate limits

Be mindful of your PDFMonkey plan limits when generating multiple documents. Consider adding Wait nodes between batches if generating many documents. See Rate Limiting for details, and Our Plans for quota information.

Error Handling

Use n8n’s error handling features to manage failures:

  1. Click on the PDFMonkey node
  2. Go to Settings tab
  3. Configure On Error:
    • Stop Workflow (default)
    • Continue With Last Successful Item
    • Continue Execution

For more robust error handling, add an IF node after PDFMonkey to check the document status:

IF: {{ $json.status }} equals "success"
  -> TRUE: Continue with the file
  -> FALSE: Send error notification

PDFMonkey Trigger

The PDFMonkey Trigger is a webhook-based trigger that listens for document generation events. When a document finishes generating, PDFMonkey sends a notification to your n8n workflow. This is useful for automating post-generation actions like storing files, sending notifications, or updating databases.

For background on how PDFMonkey webhooks work (including event types, payload format, and signature verification), see Webhooks.

Setup

  1. In your n8n workflow, click + to add a new node
  2. Search for PDFMonkey Trigger and select it as your workflow’s starting point
  3. Select your PDFMonkey API credentials
  4. Choose which templates to listen to:
    • Any Template: trigger for all documents in your workspace
    • Specific Template: trigger for a single template
    • Multiple Templates: trigger for several selected templates
  5. Copy the Webhook URL displayed by the trigger node
  6. In your PDFMonkey dashboard, go to the Webhooks section
  7. Create a new endpoint with the n8n webhook URL
  8. Check the success and failure events, then press Create
  9. Back in n8n, click the Activate toggle to enable your workflow

Production vs Test webhooks

n8n provides two URLs:

  • Test URL: For testing in the n8n editor
  • Production URL: For activated/published workflows

Make sure to update your PDFMonkey webhook URL when activating your workflow.

Trigger Data

When a document finishes generating, the trigger receives a DocumentCard object. This includes document metadata, status, and download URL, but does not include the original dynamic data you sent:

{
  "document": {
    "id": "a5e86d72-f5b7-43d4-a04e-8b7e08e6741c",
    "app_id": "d6b4e8f2-7a3c-4d1e-9f5b-2c8a1d3e6f90",
    "created_at": "2050-03-13T12:34:56.181+02:00",
    "document_template_id": "2903f5b4-623b-4e10-b2e3-dc7e2e67ea39",
    "document_template_identifier": "My Invoice Template",
    "download_url": "https://pdfmonkey.s3.eu-west-1.amazonaws.com/...",
    "failure_cause": null,
    "filename": "2050-03-14 Peter Parker.pdf",
    "meta": {
      "_filename": "2050-03-14 Peter Parker.pdf",
      "clientRef": "spidey-616"
    },
    "output_type": "pdf",
    "preview_url": "https://preview.pdfmonkey.io/...",
    "public_share_link": null,
    "status": "success",
    "updated_at": "2050-03-13T12:34:59.412+02:00"
  }
}

Dynamic data is not included

The webhook payload does not include the original dynamic data (payload) you sent to generate the document. If you need this information in your workflow, store it in the metadata field when generating the document. Metadata is included in every webhook notification.

Auto-Download

The PDFMonkey Trigger has a Download File option that automatically downloads the generated file when the trigger fires.

When enabled:

  • The file is downloaded as binary data
  • It is available immediately in the next nodes
  • No need for a separate Download File operation

To enable it:

  1. Open the trigger node settings
  2. Expand Additional Options
  3. Toggle Download File to ON

The binary data is available with the key data.

Use Cases

Store files in Google Drive:

1. PDFMonkey Trigger (Download File: enabled)
2. Google Drive - Upload File
   - File: {{ $binary.data }}
   - Folder: /Invoices/
   - Filename: {{ $json.filename }}

Send notification to Slack:

1. PDFMonkey Trigger
2. Slack - Send Message
   - Channel: #notifications
   - Message: "New document generated: {{ $json.filename }}"
   - Attachment: {{ $json.download_url }}

Update database record:

1. PDFMonkey Trigger
2. Postgres - Update
   - Table: orders
   - Where: id = {{ $json.metadata.orderId }}
   - Set: pdf_url = {{ $json.download_url }}, status = 'completed'

Email document to customer:

1. PDFMonkey Trigger (Download File: enabled)
2. Gmail - Send Email
   - To: {{ $json.metadata.customerEmail }}
   - Subject: Your invoice is ready
   - Attachments: {{ $binary.data }}

Metadata for Routing

Metadata enables conditional workflows. When generating a document, attach routing information:

{
  "metadata": {
    "documentType": "invoice",
    "customerId": "12345",
    "sendEmail": true
  }
}

Then in your triggered workflow, use an IF node or Switch node to route based on metadata:

1. PDFMonkey Trigger
2. Switch node
   - Case 1: {{ $json.metadata.documentType }} = "invoice" -> Store in accounting
   - Case 2: {{ $json.metadata.documentType }} = "report" -> Share on Slack
   - Case 3: {{ $json.metadata.documentType }} = "contract" -> Store in DocuSign

Testing

Method 1: Generate a test document. Use another workflow or the API to generate a document, wait for the webhook to fire, and check the trigger node execution in n8n.

Method 2: Use the test webhook.

  1. Click Listen for event in the trigger node
  2. Generate a document from your PDFMonkey template
  3. The trigger catches the event and displays the data
  4. Click Use test event to use this data while building your workflow

Trigger from the dashboard

You can manually trigger a test generation from your PDFMonkey template editor by clicking the Generate button. This fires the webhook immediately.

You can also have multiple n8n workflows listening to the same template. Each webhook receives the notification independently, which is useful for separating environments or having different workflows for different document types.

Delivery Guarantees

PDFMonkey uses Svix to deliver webhooks. Deliveries follow these guarantees:

  • At-least-once delivery: You might receive the same event multiple times
  • Best-effort ordering: Events are usually in order but not guaranteed
  • Automatic retries: Failed deliveries are retried with exponential backoff
  • Signature verification: Every webhook is signed so you can verify authenticity

Make your workflow idempotent

Since webhooks might be delivered multiple times, design your workflow to handle duplicate events gracefully. Use document IDs to check if you have already processed an event.

For full details on webhook configuration (including channel routing and signature verification), see Webhooks.

Other Operations

Beyond generating documents and reacting to triggers, the PDFMonkey node supports several operations for managing documents.

Get Document

The Get Document operation retrieves information about a previously generated document. Use it to check a document’s status, retrieve its download URL, access attached metadata, or verify a document exists before processing.

Required field: Document ID

Document ID: {{ $json.documentId }}

The operation returns complete document information including status, download URL, preview URL, metadata, and timestamps.

Document status values:

  • draft — document is created but not yet queued for generation
  • pending — document is queued for generation
  • generating — document is currently being rendered
  • success — document generated successfully
  • failure — generation failed (check failure_cause for details)

For the full status lifecycle, see Document Statuses.

Download File

The Download File operation downloads a generated file as binary data. Use it to download a file that was generated earlier, get binary data separately from generation, or re-download a document for processing.

Required field: Document ID

Optional field: Binary Property Name (default: data)

Document ID: {{ $json.documentId }}
Binary Property Name: pdfFile

The file is stored as binary data and can be used in email attachments, file storage nodes (Google Drive, Dropbox, etc.), FTP uploads, or further processing nodes.

Generate Document has built-in download

If you are generating and immediately downloading, use the Download File option in the Generate Document operation instead of a separate Download File node.

Delete Document

The Delete Document operation permanently removes a document from PDFMonkey. Use it to clean up after sending a document, remove documents containing sensitive data, manage storage quotas, or implement document retention policies.

Required field: Document ID

Document ID: {{ $json.documentId }}

Deletion is permanent

Once deleted, documents cannot be recovered. The download URL stops working. Make sure you have saved the file elsewhere if you need it.

TTL as alternative

Consider using automatic deletion (TTL) instead of manually deleting documents. You can set documents to auto-delete after a configurable period when generating them.

Polling for Completion

If you generated a document with Wait for Document disabled, you can poll for its completion instead of using a webhook trigger:

1. PDFMonkey - Generate Document (Wait: disabled)
2. Wait (10 seconds)
3. PDFMonkey - Get Document
   - Document ID: {{ $node["PDFMonkey"].json.id }}
4. IF node
   - {{ $json.status }} = "success"
   - TRUE: Continue with the file
   - FALSE: Loop back to step 2

Better approach: Use the trigger

Instead of polling, consider using the PDFMonkey Trigger to be notified when documents are ready. Triggers are more efficient and respond faster.

Combining Operations

Generate, store, and clean up:

1. Manual Trigger
2. PDFMonkey - Generate Document (Download: enabled)
3. Google Drive - Upload File
   - File: {{ $binary.data }}
   - Folder: /Invoices/
4. Postgres - Insert
   - Table: documents
   - Data: {
       drive_url: {{ $node["Google Drive"].json.webViewLink }},
       pdfmonkey_id: {{ $node["PDFMonkey"].json.id }}
     }
5. PDFMonkey - Delete Document
   - Document ID: {{ $node["PDFMonkey"].json.id }}

Conditional download based on status:

1. Webhook (receives document ID)
2. PDFMonkey - Get Document
   - Document ID: {{ $json.documentId }}
3. IF node
   - Condition: {{ $json.status }} = "success"
   - TRUE:
     4a. PDFMonkey - Download File
     5a. Send to customer
   - FALSE:
     4b. Send error notification
     5b. PDFMonkey - Delete Document (cleanup failed attempt)

Re-generate and replace:

1. Webhook (receives order update)
2. PDFMonkey - Delete Document
   - Document ID: {{ $json.oldDocumentId }}
3. PDFMonkey - Generate Document
   - Template: Invoice
   - Payload: {{ $json.updatedData }}
4. Update database with new document ID

Troubleshooting

Authentication Errors

Invalid API key:

401 Unauthorized - Invalid API key
  1. Go to your PDFMonkey dashboard
  2. Navigate to Account then API
  3. Copy your API key
  4. In n8n, update your PDFMonkey credentials with the correct key
  5. Test the connection

For more on API authentication, see Authentication.

Multiple workspaces

If you have multiple PDFMonkey workspaces, make sure you are using the API key from the correct workspace.

If your credentials suddenly stop working, delete the old credentials in n8n, create new ones with a fresh API key, and update all nodes using those credentials.

Template Not Found

404 Not Found - Template does not exist

Causes: the template was deleted, the wrong workspace or API key is in use, or the template ID is incorrect.

Solution: Verify the template exists in your PDFMonkey dashboard, check you are using the correct API key, and re-select the template from the dropdown in n8n.

Template not published:

422 Unprocessable Entity - Template is not published

Go to your template in PDFMonkey and make sure it is published by clicking the Publish button, then try generating again.

Common mistake

This is one of the most frequent errors. Always remember to publish your template after making changes.

Invalid Payload

422 Unprocessable Entity - Invalid payload

Causes: invalid JSON syntax (when using JSON mode), wrong data types, or missing required fields.

Common JSON syntax issues:

Missing quotes:

// Wrong
{ name: "John" }

// Correct
{ "name": "John" }

Trailing commas:

// Wrong
{
  "name": "John",
  "age": 30,
}

// Correct
{
  "name": "John",
  "age": 30
}

Unescaped double quotes in values:

// Wrong - nested quotes break the JSON
{ "name": "Peter "Spider-Man" Parker" }

// Correct - escape inner quotes with backslash
{ "name": "Peter \"Spider-Man\" Parker" }

Using n8n expressions in JSON:

When using expressions, make sure to stringify objects:

// Wrong - Will create invalid JSON
{
  "items": {{ $json.items }}
}

// Correct - Properly stringify
{
  "items": {{ JSON.stringify($json.items) }}
}

Use Key-Value Pairs mode

If you are struggling with JSON syntax, switch to Key-Value Pairs mode. n8n handles all the escaping and formatting automatically.

Download Errors

Download URL expired:

403 Forbidden - Download URL has expired

Download URLs expire after 1 hour for security reasons.

Option 1: Use Get Document to get a fresh URL, then download from the new URL with an HTTP Request node.

Option 2: Enable the Download File option in the Generate Document node to download immediately after generation.

Option 3: Store the binary data in a file storage service (Google Drive, S3, etc.) instead of relying on PDFMonkey URLs.

For more details, see Download URL Returns 403.

Binary data not available:

If no binary data is available for attachment or storage, make sure Download File is enabled:

  • In Generate Document operation: Additional Options then Download File
  • In PDFMonkey Trigger: Additional Options then Download File
  • Or use a Download File operation explicitly

Webhook Issues

Webhook not receiving events checklist:

  1. Workflow is activated (not just saved)
  2. Webhook URL is correct in PDFMonkey
  3. Using Production URL not Test URL
  4. Template is published
  5. Firewall is not blocking requests

To debug: check the Executions tab in n8n for errors, go to template settings in the PDFMonkey dashboard and check webhook delivery logs, and try generating a test document manually. See Webhooks for webhook configuration details.

Receiving duplicate webhook events is expected behavior. PDFMonkey webhooks use at-least-once delivery. Make your workflow idempotent by checking if you have already processed a document:

1. PDFMonkey Trigger
2. Postgres - Check if document ID exists
3. IF node
   - Already processed: Stop
   - New document: Continue processing

Wrong webhook URL: After activating your workflow, the webhook URL changes from Test to Production. Copy the Production URL from the trigger node and update the webhook URL in your PDFMonkey settings.

Expression Errors

Cannot read property of undefined:

Cannot read property 'field' of undefined

This happens when trying to access data that does not exist from a previous node.

Check the node name:

// Wrong node name
{{ $node["PDFmonkey"].json.id }}

// Correct node name (capital M)
{{ $node["PDFMonkey"].json.id }}

Check the data exists:

// Assumes field exists
{{ $json.customer.email }}

// Use optional chaining (n8n 1.0+)
{{ $json.customer?.email }}

// Or provide default value
{{ $json.customer?.email || 'no-email@example.com' }}

Use the expression editor in n8n (click the Expression button) and use the autocomplete to ensure you are referencing the correct fields.

Workflow Timeout

Workflow execution timed out

Causes: document taking too long to generate, network issues, or large file downloads.

Option 1: Increase the timeout in workflow settings (Execution Timeout).

Option 2: Disable “Wait for Document” and use a webhook trigger in a separate workflow.

Option 3: Split into multiple workflows and use webhooks to chain them together.

Memory Errors

JavaScript heap out of memory

This happens when processing very large files or data in n8n.

Solutions:

  1. Process items in smaller batches (use the Split In Batches node)
  2. Use streaming where possible
  3. Increase n8n memory allocation (self-hosted only)
  4. Store large files externally instead of passing them through the workflow

Rate Limiting

429 Too Many Requests - Rate limit exceeded

Add Wait nodes between operations when processing multiple documents:

1. Get items to process
2. Split In Batches (size: 10)
3. Wait (5 seconds)
4. PDFMonkey - Generate Document
5. Loop

Or use the Code node to add delays:

// Wait 1 second per item
await new Promise(resolve => setTimeout(resolve, 1000));
return items;

JSON Formatting

Line breaks in JSON: JSON does not support raw line breaks in strings:

// Wrong
{
  "description": "Line 1
Line 2"
}

// Correct
{
  "description": "Line 1\nLine 2"
}

Or use a Code node to escape:

items[0].json.description = items[0].json.description.replace(/\n/g, '\\n');
return items;

Special characters: Escape double quotes inside string values:

// Wrong - unescaped quotes break JSON
{ "html": "<div class=\"test\">Hello</div>" }

// Correct - escaped inner quotes
{ "html": "<div class=\"test\">Hello</div>" }

Or use Key-Value Pairs mode which handles escaping automatically.

Next Steps

Need More Help?

If you are still experiencing issues:

  1. n8n documentation: docs.n8n.io
  2. PDFMonkey status: status.pdfmonkey.io
  3. n8n Community: community.n8n.io
  4. PDFMonkey support: support@pdfmonkey.io

Include details in support requests

When asking for help, include the full error message, your n8n version, a workflow screenshot, and the steps to reproduce.