This workflow corresponds to n8n.io template #10771 — we link there as the canonical source.
This workflow follows the Gmail → Google Drive 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": "",
"meta": {
"templateCredsSetupCompleted": false
},
"name": "Patient Pre-Check-in Health Card",
"tags": [],
"nodes": [
{
"id": "2f91d899-694a-44da-852a-0512536b9b23",
"name": "Webhook Trigger",
"type": "n8n-nodes-base.webhook",
"position": [
-768,
384
],
"parameters": {
"path": "patient-checkin",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "3d40b91e-1254-4a36-b103-f985c0d9895d",
"name": "Validate Input Data",
"type": "n8n-nodes-base.code",
"position": [
-560,
384
],
"parameters": {
"jsCode": "// Extract data from webhook body\nconst data = $input.item.json.body;\n\n// Required fields validation\nconst requiredFields = ['name', 'email', 'appointment_date', 'appointment_time'];\nconst missingFields = requiredFields.filter(field => !data[field] || data[field].trim() === '');\n\nif (missingFields.length > 0) {\n throw new Error(`Missing required fields: ${missingFields.join(', ')}`);\n}\n\n// Clean and format data\nconst cleanData = {\n name: data.name.trim(),\n email: data.email.trim().toLowerCase(),\n phone: data.phone || 'Not provided',\n appointment_date: data.appointment_date,\n appointment_time: data.appointment_time,\n symptoms: data.symptoms || 'Not specified',\n age: data.age || 'Not specified',\n gender: data.gender || 'Not specified',\n timestamp: new Date().toISOString(),\n // Generate unique patient ID\n patient_id: `PAT-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`\n};\n\n// Format appointment datetime\nconst appointmentDateTime = `${cleanData.appointment_date}T${cleanData.appointment_time}:00`;\ncleanData.appointment_datetime = appointmentDateTime;\n\n// Format for display in Indian format\nconst appointmentDate = new Date(appointmentDateTime);\ncleanData.appointment_display = appointmentDate.toLocaleString('en-IN', {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true\n});\n\n// Also create a short display format\ncleanData.appointment_short = appointmentDate.toLocaleString('en-IN', {\n day: '2-digit',\n month: 'short',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true\n});\n\nreturn cleanData;"
},
"typeVersion": 2
},
{
"id": "aa616b7f-4d48-4254-b0e1-bb875d9fd3f8",
"name": "Check Email Valid",
"type": "n8n-nodes-base.if",
"position": [
-112,
384
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "906bc6a4-c968-44bd-b1ad-22c3e4efb0c6",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.valid }}",
"rightValue": "valid"
}
]
}
},
"typeVersion": 2
},
{
"id": "20ce83eb-f542-4be2-b39d-614c7d3cf2a7",
"name": "Generate QR Code",
"type": "n8n-nodes-base.code",
"position": [
256,
224
],
"parameters": {
"jsCode": "// Get patient data from the Validate Input Data node\nconst patientData = $('Validate Input Data').item.json;\n\n// Create verification URL (replace with your actual clinic URL or use a temporary one)\nconst verificationURL = `https://clinic-verify.mediajade.com/patient/${patientData.patient_id}`;\n\n// Generate QR code using free API (300x300 pixels, high quality)\nconst qrCodeURL = `https://api.qrserver.com/v1/create-qr-code/?size=300x300&format=png&qzone=1&data=${encodeURIComponent(verificationURL)}`;\n\n// Return all patient data plus QR code info\nreturn {\n ...patientData,\n verification_url: verificationURL,\n qr_code_url: qrCodeURL\n};"
},
"typeVersion": 2
},
{
"id": "eef2eaf3-bf1d-447d-a94e-b4e63f33f061",
"name": "Build Health Card HTML",
"type": "n8n-nodes-base.code",
"position": [
448,
224
],
"parameters": {
"jsCode": "const data = $json;\n\n// Build comprehensive HTML health card\nconst htmlContent = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n body {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n padding: 40px 20px;\n }\n .card {\n max-width: 850px;\n margin: 0 auto;\n background: white;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n overflow: hidden;\n }\n .header {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n padding: 40px 30px;\n text-align: center;\n position: relative;\n }\n .header h1 {\n font-size: 36px;\n margin-bottom: 10px;\n font-weight: 700;\n }\n .header p {\n font-size: 18px;\n opacity: 0.95;\n margin-bottom: 20px;\n }\n .status-badge {\n display: inline-block;\n background: #28a745;\n color: white;\n padding: 10px 25px;\n border-radius: 25px;\n font-size: 14px;\n font-weight: 600;\n letter-spacing: 1px;\n }\n .content {\n padding: 40px 35px;\n }\n .patient-info {\n display: grid;\n grid-template-columns: repeat(2, 1fr);\n gap: 20px;\n margin-bottom: 30px;\n }\n .info-block {\n background: #f8f9fa;\n padding: 20px;\n border-radius: 12px;\n border-left: 5px solid #667eea;\n transition: transform 0.2s;\n }\n .info-block:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);\n }\n .info-label {\n font-size: 11px;\n color: #6c757d;\n text-transform: uppercase;\n letter-spacing: 1.2px;\n margin-bottom: 8px;\n font-weight: 600;\n }\n .info-value {\n font-size: 18px;\n color: #212529;\n font-weight: 600;\n line-height: 1.4;\n }\n .symptoms-section {\n background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%);\n border: 2px solid #ffc107;\n padding: 25px;\n border-radius: 12px;\n margin: 30px 0;\n }\n .symptoms-section h3 {\n color: #856404;\n margin-bottom: 12px;\n font-size: 20px;\n display: flex;\n align-items: center;\n gap: 10px;\n }\n .symptoms-section p {\n color: #856404;\n font-size: 16px;\n line-height: 1.6;\n }\n .qr-section {\n text-align: center;\n padding: 35px;\n background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);\n border-radius: 12px;\n margin-top: 30px;\n border: 2px dashed #667eea;\n }\n .qr-section h3 {\n color: #495057;\n margin-bottom: 20px;\n font-size: 22px;\n }\n .qr-container {\n display: inline-block;\n padding: 15px;\n background: white;\n border-radius: 15px;\n box-shadow: 0 4px 15px rgba(0,0,0,0.1);\n }\n .qr-section img {\n max-width: 250px;\n height: 250px;\n border-radius: 10px;\n display: block;\n }\n .patient-id {\n text-align: center;\n font-size: 16px;\n color: #495057;\n margin-top: 20px;\n font-family: 'Courier New', monospace;\n font-weight: 700;\n letter-spacing: 1px;\n padding: 10px;\n background: white;\n border-radius: 8px;\n display: inline-block;\n }\n .footer {\n text-align: center;\n padding: 25px;\n background: #f8f9fa;\n color: #6c757d;\n font-size: 14px;\n line-height: 1.6;\n }\n .footer strong {\n color: #495057;\n }\n .divider {\n height: 2px;\n background: linear-gradient(90deg, transparent, #667eea, transparent);\n margin: 30px 0;\n }\n @media print {\n body {\n background: white;\n padding: 0;\n }\n .card {\n box-shadow: none;\n }\n }\n @media (max-width: 768px) {\n .patient-info {\n grid-template-columns: 1fr;\n }\n .header h1 {\n font-size: 28px;\n }\n .content {\n padding: 30px 20px;\n }\n }\n </style>\n</head>\n<body>\n <div class=\"card\">\n <div class=\"header\">\n <h1>\ud83c\udfe5 Patient Pre-Check-in Health Card</h1>\n <p>Verified & Ready for Appointment</p>\n <span class=\"status-badge\">\u2713 EMAIL VERIFIED</span>\n </div>\n \n <div class=\"content\">\n <div class=\"patient-info\">\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83d\udc64 Patient Name</div>\n <div class=\"info-value\">${data.name}</div>\n </div>\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83c\udd94 Patient ID</div>\n <div class=\"info-value\">${data.patient_id}</div>\n </div>\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83d\udce7 Email Address</div>\n <div class=\"info-value\" style=\"font-size: 15px; word-break: break-word;\">${data.email}</div>\n </div>\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83d\udcf1 Phone Number</div>\n <div class=\"info-value\">${data.phone}</div>\n </div>\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83d\udc65 Age / Gender</div>\n <div class=\"info-value\">${data.age} Years / ${data.gender}</div>\n </div>\n <div class=\"info-block\">\n <div class=\"info-label\">\ud83d\udcc5 Appointment</div>\n <div class=\"info-value\" style=\"font-size: 15px;\">${data.appointment_display}</div>\n </div>\n </div>\n \n <div class=\"divider\"></div>\n \n <div class=\"symptoms-section\">\n <h3>\ud83d\udccb Chief Complaints / Symptoms</h3>\n <p>${data.symptoms}</p>\n </div>\n \n <div class=\"qr-section\">\n <h3>\ud83d\udcf1 Scan QR Code for Quick Check-in</h3>\n <div class=\"qr-container\">\n <img src=\"${data.qr_code_url}\" alt=\"Patient QR Code\">\n </div>\n <div class=\"patient-id\">\n \ud83d\udd10 ID: ${data.patient_id}\n </div>\n <p style=\"margin-top: 15px; color: #6c757d; font-size: 13px;\">\n Show this QR code at reception for instant verification\n </p>\n </div>\n </div>\n \n <div class=\"footer\">\n <strong>\ud83d\udccd Important Instructions:</strong><br>\n Please arrive 10 minutes before your scheduled appointment<br>\n Bring this health card (printed or on your mobile device)<br>\n Carry a valid government-issued ID for verification<br><br>\n <em>Generated on ${new Date(data.timestamp).toLocaleString('en-IN', {\n day: '2-digit',\n month: 'long',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n hour12: true\n })}</em>\n </div>\n </div>\n</body>\n</html>\n`;\n\nreturn {\n ...data,\n html_content: htmlContent\n};"
},
"typeVersion": 2
},
{
"id": "0e4b60f6-05f8-464b-8c0b-8f8914d7187f",
"name": "Download PNG Binary",
"type": "n8n-nodes-base.httpRequest",
"position": [
912,
224
],
"parameters": {
"url": "={{ $json.image_url }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
}
},
"typeVersion": 4.2
},
{
"id": "e47dfc72-f44c-40ba-9d9e-ddd0d04b496f",
"name": "Upload PNG to Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
1216,
224
],
"parameters": {
"name": "={{ $('Build Health Card HTML').item.json.patient_id }}_health_card.png",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_GOOGLE_DRIVE_FOLDER_ID",
"cachedResultName": "Patients record"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "6e3a7d51-6a71-461c-bcc1-0ae809df2a4f",
"name": "Email Health Card to Patient",
"type": "n8n-nodes-base.gmail",
"position": [
1680,
0
],
"parameters": {
"sendTo": "={{ $('Build Health Card HTML').item.json.email }}",
"message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;\">\n <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0;\">\n <h1>\ud83c\udfe5 Your Pre-Check-in is Complete!</h1>\n </div>\n <div style=\"background: #f8f9fa; padding: 30px; border-radius: 0 0 10px 10px;\">\n <p style=\"font-size: 16px; color: #212529;\">Dear <strong>{{ $('Build Health Card HTML').item.json.name }}</strong>,</p>\n <p style=\"font-size: 14px; color: #495057; line-height: 1.6;\">Thank you for completing your pre-check-in! Your email has been verified and your health card is ready.</p>\n <div style=\"background: white; padding: 20px; border-radius: 10px; margin: 20px 0; border-left: 4px solid #667eea;\">\n <h3 style=\"color: #667eea; margin-bottom: 15px;\">\ud83d\udcc5 Appointment Details</h3>\n <p style=\"margin: 5px 0;\"><strong>Date & Time:</strong> {{ $('Build Health Card HTML').item.json.appointment_display }}</p>\n <p style=\"margin: 5px 0;\"><strong>Patient ID:</strong> {{ $('Build Health Card HTML').item.json.patient_id }}</p>\n <p style=\"margin: 5px 0;\"><strong>Symptoms:</strong> {{ $('Build Health Card HTML').item.json.symptoms }}</p>\n </div>\n <div style=\"background: #d4edda; border: 2px solid #28a745; padding: 20px; border-radius: 10px; margin: 20px 0;\">\n <h3 style=\"color: #155724; margin-bottom: 10px;\">\u2713 What to Do Next:</h3>\n <ul style=\"color: #155724; padding-left: 20px;\">\n <li>Your health card is attached (PNG & PDF formats)</li>\n <li>You can print the PDF or show the PNG on your phone</li>\n <li>Scan the QR code at reception for quick check-in</li>\n <li>Arrive 10 minutes before your appointment</li>\n </ul>\n </div>\n <div style=\"text-align: center; margin: 30px 0;\">\n <a href=\"{{ $json.webViewLink }}\" style=\"background: #667eea; color: white; padding: 15px 30px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 5px;\">View PNG in Drive</a>\n </div>\n <p style=\"font-size: 12px; color: #6c757d; text-align: center; margin-top: 30px;\">If you need to reschedule or have questions, please contact us.<br>See you soon!</p>\n </div>\n</div>",
"options": {},
"subject": "=\u2705 Your Pre-Check-in Health Card - Appointment on {{ $('Build Health Card HTML').item.json.appointment_display }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "1d873484-7910-4bb4-ac54-272e59b47d1e",
"name": "Notify Reception Team",
"type": "n8n-nodes-base.slack",
"position": [
1680,
224
],
"parameters": {
"text": "=\ud83c\udfe5 *New Patient Pre-Check-in Verified*\n\n\ud83d\udc64 *Patient:*{{ $('Build Health Card HTML').item.json.name }} \n\ud83c\udd94 *ID:* `{{ $('Build Health Card HTML').item.json.patient_id }}`\n\ud83d\udce7 *Email:* {{ $('Build Health Card HTML').item.json.email }} \u2705 Verified\n\ud83d\udcf1 *Phone:* {{ $('Build Health Card HTML').item.json.phone }}\n\ud83d\udcc5 *Appointment:*{{ $('Build Health Card HTML').item.json.appointment_display }} \n\ud83e\ude7a *Symptoms:* {{ $('Build Health Card HTML').item.json.symptoms }}\n\n\ud83d\udcc1 *Files:*\n\u2022 <{{ $json.webViewLink }}|View PNG>\n\n\u2709\ufe0f Health card emailed to patient",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "YOUR_SLACK_CHANNEL_ID",
"cachedResultName": "YOUR_SLACK_CHANNEL_NAME"
},
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "f40c352d-cea8-4a68-80f5-37a887607035",
"name": "Log to Patient Database",
"type": "n8n-nodes-base.googleSheets",
"position": [
1696,
448
],
"parameters": {
"columns": {
"value": {
"Name": "={{ $('Build Health Card HTML').item.json.name }}",
"Email": "={{ $('Build Health Card HTML').item.json.email }}",
"Phone": "={{ $('Build Health Card HTML').item.json.phone }}",
"Status": "Completed",
"PNG Link": "={{ $json.webViewLink }}",
"Symptoms": "={{ $('Build Health Card HTML').item.json.symptoms }}",
"Timestamp": "={{ $('Build Health Card HTML').item.json.timestamp }}",
"Email Sent": "Yes",
"Patient ID": "={{ $('Build Health Card HTML').item.json.patient_id }}",
"Appointment": "={{ $('Build Health Card HTML').item.json.appointment_date }} at {{ $('Build Health Card HTML').item.json.appointment_time }}",
"Email Verified": "Yes"
},
"schema": [
{
"id": "Timestamp",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Patient ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Patient ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Phone",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Verified",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email Verified",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Appointment",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Appointment",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Symptoms",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Symptoms",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "PNG Link",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "PNG Link",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email Sent",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email Sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Patient ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_DOCUMENT_ID/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "YOUR_GOOGLE_SHEET_DOCUMENT_ID",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_DOCUMENT_ID/edit?usp=drivesdk",
"cachedResultName": "Patients Records"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
},
{
"id": "5080bad8-26d2-494f-be09-ec8aaf3ef40b",
"name": "Respond to Webhook",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
2016,
224
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={{ {\n \"success\": true,\n \"message\": \"Pre-check-in completed successfully\",\n \"patient_id\": $json.patient_id,\n \"email_sent\": true,\n \"verification_status\": \"verified\"\n} }}"
},
"typeVersion": 1.1
},
{
"id": "924cf82b-8ca4-4dc3-a7a6-e8fe594980b7",
"name": "Stop and Error",
"type": "n8n-nodes-base.stopAndError",
"position": [
272,
576
],
"parameters": {
"errorMessage": "Invalid Email"
},
"typeVersion": 1
},
{
"id": "8757e513-b95f-4ed7-ae9a-70c3d3bcc203",
"name": "Verifi Email",
"type": "n8n-nodes-verifiemail.verifiEmail",
"position": [
-352,
384
],
"parameters": {
"email": "={{ $json.email }}"
},
"credentials": {
"verifiEmailApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "d9d1b4ef-ed96-46f2-b565-92a016dcee27",
"name": "HTML/CSS to Image",
"type": "n8n-nodes-htmlcsstoimage.htmlCssToImage",
"position": [
704,
224
],
"parameters": {
"html_content": "={{ $json.html_content }}"
},
"credentials": {
"htmlcsstoimgApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "22dd2a05-108e-44aa-93b3-3f5cf3179f41",
"name": "Sticky Note - Main Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1280,
112
],
"parameters": {
"color": 1,
"width": 420,
"height": 684,
"content": "## \ud83c\udfe5 Patient Pre-Check-in Health Card Workflow\n\n### How it works\nThis workflow automates the complete patient pre-check-in process. When a patient submits their information via a web form, the workflow validates their data, verifies their email using VerifiEmail API, generates a unique patient ID, creates a professional health card (PNG format) with an embedded QR code using HTMLCSSToImg API, uploads the card to Google Drive, emails it to the patient with their appointment details, notifies the clinic reception team via Slack, and logs all information to Google Sheets for record-keeping. The entire process completes in 15-20 seconds with full automation.\n\n### Setup steps\n1. **Add Credentials**: Configure VerifiEmail API, HTMLCSSToImg API, Google Drive OAuth2, Gmail OAuth2, Slack OAuth2, and Google Sheets OAuth2 credentials in n8n\n2. **Create Google Drive Folder**: Create a \"Patients record\" folder in Google Drive and note the folder ID \n3. **Setup Google Sheet**: Create a sheet with columns: Timestamp, Patient ID, Name, Email, Phone, Email Verified, Appointment DateTime, Symptoms, Drive Link, Email Sent, Status\n4. **Configure Slack Channel**: Set up a #clinic-reception channel in your Slack workspace\n5. **Test**: Send a test patient registration and verify all steps complete successfully"
},
"typeVersion": 1
},
{
"id": "1564f9d0-c620-4695-8465-e274aeb581d9",
"name": "Sticky Note - Input",
"type": "n8n-nodes-base.stickyNote",
"position": [
-816,
128
],
"parameters": {
"color": 6,
"width": 376,
"height": 408,
"content": "## \ud83d\udce5 Section 1: Data Input & Validation\n\nReceives patient form data via POST webhook, validates all required fields (name, email, appointment date/time), cleans and formats the data, generates a unique patient ID with timestamp and random string, and creates both long and short display formats for the appointment datetime in Indian locale with 12-hour time format."
},
"typeVersion": 1
},
{
"id": "816c5d4a-eb69-4cc9-aedb-b7304b3900dc",
"name": "Sticky Note - Verification",
"type": "n8n-nodes-base.stickyNote",
"position": [
-368,
192
],
"parameters": {
"color": 6,
"width": 432,
"height": 360,
"content": "## \ud83d\udd0d Section 2: Email Verification\n\nVerifies patient email address using VerifiEmail API to ensure deliverability. If verification fails (valid = false), workflow stops and sends error notification to patient. If successful (valid = true), proceeds to generate health card."
},
"typeVersion": 1
},
{
"id": "55655ae3-ee67-4f53-b094-5abb993ca022",
"name": "Sticky Note - Generation",
"type": "n8n-nodes-base.stickyNote",
"position": [
224,
48
],
"parameters": {
"color": 6,
"width": 824,
"height": 328,
"content": "## \ud83c\udfa8 Section 3: Health Card Generation\n\nGenerates professional health card with patient details. Creates verification URL and QR code using free QR Server API. Builds responsive HTML card with gradient header, patient info grid, symptoms section, QR code display, and footer with instructions. Converts HTML to PNG image using HTMLCSSToImg API, then downloads the binary file for Google Drive upload."
},
"typeVersion": 1
},
{
"id": "bb079b7e-c946-4486-bc15-8bd2280898b3",
"name": "Sticky Note - Storage",
"type": "n8n-nodes-base.stickyNote",
"position": [
1088,
-16
],
"parameters": {
"color": 6,
"width": 360,
"height": 392,
"content": "## \ud83d\udcc1 Section 4: Google Drive Storage\n\nUploads the generated PNG health card to Google Drive in the \"Patients record\" folder. File is named using patient ID (e.g., PAT-1762965729048-E5BPPW4T4_health_card.png) for easy identification. Creates shareable Drive link for access by clinic staff and patient."
},
"typeVersion": 1
},
{
"id": "881bced5-eca7-43b1-bcb4-65f9b8c017e4",
"name": "Sticky Note - Delivery",
"type": "n8n-nodes-base.stickyNote",
"position": [
1584,
-256
],
"parameters": {
"color": 6,
"width": 648,
"height": 888,
"content": "## \ud83d\udce7 Section 5: Delivery & Notifications\n\nFinal parallel processing:\n(1) Emails health card to patient with PNG attachment, appointment details, Drive link, and check-in instructions \n\n(2) Sends Slack message to #clinic-reception with patient info, verification status, and Drive link \n\n(3) Logs complete record to Google Sheets with timestamp, patient ID, email verification status, and file links. All three branches converge to send success response back to webhook."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"connections": {
"Verifi Email": {
"main": [
[
{
"node": "Check Email Valid",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger": {
"main": [
[
{
"node": "Validate Input Data",
"type": "main",
"index": 0
}
]
]
},
"Generate QR Code": {
"main": [
[
{
"node": "Build Health Card HTML",
"type": "main",
"index": 0
}
]
]
},
"Check Email Valid": {
"main": [
[
{
"node": "Generate QR Code",
"type": "main",
"index": 0
}
],
[
{
"node": "Stop and Error",
"type": "main",
"index": 0
}
]
]
},
"HTML/CSS to Image": {
"main": [
[
{
"node": "Download PNG Binary",
"type": "main",
"index": 0
}
]
]
},
"Download PNG Binary": {
"main": [
[
{
"node": "Upload PNG to Drive",
"type": "main",
"index": 0
}
]
]
},
"Upload PNG to Drive": {
"main": [
[
{
"node": "Log to Patient Database",
"type": "main",
"index": 0
},
{
"node": "Notify Reception Team",
"type": "main",
"index": 0
},
{
"node": "Email Health Card to Patient",
"type": "main",
"index": 0
}
]
]
},
"Validate Input Data": {
"main": [
[
{
"node": "Verifi Email",
"type": "main",
"index": 0
}
]
]
},
"Notify Reception Team": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Build Health Card HTML": {
"main": [
[
{
"node": "HTML/CSS to Image",
"type": "main",
"index": 0
}
]
]
},
"Log to Patient Database": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"Email Health Card to Patient": {
"main": [
[
{
"node": "Respond to Webhook",
"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.
gmailOAuth2googleDriveOAuth2ApigoogleSheetsOAuth2ApihtmlcsstoimgApislackApiverifiEmailApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automated Email Verification & Digital Health Card Generator
Source: https://n8n.io/workflows/10771/ — 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.
This workflow automates the entire pre-issuance process of workshop participation certificates. When an attendee submits a registration form via a webhook, the workflow validates the data, verifies th
Verified Corporate Training Certificate with CEUs – Fully Automated & Verifiable
This comprehensive workflow automates the entire testimonial collection and publishing process, from submission to social media-ready content. It uses AI to enhance testimonials, generates beautiful b
Simplify employee performance reviews with AI-powered automation. This workflow transforms raw feedback and evaluation inputs into clear, structured, and professional performance review summaries — sa
A comprehensive n8n workflow template that completely automates the startup pitch deck submission process for accelerators, incubators, VC firms, and startup competitions. This workflow validates foun