{
  "name": "Shopify paid order to PDF invoice (html-pdf.com)",
  "nodes": [
    {
      "parameters": {
        "content": "## Shopify paid order to PDF invoice\n1. **Shopify Trigger** fires on `orders/paid`.\n2. **Build invoice HTML** turns the order into a styled HTML invoice. Edit the `SHOP` block and CSS.\n3. **Create invoice PDF** sends it to html-pdf.com with `response: \"url\"` and gets back a download link (valid 24 hours).\n4. **Email invoice link** sends the link to the customer with Gmail.\n\nWant an attachment instead? Remove `response` from the JSON body, set the response format to **File**, and add the `data` field under Gmail *Options → Attachments*.",
        "height": 380,
        "width": 560
      },
      "id": "8638c3db-8bf9-5796-9ed1-d9ff3aedb406",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -80,
        -340
      ]
    },
    {
      "parameters": {
        "content": "## html-pdf.com credential\nCreate a **Header Auth** credential:\n- Name: `Authorization`\n- Value: `Bearer hp_live_...`\n\nFree key (100 pages, no card): https://html-pdf.com/login\nDocs: https://html-pdf.com/docs\n\nAlso connect: Shopify (Access Token) and Gmail (OAuth2).",
        "height": 380,
        "width": 380,
        "color": 5
      },
      "id": "81dc5c7e-e1a1-5019-be6c-4e8ba94ff2cb",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        500,
        -340
      ]
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "topic": "orders/paid"
      },
      "id": "79d84e4f-672b-5208-8e95-64ebf62b16c3",
      "name": "Shopify Trigger",
      "type": "n8n-nodes-base.shopifyTrigger",
      "typeVersion": 1,
      "position": [
        0,
        120
      ],
      "credentials": {
        "shopifyAccessTokenApi": {
          "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
          "name": "Shopify account"
        }
      },
      "webhookId": "086a6c99-c8b4-5631-ade4-078acfd85c25"
    },
    {
      "parameters": {
        "jsCode": "// Builds a printable invoice from the Shopify order (orders/paid webhook body).\n// Edit SHOP and the CSS to match your brand.\nconst SHOP = { name: 'Your Store', address: '1 Main St, City', email: 'hello@yourstore.com' };\n\nconst esc = (v) => String(v ?? '').replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]));\n\nreturn $input.all().map(({ json: order }) => {\n  const cur = order.currency || '';\n  const money = (v) => `${Number(v || 0).toFixed(2)} ${cur}`;\n  const bill = order.billing_address || {};\n  const customerName = [order.customer?.first_name, order.customer?.last_name].filter(Boolean).join(' ') || bill.name || '';\n  const shipping = (order.shipping_lines || []).reduce((s, l) => s + Number(l.price || 0), 0);\n\n  const rows = (order.line_items || []).map((li) => `\n    <tr>\n      <td>${esc(li.title)}${li.variant_title ? ` <span class=\"muted\">(${esc(li.variant_title)})</span>` : ''}</td>\n      <td class=\"r\">${li.quantity}</td>\n      <td class=\"r\">${money(li.price)}</td>\n      <td class=\"r\">${money(Number(li.price) * li.quantity)}</td>\n    </tr>`).join('');\n\n  const html = `<!doctype html><html><head><meta charset=\"utf-8\"><style>\n    body { font-family: Helvetica, Arial, sans-serif; color: #111; font-size: 13px; margin: 0; }\n    h1 { font-size: 26px; margin: 0 0 4px; }\n    .muted { color: #666; }\n    .top { display: flex; justify-content: space-between; margin-bottom: 32px; }\n    table { width: 100%; border-collapse: collapse; margin-top: 16px; }\n    th, td { padding: 8px 6px; border-bottom: 1px solid #e5e5e5; text-align: left; }\n    th { background: #f6f6f6; }\n    .r { text-align: right; }\n    .totals td { border: none; padding: 4px 6px; }\n    .grand td { font-weight: bold; font-size: 15px; border-top: 2px solid #111; }\n  </style></head><body>\n    <div class=\"top\">\n      <div><h1>Invoice</h1><div class=\"muted\">Order ${esc(order.name)} · ${esc((order.created_at || '').slice(0, 10))}</div></div>\n      <div class=\"r\"><strong>${esc(SHOP.name)}</strong><br>${esc(SHOP.address)}<br>${esc(SHOP.email)}</div>\n    </div>\n    <div><strong>Bill to</strong><br>${esc(customerName)}<br>${esc(bill.address1)} ${esc(bill.address2)}<br>${esc(bill.zip)} ${esc(bill.city)} ${esc(bill.country)}<br>${esc(order.email)}</div>\n    <table>\n      <thead><tr><th>Item</th><th class=\"r\">Qty</th><th class=\"r\">Price</th><th class=\"r\">Total</th></tr></thead>\n      <tbody>${rows}</tbody>\n    </table>\n    <table class=\"totals\">\n      <tr><td class=\"r\" style=\"width:80%\">Subtotal</td><td class=\"r\">${money(order.subtotal_price)}</td></tr>\n      <tr><td class=\"r\">Shipping</td><td class=\"r\">${money(shipping)}</td></tr>\n      <tr><td class=\"r\">Tax</td><td class=\"r\">${money(order.total_tax)}</td></tr>\n      <tr class=\"grand\"><td class=\"r\">Total</td><td class=\"r\">${money(order.total_price)}</td></tr>\n    </table>\n  </body></html>`;\n\n  return {\n    json: {\n      html,\n      filename: `invoice-${String(order.name || order.id).replace('#', '')}.pdf`,\n      email: order.email,\n      customerName,\n      orderName: order.name,\n    },\n  };\n});"
      },
      "id": "c0367a3c-897d-5670-8b43-8f19d1f5c0aa",
      "name": "Build invoice HTML",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        120
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://html-pdf.com/v1/pdf",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ html: $json.html, format: 'A4', margin: '15mm', print_background: true, filename: $json.filename, response: 'url' }) }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          },
          "timeout": 60000
        }
      },
      "id": "41c409dc-5de0-51e3-8d45-05f634add092",
      "name": "Create invoice PDF",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        120
      ],
      "credentials": {
        "httpHeaderAuth": {
          "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
          "name": "html-pdf.com API key"
        }
      }
    },
    {
      "parameters": {
        "sendTo": "={{ $('Build invoice HTML').item.json.email }}",
        "subject": "=Your invoice for order {{ $('Build invoice HTML').item.json.orderName }}",
        "emailType": "html",
        "message": "=<p>Hi {{ $('Build invoice HTML').item.json.customerName }},</p><p>Thanks for your order. You can download your invoice here:</p><p><a href=\"{{ $json.url }}\">Download invoice (PDF)</a></p><p>The link is valid for 24 hours.</p>",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "1884f997-4e33-554e-bd06-dd38b721eb54",
      "name": "Email invoice link",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        660,
        120
      ],
      "credentials": {
        "gmailOAuth2": {
          "id": "REPLACE_WITH_YOUR_CREDENTIAL_ID",
          "name": "Gmail account"
        }
      },
      "webhookId": "0d543dc0-9444-5449-b25d-c1d9347a9439"
    }
  ],
  "pinData": {},
  "connections": {
    "Shopify Trigger": {
      "main": [
        [
          {
            "node": "Build invoice HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build invoice HTML": {
      "main": [
        [
          {
            "node": "Create invoice PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create invoice PDF": {
      "main": [
        [
          {
            "node": "Email invoice link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}
