AutomationFlowsEmail & Gmail › Generate Concert Ticket PDFs with QR Codes

Generate Concert Ticket PDFs with QR Codes

Original n8n title: Generate Concert Ticket Pdfs with Qr Codes Using PDF Generator API

ByMarián Današ @marian on n8n.io

Generate personalized concert ticket PDFs with QR codes using PDF Generator API, then email them to attendees, log sales to Google Sheets, and notify organizers via Slack — all triggered from a simple web form.

Event trigger★★★★☆ complexity11 nodesForm Trigger@Pdfgeneratorapi/N8N Nodes Pdf Generator ApiGmailGoogle SheetsSlack
Email & Gmail Trigger: Event Nodes: 11 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #14216 — we link there as the canonical source.

This workflow follows the Form Trigger → Gmail 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 →

Download .json
{
  "id": "xJYtz0FU0LQCj4uN",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Concert Ticket Generator with QR Code (PDF Generator API)",
  "tags": [],
  "nodes": [
    {
      "id": "sticky-001",
      "name": "\ud83d\udccb Setup Instructions",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        -448
      ],
      "parameters": {
        "width": 892,
        "height": 776,
        "content": "## \ud83c\udfb5 Concert Ticket Generator\n### Powered by PDF Generator API\n\nThis workflow accepts ticket requests via a web form, generates a personalized **PDF ticket with a built-in QR code** using **PDF Generator API**, emails it to the attendee, logs the sale to **Google Sheets**, and notifies the event organizer via **Slack**.\n\n---\n\n### \u2699\ufe0f Setup (4 steps)\n\n**1. Create a PDF ticket template in PDF Generator API**\nSign up at [pdfgeneratorapi.com](https://pdfgeneratorapi.com) \u2192 Templates \u2192 New Template.\nDesign your concert ticket and use these data variables:\n- `ticket_id` \u2014 unique ticket identifier *(also the QR code data \u2014 see note \u2192)*\n- `attendee_name` \u00b7 `event_name` \u00b7 `venue` \u00b7 `event_date` \u00b7 `seat_number`\n- `ticket_tier` \u2014 tier badge (GENERAL / VIP / BACKSTAGE)\n- `issued_date` \u2014 ticket issue date\n\n**2. Set your Template ID**\nIn the **Generate Concert Ticket PDF** node, replace `123456` with your actual template ID (found in the PDF Generator API dashboard).\n\n**3. Add credentials**\n- **Generate Concert Ticket PDF** node \u2192 add your PDF Generator API credentials\n- **Send Ticket to Attendee** node \u2192 connect your Gmail account\n- **Log Ticket Sale** node \u2192 connect your Google Sheets account\n- **Notify Event Organizer** node \u2192 connect your Slack account\n\n**4. Configure Google Sheets & Slack**\nSee the sticky notes on the right for details."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-002",
      "name": "\ud83d\udd32 QR Code & PDF Output",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 420,
        "height": 412,
        "content": "### \ud83d\udd32 QR Code \u2014 Built into the Template\n\nThe QR code is **not generated by this workflow**. Instead, it is a native **QR Code component** inside your PDF Generator API template.\n\n**How to set it up in the template editor:**\n1. Open your template in PDF Generator API\n2. Add a **QR Code** component to the ticket design\n3. Set the QR code data field to: `{{ ticket_id }}`\n4. The QR will automatically encode the unique ticket ID for each generated PDF\n\nThis approach is simpler, more reliable, and gives you full design control over QR code size and position.\n\n---\n**Output format:** `URL` \u2014 the node returns a hosted PDF link valid for 30 days. Change to `File` to attach the PDF directly to the email (update the Gmail node accordingly)."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-003",
      "name": "\ud83d\udcca Google Sheets Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1264,
        16
      ],
      "parameters": {
        "color": 3,
        "width": 380,
        "height": 304,
        "content": "### \ud83d\udcca Google Sheets Tracker\n\nLogs every issued ticket for event management.\n\n**Setup:**\n1. Create a Google Sheet with a tab named **Tickets**\n2. Add these column headers in row 1:\n   `Ticket ID` \u00b7 `Attendee` \u00b7 `Email` \u00b7 `Event` \u00b7 `Venue` \u00b7 `Date` \u00b7 `Seat` \u00b7 `Tier` \u00b7 `PDF URL` \u00b7 `Issued At`\n3. In the **Log Ticket Sale** node, set your Spreadsheet ID and connect your Google account\n\n\ud83d\udca1 Use this sheet to track attendance, validate tickets at the door, or export attendee lists."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-004",
      "name": "\ud83d\udd14 Slack Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1744,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 340,
        "height": 294,
        "content": "### \ud83d\udd14 Slack Notification\n\nSends a real-time alert to the event organizer whenever a new ticket is issued.\n\n**Setup:**\n1. Connect your Slack workspace in the **Notify Event Organizer** node\n2. Set the channel name (e.g. `#tickets` or `#events`)\n3. Optional: remove this node if you don't use Slack"
      },
      "typeVersion": 1
    },
    {
      "id": "node-form",
      "name": "Concert Ticket Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        288,
        384
      ],
      "parameters": {
        "path": "cc+1234567890-+1234567890",
        "options": {},
        "formTitle": "\ud83c\udfb5 Concert Ticket Request",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Full Name",
              "placeholder": "Jane Smith",
              "requiredField": true
            },
            {
              "fieldType": "email",
              "fieldLabel": "Email Address",
              "placeholder": "user@example.com",
              "requiredField": true
            },
            {
              "fieldLabel": "Event Name",
              "placeholder": "Summer Rock Festival 2025",
              "requiredField": true
            },
            {
              "fieldLabel": "Venue",
              "placeholder": "Madison Square Garden, New York",
              "requiredField": true
            },
            {
              "fieldLabel": "Event Date",
              "placeholder": "Saturday, July 5, 2025",
              "requiredField": true
            },
            {
              "fieldLabel": "Seat Number",
              "placeholder": "Section A, Row 3, Seat 12",
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Ticket Tier",
              "fieldOptions": {
                "values": [
                  {
                    "option": "General Admission"
                  },
                  {
                    "option": "VIP"
                  },
                  {
                    "option": "Backstage Pass"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        },
        "formDescription": "Fill in your details to receive your personalized concert ticket via email. Your PDF ticket includes a unique QR code for venue entry."
      },
      "typeVersion": 2.1
    },
    {
      "id": "node-prepare",
      "name": "Prepare Ticket Data",
      "type": "n8n-nodes-base.code",
      "position": [
        688,
        384
      ],
      "parameters": {
        "jsCode": "const item = $input.item.json;\n\n// Generate unique ticket ID (URL-safe, 8 chars)\nconst chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\nlet suffix = '';\nfor (let i = 0; i < 8; i++) {\n  suffix += chars[Math.floor(Math.random() * chars.length)];\n}\nconst ticketId = 'TKT-' + suffix;\n\nconst issuedDate = new Date().toLocaleDateString('en-US', {\n  year: 'numeric', month: 'long', day: 'numeric'\n});\n\nconst ticketTier = item['Ticket Tier'] || 'General Admission';\n\n// Tier badge for the PDF template and email\nconst tierBadge = ticketTier === 'VIP' ? 'VIP'\n  : ticketTier === 'Backstage Pass' ? 'BACKSTAGE'\n  : 'GENERAL';\n\n// Tier accent colour used in the confirmation email\nconst tierColor = ticketTier === 'VIP' ? '#7B2FBE'\n  : ticketTier === 'Backstage Pass' ? '#C0392B'\n  : '#0f3460';\n\n// \u26a0\ufe0f Replace 123456 with your PDF Generator API template ID.\n// The template should include a QR Code component whose data is set to {{ ticket_id }}.\nconst TEMPLATE_ID = 1615251;\n\nreturn [{\n  json: {\n    ticketId,\n    attendeeName:  item['Full Name'],\n    attendeeEmail: item['Email Address'],\n    eventName:     item['Event Name'],\n    venue:         item['Venue'],\n    eventDate:     item['Event Date'],\n    seatNumber:    item['Seat Number'],\n    ticketTier,\n    tierBadge,\n    tierColor,\n    issuedDate,\n    emailSubject:  `\ud83c\udfab Your ${ticketTier} Ticket: ${item['Event Name']} \u2014 ${ticketId}`,\n    templateId:    TEMPLATE_ID,\n    outputName:    `concert-ticket-${ticketId}`,\n    // Variables passed to the PDF Generator API template.\n    // Map each one to the corresponding component in your template editor.\n    templateData: {\n      ticket_id:     ticketId,\n      attendee_name: item['Full Name'],\n      event_name:    item['Event Name'],\n      venue:         item['Venue'],\n      event_date:    item['Event Date'],\n      seat_number:   item['Seat Number'],\n      ticket_tier:   tierBadge,\n      issued_date:   issuedDate\n    }\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "node-pdfgen",
      "name": "Generate Concert Ticket PDF",
      "type": "@pdfgeneratorapi/n8n-nodes-pdf-generator-api.pdfGeneratorApi",
      "position": [
        1088,
        384
      ],
      "parameters": {
        "data": "={{ JSON.stringify($json.templateData) }}",
        "templateId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.templateId }}"
        },
        "documentOutput": "url",
        "additionalFields": {
          "outputName": "={{ $json.outputName }}"
        }
      },
      "credentials": {
        "pdfGeneratorApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "node-buildemail",
      "name": "Build Confirmation Email",
      "type": "n8n-nodes-base.code",
      "position": [
        1488,
        384
      ],
      "parameters": {
        "jsCode": "const pdfData    = $input.item.json;\nconst t          = $('Prepare Ticket Data').item.json;\n\n// URL returned by PDF Generator API (documentOutput: url)\nconst pdfUrl = pdfData.response || '';\n\n// Tier-specific header colour\nconst headerColor = t.tierColor || '#0f3460';\n\nconst emailHtml = ''\n  + '<!DOCTYPE html><html><body style=\"margin:0;padding:0;background:#f4f4f8;font-family:Arial,sans-serif\">'\n  + '<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"padding:24px 0\"><tr><td align=\"center\">'\n  + '<table width=\"600\" cellpadding=\"0\" cellspacing=\"0\" style=\"background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 4px 24px rgba(0,0,0,0.12)\">'\n\n  // Header\n  + '<tr><td style=\"background:' + headerColor + ';padding:36px 30px;text-align:center\">'\n  + '<div style=\"font-size:44px;line-height:1\">\ud83c\udfb5</div>'\n  + '<h1 style=\"color:#fff;margin:10px 0 4px;font-size:24px;font-weight:700\">Your Concert Ticket</h1>'\n  + '<span style=\"display:inline-block;background:rgba(255,255,255,0.2);color:#fff;padding:4px 18px;border-radius:20px;font-size:11px;letter-spacing:2px;font-weight:700;margin-top:6px\">'\n  + t.tierBadge\n  + '</span>'\n  + '</td></tr>'\n\n  // Body\n  + '<tr><td style=\"padding:32px 40px\">'\n  + '<p style=\"font-size:16px;color:#333;margin:0 0 10px\">Hi <strong>' + t.attendeeName + '</strong>,</p>'\n  + '<p style=\"color:#555;line-height:1.7;margin:0 0 24px\">Your <strong>' + t.ticketTier + '</strong> ticket is confirmed! Your personalized PDF \u2014 complete with a unique entry QR code \u2014 is ready to download.</p>'\n\n  // Event card\n  + '<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"border:2px dashed ' + headerColor + ';border-radius:10px;margin-bottom:24px\"><tr><td style=\"padding:22px\">'\n  + '<h2 style=\"color:' + headerColor + ';margin:0 0 14px;font-size:19px\">\ud83c\udfb8 ' + t.eventName + '</h2>'\n  + '<p style=\"margin:6px 0;color:#555;font-size:14px\">\ud83d\udccd <strong>Venue:</strong> ' + t.venue + '</p>'\n  + '<p style=\"margin:6px 0;color:#555;font-size:14px\">\ud83d\udcc5 <strong>Date:</strong> ' + t.eventDate + '</p>'\n  + '<p style=\"margin:6px 0;color:#555;font-size:14px\">\ud83d\udcba <strong>Seat:</strong> ' + t.seatNumber + '</p>'\n  + '<p style=\"margin:6px 0;color:#555;font-size:14px\">\ud83c\udfab <strong>Ticket ID:</strong> <code style=\"background:#f0f0f0;padding:2px 7px;border-radius:4px;font-size:13px\">' + t.ticketId + '</code></p>'\n  + '</td></tr></table>'\n\n  // Download button\n  + '<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\"><tr><td align=\"center\" style=\"padding-bottom:24px\">'\n  + '<a href=\"' + pdfUrl + '\" style=\"background:' + headerColor + ';color:#fff;padding:14px 44px;border-radius:8px;text-decoration:none;font-size:15px;font-weight:700;display:inline-block\">\ud83d\udcc4 Download PDF Ticket</a>'\n  + '</td></tr></table>'\n\n  + '<p style=\"color:#999;font-size:12px;text-align:center;margin:0 0 4px\">Your PDF contains a unique QR code for venue entry.</p>'\n  + '<p style=\"color:#bbb;font-size:11px;text-align:center;margin:0\">Please have it ready \u2014 printed or on your phone.</p>'\n  + '</td></tr>'\n\n  // Footer\n  + '<tr><td style=\"background:#f8f8f8;padding:16px 30px;text-align:center;border-top:1px solid #eee\">'\n  + '<p style=\"color:#bbb;font-size:11px;margin:0\">PDF ticket generated with <a href=\"https://pdfgeneratorapi.com\" style=\"color:' + headerColor + ';text-decoration:none\">PDF Generator API</a> &bull; Automated by <a href=\"https://n8n.io\" style=\"color:' + headerColor + ';text-decoration:none\">n8n</a></p>'\n  + '</td></tr>'\n  + '</table></td></tr></table></body></html>';\n\nreturn [{\n  json: {\n    attendeeEmail: t.attendeeEmail,\n    emailSubject:  t.emailSubject,\n    emailHtml,\n    pdfUrl,\n    ticketId:  t.ticketId,\n    eventName: t.eventName,\n    tierBadge: t.tierBadge\n  }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "node-gmail",
      "name": "Send Ticket to Attendee",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1760,
        384
      ],
      "parameters": {
        "sendTo": "={{ $json.attendeeEmail }}",
        "message": "={{ $json.emailHtml }}",
        "options": {},
        "subject": "={{ $json.emailSubject }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "node-sheets",
      "name": "Log Ticket Sale",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2016,
        384
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1hlzNCuQQH_1qq7fQiwRcxq84rKeR9bOVnf8o8hb4wug/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1hlzNCuQQH_1qq7fQiwRcxq84rKeR9bOVnf8o8hb4wug",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1hlzNCuQQH_1qq7fQiwRcxq84rKeR9bOVnf8o8hb4wug/edit?usp=drivesdk",
          "cachedResultName": "Concert Tickets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "node-slack",
      "name": "Notify Event Organizer",
      "type": "n8n-nodes-base.slack",
      "position": [
        2288,
        384
      ],
      "parameters": {
        "text": "={{ '\ud83c\udfab New ticket issued!\\n*' + $('Prepare Ticket Data').item.json.tierBadge + '* \u2014 ' + $('Prepare Ticket Data').item.json.eventName + '\\n\\n\ud83d\udc64 *Attendee:* ' + $('Prepare Ticket Data').item.json.attendeeName + '\\n\ud83d\udce7 ' + $('Prepare Ticket Data').item.json.attendeeEmail + '\\n\ud83d\udcba *Seat:* ' + $('Prepare Ticket Data').item.json.seatNumber + '\\n\ud83c\udf9f *Ticket ID:* ' + $('Prepare Ticket Data').item.json.ticketId + '\\n\\n\ud83d\udcc4 PDF: ' + $('Generate Concert Ticket PDF').item.json.response }}",
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "U02P412345"
        },
        "select": "user",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "59716666-a031-4373-981d-99e95d12a1f9",
  "connections": {
    "Log Ticket Sale": {
      "main": [
        [
          {
            "node": "Notify Event Organizer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Concert Ticket Form": {
      "main": [
        [
          {
            "node": "Prepare Ticket Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Ticket Data": {
      "main": [
        [
          {
            "node": "Generate Concert Ticket PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Ticket to Attendee": {
      "main": [
        [
          {
            "node": "Log Ticket Sale",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Confirmation Email": {
      "main": [
        [
          {
            "node": "Send Ticket to Attendee",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Concert Ticket PDF": {
      "main": [
        [
          {
            "node": "Build Confirmation 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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Generate personalized concert ticket PDFs with QR codes using PDF Generator API, then email them to attendees, log sales to Google Sheets, and notify organizers via Slack — all triggered from a simple web form.

Source: https://n8n.io/workflows/14216/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

Stop chasing blurry receipts and manually typing expense data. This workflow creates an intelligent, "snap-and-submit" reimbursement pipeline that hosts photos via UploadToURL, extracts deep data via

Form Trigger, N8N Nodes Uploadtourl, HTTP Request +3
Email & Gmail

This template automates internal equipment and supply purchase requests for operations, HR, and IT teams. Requests are submitted via a built-in n8n form, automatically approved for small amounts, and

Form Trigger, Google Sheets, Slack +1
Email & Gmail

This workflow is triggered when the contact form is submitted.

Form Trigger, Slack, Google Sheets +2
Email & Gmail

n8n Recruitment. Uses gmailTrigger, openAi, googleSheets, gmail. Event-driven trigger; 20 nodes.

Gmail Trigger, OpenAI, Google Sheets +4
Email & Gmail

Loan eligibility workflow. Uses formTrigger, googleSheets, gmail. Event-driven trigger; 53 nodes.

Form Trigger, Google Sheets, Gmail