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": "o018cyB8genb6ONB",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "6-Utility-Certificate-Creator&Validation",
"tags": [
{
"id": "YOUR-ID",
"name": "YOUR-ID",
"createdAt": "2025-11-23T13:36:13.729Z",
"updatedAt": "2025-11-23T13:36:13.729Z"
}
],
"nodes": [
{
"id": "613c5389-2f80-44c9-8ec1-043d02d720d7",
"name": "Insert_Certificaton",
"type": "n8n-nodes-base.dataTable",
"position": [
320,
-224
],
"parameters": {
"columns": {
"value": {
"Name": "={{ $('Webhook_Creation').item.json.headers.name }}",
"Surname": "={{ $('Webhook_Creation').item.json.headers.surname }}",
"CertificationID": "={{ $('Generate_Certification_ID').item.json.id }}"
},
"schema": [
{
"id": "Name",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Name",
"defaultMatch": false
},
{
"id": "Surname",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Surname",
"defaultMatch": false
},
{
"id": "CertificationID",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "CertificationID",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "Your_ID",
"cachedResultUrl": "/projects/jmCdsRSQMosgYP5V/datatables/Your_ID",
"cachedResultName": "Certifications"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "7b690565-bc2e-4c50-9e34-5368972be90f",
"name": "Generate_Certification_ID",
"type": "n8n-nodes-base.code",
"position": [
-352,
-240
],
"parameters": {
"jsCode": "const uniqueId =\n Date.now().toString(36).toUpperCase() +\n Math.random().toString(36).substring(2, 8).toUpperCase();\n\nreturn [{ id: uniqueId }];\n"
},
"typeVersion": 2
},
{
"id": "ee3e5ab4-7d0a-41d9-b72c-0d1e071c9142",
"name": "Find_Certification_By_ID",
"type": "n8n-nodes-base.dataTable",
"position": [
-144,
-240
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "CertificationID",
"keyValue": "={{ $json.id }}"
}
]
},
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "ZyOrfuHDK22tXq81",
"cachedResultUrl": "/projects/YOUR_ID/datatables/ZyOrfuHDK22tXq81",
"cachedResultName": "Certifications"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "554946dd-0444-4e50-b132-983b44e931e5",
"name": "Certification_ID_Exists",
"type": "n8n-nodes-base.if",
"position": [
64,
-240
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "416a8c8a-b9bd-4044-9987-b3320c09efd4",
"operator": {
"type": "string",
"operation": "empty",
"singleValue": true
},
"leftValue": "=Object",
"rightValue": "={{ $json }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "848bddc2-4362-40b6-a8e0-18511f9b5c23",
"name": "Generate_PDF",
"type": "@pdfgeneratorapi/n8n-nodes-pdf-generator-api.pdfGeneratorApi",
"position": [
528,
-224
],
"parameters": {
"resource": "conversion",
"htmlContent": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Certificate of Achievement</title>\n</head>\n<body>\n\n<div style=\"\n width: 800px;\n height: 600px;\n margin: 50px auto;\n padding: 30px;\n border: 10px solid #0056b3; /* Dark blue main border */\n border-image: linear-gradient(45deg, #0056b3, #007bff, #0056b3) 1; /* Gradient effect */\n box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);\n background-color: #ffffff; /* White background for clean look */\n font-family: 'Arial', sans-serif; /* Simplified font for better rendering */\n text-align: center;\n position: relative;\n\">\n \n <h1 style=\"\n font-size: 48px;\n color: #e3a800; /* Gold/Orange */\n margin-bottom: 0;\n text-transform: uppercase;\n letter-spacing: 3px;\n \">CERTIFICATE</h1>\n \n <h2 style=\"\n font-size: 36px;\n color: #0056b3; /* Dark Blue */\n margin-top: 5px;\n margin-bottom: 40px;\n text-transform: uppercase;\n \">OF ACHIEVEMENT</h2>\n \n <p style=\"\n font-size: 18px;\n color: #343a40;\n margin-bottom: 10px;\n font-style: italic;\n \">Is proudly presented to:</p>\n \n <div style=\"\n border-bottom: 2px solid #343a40;\n display: inline-block;\n padding: 5px 60px;\n margin-bottom: 40px;\n \">\n <p style=\"\n font-size: 36px;\n color: #000000;\n font-weight: bold;\n text-transform: uppercase;\n letter-spacing: 1px;\n margin: 0;\n \">{{ $('Webhook_Creation').item.json.headers.name }} {{ $('Webhook_Creation').item.json.headers.surname }}</p> \n </div>\n \n <p style=\"\n font-size: 24px;\n color: #343a40;\n line-height: 1.5;\n margin-bottom: 80px; /* Increased margin for signature lines */\n \">\n For successful completion and outstanding performance in the course:\n <br>\n <strong style=\"color: #007bff; font-size: 30px;\">\"{{ $('Webhook_Creation').item.json.headers.course }}\"</strong>\n </p>\n \n <div style=\"\n display: flex;\n justify-content: space-around;\n align-items: flex-end;\n width: 80%;\n margin: 0 auto;\n \">\n \n <div style=\"text-align: center; flex-basis: 40%;\">\n <p style=\"\n font-size: 16px; \n font-weight: bold; \n margin: 0 0 5px 0;\n color: #000000;\n letter-spacing: 0.5px;\n \">\n {{ $('Generate_Certification_ID').item.json.id }}\n </p>\n <div style=\"border-top: 1px solid #343a40; width: 100%;\"></div>\n <p style=\"margin: 5px 0 0 0; font-size: 14px; color: #343a40;\">\n Candidate ID\n </p>\n </div>\n \n <div style=\"text-align: center; flex-basis: 40%;\">\n <p style=\"\n font-size: 16px; \n font-weight: bold; \n margin: 0 0 5px 0;\n color: #000000;\n letter-spacing: 0.5px;\n \">\n {{ $today.toFormat('dd/MM/yyyy') }}\n </p>\n <div style=\"border-top: 1px solid #343a40; width: 100%;\"></div>\n <p style=\"margin: 5px 0 0 0; font-size: 14px; color: #343a40;\">\n Date\n </p>\n </div>\n \n </div>\n\n</div>\n\n</body>\n</html>",
"conversionOptions": {
"orientation": "landscape",
"conversionOutput": "file"
}
},
"credentials": {
"pdfGeneratorApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "03f873c2-f9b0-409c-bff0-4d32f5ed6efd",
"name": "Email_Certification",
"type": "n8n-nodes-base.gmail",
"position": [
752,
-224
],
"parameters": {
"sendTo": "={{ $('Webhook_Creation').item.json.headers.email }}",
"message": "Attached you find your new certification!",
"options": {
"attachmentsUi": {
"attachmentsBinary": [
{
"property": "document.pdf"
}
]
}
},
"subject": "Your certification is ready!"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "aed81c3b-10ce-4d98-9b6c-c890c71ab815",
"name": "Webhook_Check",
"type": "n8n-nodes-base.webhook",
"position": [
-592,
224
],
"parameters": {
"path": "certificationscheck",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "71b9f653-4574-4bf2-b9ce-660c083d0a85",
"name": "Find_Certification_By_ID1",
"type": "n8n-nodes-base.dataTable",
"position": [
-352,
224
],
"parameters": {
"filters": {
"conditions": [
{
"keyName": "CertificationID",
"keyValue": "={{ $json.headers.id }}"
}
]
},
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "ZyOrfuHDK22tXq81",
"cachedResultUrl": "/projects/jmCdsRSQMosgYP5V/datatables/ZyOrfuHDK22tXq81",
"cachedResultName": "Certifications"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "e35823bf-189c-4192-85ca-24010ba3ed09",
"name": "Certification_Exists",
"type": "n8n-nodes-base.if",
"position": [
-144,
224
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "416a8c8a-b9bd-4044-9987-b3320c09efd4",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.CertificationID }}",
"rightValue": "={{ $('Webhook_Check').item.json.headers.id }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "98428e2a-330b-4995-b177-74ce6ec41a35",
"name": "Respond_Found",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
96,
160
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"ok\": \"true\",\n \"name\": \"{{ $('Find_Certification_By_ID1').item.json.Name }}\",\n \"surname\": \"{{ $('Find_Certification_By_ID1').item.json.Surname }}\"\n}"
},
"typeVersion": 1.4
},
{
"id": "15e115bd-3d35-4805-9806-85d6e80a7c21",
"name": "Respond_NotFound",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
96,
288
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "{\n \"ok\": \"false\"\n}"
},
"typeVersion": 1.4
},
{
"id": "38d50087-20f5-43aa-acbd-0893dafe8381",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-672,
-448
],
"parameters": {
"color": 7,
"width": 256,
"height": 368,
"content": "## Creation \n## Webhook input\n\nReceives name, surname, course and email via HTTP POST on `/certifications`. \nStarts the certificate creation flow.\n"
},
"typeVersion": 1
},
{
"id": "9672b65b-832d-4496-9f50-d75b5432fcc2",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
-448
],
"parameters": {
"color": 7,
"width": 864,
"height": 368,
"content": "## Creation \u2013 Generate & validate ID\n\nGenerates a random CertificationID, checks the Data Table for duplicates and only continues when the ID is unique. \nIf the ID already exists, the flow loops until a free one is found.\n"
},
"typeVersion": 1
},
{
"id": "00c13ad1-1026-4b0f-b880-89d901a1ee11",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
480,
-448
],
"parameters": {
"color": 7,
"width": 448,
"height": 368,
"content": "## Creation \u2013 Save, PDF & email\n\nSaves the learner record with the CertificationID to the Data Table, generates the certificate PDF from an HTML template and emails it to the learner.\n"
},
"typeVersion": 1
},
{
"id": "741f9beb-f922-441b-9249-c6a06da55571",
"name": "Sticky Note6",
"type": "n8n-nodes-base.stickyNote",
"position": [
-672,
32
],
"parameters": {
"color": 7,
"width": 256,
"height": 320,
"content": "## Check \u2013 Webhook input\n\nReceives a CertificationID via HTTP POST on `/certificationscheck` and starts the verification flow.\n"
},
"typeVersion": 1
},
{
"id": "1c7f6487-80e4-45d2-a676-645f66c4bfaf",
"name": "Webhook_Creation",
"type": "n8n-nodes-base.webhook",
"position": [
-592,
-240
],
"parameters": {
"path": "certifications",
"options": {},
"httpMethod": "POST",
"responseMode": "lastNode"
},
"typeVersion": 2.1
},
{
"id": "28750e3a-7cec-4a45-8a5a-cb87dbd3181d",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-400,
32
],
"parameters": {
"color": 7,
"width": 432,
"height": 320,
"content": "## Check \u2013 Look up ID\n\nSearches the Certifications Data Table for the submitted CertificationID and branches depending on whether a matching record exists.\n"
},
"typeVersion": 1
},
{
"id": "18468a33-fdb7-4602-a995-29d9e1c5aca5",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
272,
176
],
"parameters": {
"color": 7,
"width": 432,
"height": 176,
"content": "## Check \u2013 Responses\n\nReturns JSON to the caller. \nIf the ID is found: `ok: true` plus name and surname. \nIf not found: `ok: false` so the client can show an \u201cinvalid certification\u201d message.\n"
},
"typeVersion": 1
},
{
"id": "3bedbbcb-cd61-4c54-872d-cfd54df9e991",
"name": "Sticky Note10",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1344,
-448
],
"parameters": {
"width": 640,
"height": 560,
"content": "## Certifications \u2013 Creator & Checker\n\n## How it works\nThis workflow manages the full lifecycle of a training certificate. \n`/certifications` receives learner details, generates a unique CertificationID and checks that it does not exist yet. \nIf the ID is free, the workflow stores the record, builds a PDF certificate and emails it to the learner. \n\n`/certificationscheck` lets you verify a certificate later. \nThe webhook receives a CertificationID, looks it up in the same Data Table and returns a simple JSON response that frontends or other services can use to show \u201cvalid\u201d or \u201cnot found\u201d.\n\n## Setup steps\n1. Create a Data Table (e.g. **Certifications**) with Name, Surname, CertificationID and any extra fields.\n2. Configure the PDF Generator node with your account API and adjust the HTML template to your branding.\n3. Connect your email account (Gmail/SMTP) in **Email_Certification**.\n4. Deploy the `/certifications` and `/certificationscheck` webhooks and use their public URLs.\n5. Test creation and verification with a few sample requests before going live.\n"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "898197be-08ab-4488-85ee-a9a1b688cb1c",
"connections": {
"Generate_PDF": {
"main": [
[
{
"node": "Email_Certification",
"type": "main",
"index": 0
}
]
]
},
"Webhook_Check": {
"main": [
[
{
"node": "Find_Certification_By_ID1",
"type": "main",
"index": 0
}
]
]
},
"Webhook_Creation": {
"main": [
[
{
"node": "Generate_Certification_ID",
"type": "main",
"index": 0
}
]
]
},
"Insert_Certificaton": {
"main": [
[
{
"node": "Generate_PDF",
"type": "main",
"index": 0
}
]
]
},
"Certification_Exists": {
"main": [
[
{
"node": "Respond_Found",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond_NotFound",
"type": "main",
"index": 0
}
]
]
},
"Certification_ID_Exists": {
"main": [
[
{
"node": "Generate_Certification_ID",
"type": "main",
"index": 0
}
],
[
{
"node": "Insert_Certificaton",
"type": "main",
"index": 0
}
]
]
},
"Find_Certification_By_ID": {
"main": [
[
{
"node": "Certification_ID_Exists",
"type": "main",
"index": 0
}
]
]
},
"Find_Certification_By_ID1": {
"main": [
[
{
"node": "Certification_Exists",
"type": "main",
"index": 0
}
]
]
},
"Generate_Certification_ID": {
"main": [
[
{
"node": "Find_Certification_By_ID",
"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.
gmailOAuth2pdfGeneratorApi
About this workflow
6-Utility-Certificate-Creator&Validation. Uses dataTable, @pdfgeneratorapi/n8n-nodes-pdf-generator-api, gmail, respondToWebhook. Webhook trigger; 19 nodes.
Source: https://github.com/paoloronco/n8n-templates/blob/main/free-templates/3-Certification-Creation&Validation/Cetificate-Creation&Validation.json — original creator credit. Request a take-down →