{
  "id": "",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Verified Gym Trial Pass with Photo ID",
  "tags": [
    {
      "id": "BPzhQdipnO0Tjdq6",
      "name": "automation",
      "createdAt": "2025-10-22T13:59:37.916Z",
      "updatedAt": "2025-10-22T13:59:37.916Z"
    },
    {
      "id": "eDX0n9nuTRkN3HXW",
      "name": "gym",
      "createdAt": "2025-11-04T10:11:32.024Z",
      "updatedAt": "2025-11-04T10:11:32.024Z"
    },
    {
      "id": "pNPUfS51M4LssnEi",
      "name": "verification",
      "createdAt": "2025-11-04T10:11:32.013Z",
      "updatedAt": "2025-11-04T10:11:32.013Z"
    }
  ],
  "nodes": [
    {
      "id": "422f57ff-1e2c-49c9-ad61-fec687b01d93",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        480,
        224
      ],
      "parameters": {
        "path": "gym-trial",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "4b2316d0-1c3b-4279-a2ee-731d161bb156",
      "name": "IF Email Valid",
      "type": "n8n-nodes-base.if",
      "position": [
        1248,
        224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "753c55c0-be3a-4e15-a5db-b0914547ca23",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.valid }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "cdcd52eb-2ac2-4f4a-bb79-7b9f39b249e2",
      "name": "Send Error Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1552,
        432
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"error\",\n  \"message\": \"Invalid or disposable email address. Please use a valid email to register.\",\n  \"email_verified\": false,\n  \"email_provided\": \"{{ $json.email }}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "28dee952-c257-4fc6-ab2c-c33be5d4c286",
      "name": "Generate Pass Details",
      "type": "n8n-nodes-base.code",
      "position": [
        1552,
        64
      ],
      "parameters": {
        "jsCode": "// CRITICAL: Get original webhook data (before email verification)\n// The VerifiEmail node only outputs verification result, not the original fields\nconst webhookData = $('Webhook').first().json.body;\n\n// Get verification result from current input\nconst verificationData = $input.first().json;\n\n// Generate unique pass ID\nconst passId = \"GYM-\" + Date.now();\n\n// Get current timestamp\nconst issuedAt = new Date().toISOString();\n\n// Format dates nicely for display\nconst formatDate = (dateStr) => {\n  if (!dateStr) return 'Not provided';\n  const date = new Date(dateStr);\n  if (isNaN(date.getTime())) return 'Invalid Date';\n  return date.toLocaleDateString('en-US', { \n    year: 'numeric', \n    month: 'long', \n    day: 'numeric' \n  });\n};\n\n// Return all data from webhook + new generated fields\nreturn [{\n  json: {\n    name: webhookData.name,\n    email: webhookData.email,\n    photo_url: webhookData.photo_url,\n    start_date: webhookData.start_date,\n    valid_till: webhookData.valid_till,\n    pass_id: passId,\n    issued_at: issuedAt,\n    start_date_formatted: formatDate(webhookData.start_date),\n    valid_till_formatted: formatDate(webhookData.valid_till),\n    email_verified: verificationData.valid || false\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "9b135975-0911-4eaf-9132-77e3d5710c08",
      "name": "Generate QR Code",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1808,
        64
      ],
      "parameters": {
        "url": "=https://api.qrserver.com/v1/create-qr-code/?data={{ $json.pass_id }}&size=200x200",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "e092fddb-54d3-4a80-9d90-0f566ac1eecb",
      "name": "Build HTML Pass",
      "type": "n8n-nodes-base.set",
      "position": [
        2080,
        64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "html-template",
              "name": "html_content",
              "type": "string",
              "value": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n    body {\n      font-family: 'Arial', sans-serif;\n      background: #f5f5f5;\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      min-height: 100vh;\n      padding: 20px;\n    }\n    .pass-card {\n      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n      border-radius: 20px;\n      padding: 40px;\n      width: 500px;\n      box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n      color: white;\n      text-align: center;\n    }\n    .header {\n      font-size: 28px;\n      font-weight: bold;\n      margin-bottom: 25px;\n      text-transform: uppercase;\n      letter-spacing: 2px;\n    }\n    .photo-container {\n      margin: 20px 0;\n    }\n    .photo {\n      width: 120px;\n      height: 120px;\n      border-radius: 50%;\n      border: 5px solid white;\n      object-fit: cover;\n      box-shadow: 0 5px 15px rgba(0,0,0,0.3);\n    }\n    .member-name {\n      font-size: 26px;\n      font-weight: bold;\n      margin: 20px 0 10px 0;\n    }\n    .validity-box {\n      background: rgba(255,255,255,0.2);\n      border-radius: 10px;\n      padding: 15px;\n      margin: 20px 0;\n    }\n    .validity-label {\n      font-size: 14px;\n      opacity: 0.9;\n      margin-bottom: 5px;\n    }\n    .validity-dates {\n      font-size: 18px;\n      font-weight: bold;\n    }\n    .qr-section {\n      background: white;\n      border-radius: 15px;\n      padding: 20px;\n      margin: 25px 0;\n      display: inline-block;\n    }\n    .qr-code {\n      width: 180px;\n      height: 180px;\n    }\n    .pass-id {\n      background: rgba(0,0,0,0.2);\n      padding: 10px 20px;\n      border-radius: 25px;\n      font-size: 16px;\n      font-weight: bold;\n      margin: 15px 0;\n      letter-spacing: 1px;\n    }\n    .footer {\n      font-size: 13px;\n      opacity: 0.8;\n      margin-top: 20px;\n      line-height: 1.6;\n    }\n    .issued-date {\n      font-size: 11px;\n      opacity: 0.7;\n      margin-top: 15px;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"pass-card\">\n    <div class=\"header\">\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f GYM TRIAL PASS</div>\n    \n    <div class=\"photo-container\">\n      <img src=\"{{ $('Webhook').item.json.body.photo_url }}\" class=\"photo\" alt=\"Member Photo\">\n    </div>\n    \n    <div class=\"member-name\">{{ $('Webhook').item.json.body.name }}</div>\n    \n    <div class=\"validity-box\">\n      <div class=\"validity-label\">VALID FROM</div>\n      <div class=\"validity-dates\">{{ $json.start_date_formatted }}</div>\n      <div style=\"margin: 10px 0; font-size: 20px;\">\u2193</div>\n      <div class=\"validity-label\">VALID TILL</div>\n      <div class=\"validity-dates\">{{ $json.valid_till_formatted }}</div>\n    </div>\n    \n    <div class=\"qr-section\">\n      <img src=\"https://api.qrserver.com/v1/create-qr-code/?data={{ $json.pass_id }}&size=200x200\" class=\"qr-code\" alt=\"QR Code\">\n    </div>\n    \n    <div class=\"pass-id\">PASS ID: {{ $json.pass_id }}</div>\n    \n    <div class=\"footer\">\n      \ud83d\udcf1 Show this QR code at the gym entrance<br>\n      to activate your trial membership\n    </div>\n    \n    <div class=\"issued-date\">Issued: {{ $json.issued_at }}</div>\n  </div>\n</body>\n</html>"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8520fb96-c0f0-4e03-a82c-1f7afb8def9d",
      "name": "Send Email with Pass",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3168,
        64
      ],
      "parameters": {
        "sendTo": "={{ $('Webhook').item.json.body.email }}",
        "message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">\n  <h2 style=\"color: #667eea;\">Welcome to Our Gym Family, {{ $('Webhook').item.json.body.name }}! \ud83d\udcaa</h2>\n  \n  <p>Great news! Your trial pass has been <strong>verified and activated</strong>.</p>\n  \n  <div style=\"background: #f0f0f0; padding: 20px; border-radius: 10px; margin: 20px 0;\">\n    <h3 style=\"margin-top: 0;\">\ud83d\udccb Trial Pass Details:</h3>\n    <ul style=\"list-style: none; padding: 0;\">\n      <li>\ud83c\udd94 <strong>Pass ID:</strong> {{ $('Generate Pass Details').item.json.pass_id }}</li>\n      <li>\ud83d\udcc5 <strong>Valid From:</strong> {{ $('Generate Pass Details').item.json.start_date_formatted }}</li>\n      <li>\ud83d\udcc5 <strong>Valid Till:</strong> {{ $('Generate Pass Details').item.json.valid_till_formatted }}</li>\n      <li>\u2705 <strong>Email Verified:</strong> Yes</li>\n    </ul>\n  </div>\n  \n  <p><strong>Your digital pass is attached to this email.</strong></p>\n  \n  <div style=\"background: #667eea; color: white; padding: 15px; border-radius: 5px; margin: 20px 0;\">\n    <strong>\ud83d\udcf1 How to Use Your Pass:</strong><br>\n    Show the QR code on your pass at the gym entrance. Our staff will scan it to activate your trial membership.\n  </div>\n  \n  <p>If you have any questions, feel free to reply to this email or visit our front desk.</p>\n  \n  <p>Stay fit, stay strong! \ud83d\udd25</p>\n  \n  <p style=\"color: #888; font-size: 12px; margin-top: 30px;\">\n    \u2013 The Gym Team\n  </p>\n</div>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Your Verified Gym Trial Pass - Welcome! \ud83c\udfcb\ufe0f\u200d\u2640\ufe0f"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "db0868f4-deda-4798-834c-508cf752591b",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3472,
        64
      ],
      "parameters": {
        "columns": {
          "value": {
            "Name": "={{ $('Webhook').item.json.body.name }}",
            "Email": "={{ $('Webhook').item.json.body.email }}",
            "Status": "Active",
            "Pass ID": "={{ $('Generate Pass Details').item.json.pass_id }}",
            "Issued At": "={{ $('Generate Pass Details').item.json.issued_at }}",
            "Start Date": "={{ $('Generate Pass Details').item.json.start_date_formatted }}",
            "Valid Till": "={{ $('Generate Pass Details').item.json.valid_till_formatted }}",
            "Email Verified": "true"
          },
          "schema": [
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Pass ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Pass ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Start Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Start Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Valid Till",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Valid Till",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Issued At",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Issued At",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email Verified",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email Verified",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Pass ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_NAME",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=YOUR_GOOGLE_SHEET_NAME",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Gym Trial Passes 2025"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "67e66825-ef97-4f50-a483-d5710980f340",
      "name": "Send Success Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3744,
        64
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"success\",\n  \"message\": \"Gym trial pass verified and sent successfully! \ud83c\udf89\",\n  \"data\": {\n    \"pass_id\": \"{{ $json['Pass ID'] }}\",\n    \"email\": \"{{ $json.Email }}\",\n    \"name\": \"{{ $json.Name }}\",\n    \"valid_from\": \"{{ $json['Start Date'] }}\",\n    \"valid_till\": \"{{ $json['Valid Till'] }}\",\n    \"email_verified\": true,\n    \"recorded_in_sheets\": true,\n    \"pass_sent_to_email\": true\n  },\n  \"timestamp\": \"{{ $json['Issued At'] }}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1a0b7624-a659-4392-adbc-373a376a82c1",
      "name": "Verifi Email",
      "type": "n8n-nodes-verifiemail.verifiEmail",
      "position": [
        896,
        224
      ],
      "parameters": {
        "email": "={{ $json.body.email }}"
      },
      "credentials": {
        "verifiEmailApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "de56d48e-83e9-402c-8225-8b37a6c54aea",
      "name": "HTML/CSS to Image",
      "type": "n8n-nodes-htmlcsstoimage.htmlCssToImage",
      "position": [
        2336,
        64
      ],
      "parameters": {
        "html_content": "={{ $json.html_content }}"
      },
      "credentials": {
        "htmlcsstoimgApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "61962b44-e00d-4321-a7dd-21a9bc4399e4",
      "name": "HTML to PDF",
      "type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
      "position": [
        2624,
        64
      ],
      "parameters": {
        "html_content": "={{ $('Build HTML Pass').item.json.html_content }}"
      },
      "credentials": {
        "htmlcsstopdfApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b014ca2a-96c8-415b-86fd-d21d93361522",
      "name": "Digital Pass",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2912,
        64
      ],
      "parameters": {
        "url": "={{ $json.pdf_url }}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "70feca54-0be7-4593-b4e1-b9c2736ab1b7",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        48,
        0
      ],
      "parameters": {
        "width": 580,
        "height": 532,
        "content": "## Verified Gym Trial Pass Automation\n\nThis workflow automates gym trial pass generation with email verification, QR codes, and professional PDF passes.\n\n### How it works\n1. Webhook receives signup (name, email, photo_url, dates)\n2. VerifiEmail validates email authenticity\n3. Generates unique Pass ID and QR code\n4. Creates branded HTML pass design\n5. Converts to image and PDF\n6. Emails PDF pass to verified member\n7. Logs all signups in Google Sheets\n\n### Setup steps\n- **VerifiEmail:** Add API key from verifi.email\n- **HTMLCSSToImage & HTMLCSSToPDF:** Add credentials from htmlcsstoimg.com and pdfmunk.com\n- **Gmail:** Connect via OAuth2\n- **Google Sheets:** Create sheet 'Gym Trial Passes 2025' with headers: Name, Email, Pass ID, Start Date, Valid Till, Issued At, Email Verified, Status\n\nTest via Postman POST to webhook URL with JSON body containing: name, email, photo_url, start_date, valid_till"
      },
      "typeVersion": 1
    },
    {
      "id": "0851a6c4-d6e4-4991-92ae-3512b0040be9",
      "name": "Sticky Note21",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 256,
        "content": "## Pass Generation\n\nGenerates unique Pass ID, QR code, and formats dates. References original webhook data to preserve all fields after email verification."
      },
      "typeVersion": 1
    },
    {
      "id": "7132553c-278c-4487-aa81-d7ba0dde5e9a",
      "name": "Sticky Note22",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2288,
        -48
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 272,
        "content": "## Design & Export\n\nBuilds HTML pass with gradient design, member photo, validity dates, and QR code. Converts to PNG image and PDF format."
      },
      "typeVersion": 1
    },
    {
      "id": "35d5ec32-113d-47e4-be05-07723fb18ea6",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        112
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 272,
        "content": "## Input & Validation\n\nReceives signup data via webhook, verifies email authenticity using VerifiEmail, and routes to success or error path based on validation results."
      },
      "typeVersion": 1
    },
    {
      "id": "c557853c-1c73-44be-b7e6-7fecd1f18524",
      "name": "Sticky Note19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3120,
        -64
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 304,
        "content": "## Delivery, Logging & Response\n\nEmails PDF pass to verified member, logs signup in Google Sheets, and returns success JSON response with pass details."
      },
      "typeVersion": 1
    },
    {
      "id": "6cfcb575-7e09-4a19-9ae6-d2aed7ffd9e9",
      "name": "Section: Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 360,
        "height": 288,
        "content": "## Error Handling\n\nReturns 400 error response when email validation fails (invalid format or disposable email detected)."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Verifi Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML to PDF": {
      "main": [
        [
          {
            "node": "Digital Pass",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Digital Pass": {
      "main": [
        [
          {
            "node": "Send Email with Pass",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verifi Email": {
      "main": [
        [
          {
            "node": "IF Email Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Email Valid": {
      "main": [
        [
          {
            "node": "Generate Pass Details",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build HTML Pass": {
      "main": [
        [
          {
            "node": "HTML/CSS to Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate QR Code": {
      "main": [
        [
          {
            "node": "Build HTML Pass",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML/CSS to Image": {
      "main": [
        [
          {
            "node": "HTML to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Google Sheets": {
      "main": [
        [
          {
            "node": "Send Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email with Pass": {
      "main": [
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Pass Details": {
      "main": [
        [
          {
            "node": "Generate QR Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}