This workflow corresponds to n8n.io template #12554 — we link there as the canonical source.
This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "oGnERNi9axVVBEfj",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Automate HTML-based document creation with PDF Generator API, Gmail & Supabase",
"tags": [],
"nodes": [
{
"id": "4ac094e9-0394-48e0-bd5c-28d96eb46070",
"name": "Email Is Valid?",
"type": "n8n-nodes-base.if",
"position": [
-1024,
208
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0d865626-cd70-4815-a84c-671a9bb245c0",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "valid"
}
]
}
},
"typeVersion": 2.3
},
{
"id": "cfc188dc-929c-484a-a568-5478d68e6e5f",
"name": "Verify Client Email",
"type": "n8n-nodes-base.hunter",
"position": [
-1216,
208
],
"parameters": {
"email": "={{ $json.client.email }}",
"operation": "emailVerifier"
},
"credentials": {
"hunterApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "ec1b958f-2c27-438f-8dcf-422225d5f265",
"name": "Respond \u2013 Invalid Email",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-800,
432
],
"parameters": {
"options": {
"responseCode": 400
},
"respondWith": "json",
"responseBody": "{\n \"error\": {\n \"code\": \"400 Bad Request\",\n \"message\": \"Email validation failed: invalid email format.\"\n }\n}"
},
"executeOnce": false,
"typeVersion": 1.5,
"alwaysOutputData": false
},
{
"id": "b062010d-eb82-42a4-a058-b4081ff2847c",
"name": "Populate HTML Template",
"type": "n8n-nodes-base.code",
"position": [
-544,
192
],
"parameters": {
"jsCode": "// data from webhook\nconst data = $node[\"Receive Document Request (Webhook)\"].json;\n\n// html template from Postgres\nconst html = $node[\"Load HTML Template\"].json.html_template;\n\nfunction fillTemplate(template, data) {\n return template.replace(/{{\\s*([\\w.\\[\\]0-9]+)\\s*}}/g, (match, path) => {\n try {\n return path\n .replace(/\\[(\\d+)\\]/g, '.$1') // support items[0].field\n .split('.')\n .reduce((obj, key) => obj?.[key], data) ?? match;\n } catch {\n return match;\n }\n });\n}\n\nconst filledHtml = fillTemplate(html, data);\n\nreturn [\n {\n json: {\n html: filledHtml,\n filename: `${data.documentType}_${data.request.id}`\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "f3c33a39-c44d-4f6a-b71c-e443a5106e8e",
"name": "Convert HTML to PDF",
"type": "@pdfgeneratorapi/n8n-nodes-pdf-generator-api.pdfGeneratorApi",
"position": [
-304,
192
],
"parameters": {
"filename": "={{ $json.filename }}",
"resource": "conversion",
"htmlContent": "={{ $json.html }}",
"conversionOptions": {
"paper_size": "a4",
"orientation": "portrait",
"conversionOutput": "file"
}
},
"credentials": {
"pdfGeneratorApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "e9bc752d-8f5f-47d2-8328-f33329e53653",
"name": "Send PDF to Client Email",
"type": "n8n-nodes-base.gmail",
"position": [
-32,
320
],
"parameters": {
"sendTo": "={{ $('Receive Document Request (Webhook)').item.json.client.email }}",
"message": "=Hello {{ $('Receive Document Request (Webhook)').item.json.client.name }},\n\nYour requested document has been generated and is attached to this email for your reference.\n\nIf you have any questions or need further assistance, please do not hesitate to contact us.\n\nBest Regards,\nCompany",
"options": {
"attachmentsUi": {
"attachmentsBinary": [
{
"property": "invoice_2025-0001.pdf"
}
]
}
},
"subject": "={{ \n $json.filename\n .replace(/\\.pdf$/i, '')\n .replace(/^\\w/, c => c.toUpperCase())\n .replace('_', ' ')\n}}",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "7b5761b2-30db-4d09-aaf3-0408dfe04518",
"name": "Record Document Transaction",
"type": "n8n-nodes-base.postgres",
"position": [
256,
48
],
"parameters": {
"query": "INSERT INTO documents (\n document_type,\n document_name,\n request_id,\n client_name,\n client_email,\n file_path,\n file_url\n)\nVALUES (\n $1, $2, $3, $4, $5, $6, $7\n)\nRETURNING id;",
"options": {
"queryReplacement": "={{ $('Receive Document Request (Webhook)').item.json.documentType }}, {{ $('Populate HTML Template').item.json.filename }}, {{ $('Receive Document Request (Webhook)').item.json.request.id }}, {{ $('Receive Document Request (Webhook)').item.json.client.name }}, {{ $('Receive Document Request (Webhook)').item.json.client.email }}, {{ $('Upload PDF to Supabase Storage').item.json.Key }}, https://nwnahpmsaiaekfwuxpft.supabase.co/storage/v1/object/{{ $('Upload PDF to Supabase Storage').item.json.Key }}"
},
"operation": "executeQuery"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "c45a8c6f-a923-4def-8706-8dc0605a460a",
"name": "Upload PDF to Supabase Storage",
"type": "n8n-nodes-base.httpRequest",
"position": [
-32,
48
],
"parameters": {
"url": "=https://nwnahpmsaiaekfwuxpft.supabase.co/storage/v1/object/documents/{{ $('Receive Document Request (Webhook)').item.json.documentType }}/{{ $json.filename }}",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "binaryData",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/pdf"
},
{
"name": "x-upsert",
"value": "false"
}
]
},
"inputDataFieldName": "={{ $json.filename }}"
},
"typeVersion": 4.3
},
{
"id": "61cbe3d7-08e3-4791-9b42-d32646960b75",
"name": "Load HTML Template",
"type": "n8n-nodes-base.postgres",
"position": [
-768,
192
],
"parameters": {
"limit": 1,
"table": {
"__rl": true,
"mode": "list",
"value": "document_templates",
"cachedResultName": "document_templates"
},
"where": {
"values": [
{
"value": "={{ $('Receive Document Request (Webhook)').item.json.documentType }}",
"column": "document_type"
}
]
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {
"outputColumns": [
"html_template"
]
},
"operation": "select"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "54e77c74-c3dd-46ba-aaa0-a56c89868a19",
"name": "Receive Document Request (Webhook)",
"type": "n8n-nodes-base.webhook",
"position": [
-1472,
384
],
"parameters": {
"path": "422d2c5b-d1b2-47a2-a1a6-5785885b6374",
"options": {},
"httpMethod": "POST"
},
"typeVersion": 1
},
{
"id": "f2a780d1-bfbf-4d23-b717-018e828fb326",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1568,
-576
],
"parameters": {
"width": 688,
"height": 624,
"content": "## Automate document creation from HTML using PDF Generator API, Gmail & Supabase\n\nThis workflow automates the creation, validation, and delivery of PDF documents generated from HTML templates using **[PDF Generator API](https://pdfgeneratorapi.com/)**.\n\n ### How it works\n1. Receives a document generation request via an HTTP **POST webhook**.\n2. Validates the client\u2019s email address using **Hunter Email Verification**.\n 2.1 If the email is invalid, the workflow stops and returns an error response.\n3. Generates the document by loading the HTML template, populating it with request data, and converting it into a PDF using **PDF Generator API**.\n4. Sends the generated PDF to the client via **Gmail** and uploads it to **Supabase Storage**.\n5. Records the document generation transaction in the database.\n\n### Setup\nBefore using this workflow, make sure the following components are set up:\n\n* A **POST webhook endpoint** that accepts structured JSON input.\n* **Hunter API credentials** for validating client email addresses.\n* **[PDF Generator API credentials](https://support.pdfgeneratorapi.com/en/article/how-to-integrate-pdf-generator-api-with-n8n-zulhli/#4-step-2-set-your-credentials)** for converting HTML documents to PDF.\n* A **Postgres database** with tables for:\n * HTML document templates,\n * document generation records.\n* **Gmail or SMTP credentials** for sending generated documents via email.\n* **Supabase Storage** for storing generated PDF files."
},
"typeVersion": 1
},
{
"id": "603ed4b5-f72c-4bc7-bda3-9c551b5dbddf",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1568,
112
],
"parameters": {
"color": 7,
"width": 272,
"height": 464,
"content": "## 1. Webhook input\n\nThis pinned data simulates a test JSON payload from the webhook. \n\nIt includes sample information such as the document type, client details, request metadata, and dynamic data used to populate the document template."
},
"typeVersion": 1
},
{
"id": "cd77297d-bada-4e5e-9199-80671f473f15",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1264,
112
],
"parameters": {
"color": 7,
"width": 384,
"height": 256,
"content": "## 2. Validation \u2013 Email verification"
},
"typeVersion": 1
},
{
"id": "bb1bb4fb-7ae0-4776-b9dc-a8c8d729d404",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
400
],
"parameters": {
"color": 7,
"width": 432,
"height": 176,
"content": "\n\n\n\n## 2.1. Invalid email"
},
"typeVersion": 1
},
{
"id": "cfc93c59-5485-448e-a6e9-1d0c0c01a915",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
112
],
"parameters": {
"color": 7,
"width": 720,
"height": 256,
"content": "## 3. Generate PDF document"
},
"typeVersion": 1
},
{
"id": "40946d85-302f-4fdb-9d47-66f89cbee246",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
176,
-32
],
"parameters": {
"color": 7,
"width": 272,
"height": 256,
"content": "## 5. Record transaction"
},
"typeVersion": 1
},
{
"id": "50715f88-c0f3-4723-bb80-f19a7d6a5579",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
-32
],
"parameters": {
"color": 7,
"height": 512,
"content": "## 4. Email & storage"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "eefa53c1-27b1-42c5-8cbf-1ed878d430c5",
"connections": {
"Email Is Valid?": {
"main": [
[
{
"node": "Load HTML Template",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond \u2013 Invalid Email",
"type": "main",
"index": 0
}
]
]
},
"Load HTML Template": {
"main": [
[
{
"node": "Populate HTML Template",
"type": "main",
"index": 0
}
]
]
},
"Convert HTML to PDF": {
"main": [
[
{
"node": "Upload PDF to Supabase Storage",
"type": "main",
"index": 0
},
{
"node": "Send PDF to Client Email",
"type": "main",
"index": 0
}
]
]
},
"Verify Client Email": {
"main": [
[
{
"node": "Email Is Valid?",
"type": "main",
"index": 0
}
]
]
},
"Populate HTML Template": {
"main": [
[
{
"node": "Convert HTML to PDF",
"type": "main",
"index": 0
}
]
]
},
"Send PDF to Client Email": {
"main": [
[]
]
},
"Upload PDF to Supabase Storage": {
"main": [
[
{
"node": "Record Document Transaction",
"type": "main",
"index": 0
}
]
]
},
"Receive Document Request (Webhook)": {
"main": [
[
{
"node": "Verify Client Email",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2hunterApipdfGeneratorApipostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template is designed for teams and developers who need to generate PDF documents automatically from HTML templates. It’s suitable for use cases such as invoices, confirmations, reports, certificates, or any custom document that needs to be created dynamically based on…
Source: https://n8n.io/workflows/12554/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Scraping. Uses httpRequest, postgres, @apify/n8n-nodes-apify, respondToWebhook. Webhook trigger; 61 nodes.
Workflow B — AI Listing Engine. Uses httpRequest, postgres, errorTrigger. Webhook trigger; 47 nodes.
This workflow monitors customer health by combining payment behavior, complaint signals, and AI-driven feedback analysis. It runs on daily and weekly schedules to evaluate risk levels, escalate high-r
Fluxo de voluntárias ZendeskXANXBD. Uses functionItem, zendesk, httpRequest, postgres. Webhook trigger; 25 nodes.
Fluxo de voluntárias ZendeskXANXBD. Uses functionItem, zendesk, httpRequest, postgres. Webhook trigger; 25 nodes.