AutomationFlowsEmail & Gmail › Quotation Workflow

Quotation Workflow

Quotation-Workflow. Uses httpRequest, googleDrive, gmail. Webhook trigger; 23 nodes.

Webhook trigger★★★★☆ complexity23 nodesHTTP RequestGoogle DriveGmail
Email & Gmail Trigger: Webhook Nodes: 23 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "dc",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "5b641254-75ab-43c0-bb5b-520904aa461e",
      "name": "Webhook Form",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -848,
        480
      ]
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "# n8n Code node: Other Services & GST (Dahi Cheeni)\nbody = _input.all()[0].json.get(\"body\", {})\n\n\ndef extract_number(val):\n    if not val or isinstance(val, (int, float)):\n        return val or 0\n    import re\n    match = re.search(r\"[\\d.]+\", str(val).strip())\n    if not match:\n        return 0\n    try:\n        return float(match.group())\n    except Exception:\n        return 0\n\n\nitems = body.get(\"Items\", [])\nif items and isinstance(items, list):\n    sub_val = sum(extract_number(it.get(\"Amount\", 0)) for it in items)\nelse:\n    sub_val = extract_number(body.get(\"Total\", 0))\n\nchef_val = extract_number(body.get(\"ChefServers\", 0))\ndecor_val = extract_number(body.get(\"TableDecor\", 0))\ncutlery_val = extract_number(body.get(\"Cutlery\", 0))\nchaffing_val = extract_number(body.get(\"Chaffing\", 0))\nconv_val = extract_number(body.get(\"Conveyance\", 0))\nvenue_val = extract_number(body.get(\"VenueCharges\", 0))\n\nsubtotal_with_services = sub_val + chef_val + decor_val + cutlery_val + chaffing_val + conv_val + venue_val\ngst_amount = subtotal_with_services * 0.05\ntotal_amount = subtotal_with_services + gst_amount\n\nreturn [\n    {\"Other Services\": \"Subtotal (Items)\", \"Amount\": sub_val},\n    {\"Other Services\": \"Chef + Servers + Helper\", \"Amount\": body.get(\"ChefServers\", 0)},\n    {\"Other Services\": \"Table D\u00e9cor (As Per Theme)\", \"Amount\": body.get(\"TableDecor\", 0)},\n    {\"Other Services\": \"Cutlery & Crockery\", \"Amount\": body.get(\"Cutlery\", 0)},\n    {\"Other Services\": \"Chaffing Dishes & Snack Warmers\", \"Amount\": body.get(\"Chaffing\", 0)},\n    {\"Other Services\": \"Conveyance\", \"Amount\": body.get(\"Conveyance\", 0)},\n    {\"Other Services\": \"Venue Charges\", \"Amount\": body.get(\"VenueCharges\", 0)},\n    {\"Other Services\": \"Subtotal (With Services)\", \"Amount\": subtotal_with_services},\n    {\"Other Services\": \"GST 5%\", \"Amount\": round(gst_amount, 2)},\n    {\"Other Services\": \"TOTAL AMOUNT\", \"Amount\": round(total_amount, 2)},\n]\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        560
      ],
      "id": "a05eaf23-7a12-4726-8cf5-0803488fb528",
      "name": "Code in Python (Beta)"
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "return []"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        752
      ],
      "id": "dbc43f23-e157-4676-95f0-98d6a22f02f4",
      "name": "Code in Python (Beta)13"
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "# n8n Code node: Customer Details (Dahi Cheeni)\nbody = _input.all()[0].json.get(\"body\", {})\n\nreturn [{\n    \"Event Date\": body.get(\"EventDate\", \"N/A\"),\n    \"Host Name\": body.get(\"HostName\", \"N/A\"),\n    \"Mobile No\": body.get(\"MobileNo\", \"N/A\"),\n    \"Time\": body.get(\"Time\", \"N/A\"),\n    \"Pax\": body.get(\"Pax\", \"N/A\"),\n    \"Location\": body.get(\"Location\", \"N/A\"),\n    \"Quote ID\": body.get(\"QuotationId\", \"\"),\n}]\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        176
      ],
      "id": "b707f219-c2e8-48d4-80d2-7142ca39d1c2",
      "name": "Customer Details"
    },
    {
      "parameters": {
        "content": "## PDF Generation",
        "height": 384,
        "width": 960
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        16,
        336
      ],
      "id": "e107f2aa-623b-46b2-9848-fa12d302483c",
      "name": "Sticky Note7"
    },
    {
      "parameters": {
        "numberInputs": 4
      },
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.2,
      "position": [
        -112,
        432
      ],
      "id": "4c3c8134-e570-47d8-8456-1580b8e2f6da",
      "name": "Merge"
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "# n8n Code node: Menu Item Transformation (Dahi Cheeni \u2014 qty \u00d7 rate)\ninput_data = _input.all()[0].json\nitems_list = input_data.get(\"body\", {}).get(\"Items\", [])\n\noutput = []\nfor item in items_list:\n    qty = item.get(\"Qty\", item.get(\"Portions\", 1))\n    rate = item.get(\"Rate\", 0)\n    try:\n        amount = float(item.get(\"Amount\", 0))\n    except (TypeError, ValueError):\n        try:\n            amount = float(qty or 0) * float(rate or 0)\n        except (TypeError, ValueError):\n            amount = 0\n    output.append({\n        \"Name\": item.get(\"Name\"),\n        \"Description\": item.get(\"Description\"),\n        \"Qty\": qty,\n        \"Rate\": rate,\n        \"Category\": item.get(\"Category\", \"\"),\n        \"Veg/Non Veg\": item.get(\"VegNonVeg\", \"\"),\n        \"Amount\": amount,\n    })\n\nreturn output\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        368
      ],
      "id": "2c2fedc8-5112-4f8e-bfed-570c7866ee2a",
      "name": "Menu Item Transformation"
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "logo_url = \"https://res.cloudinary.com/dwxjq3tj9/image/upload/q_auto/f_auto/v1778926627/Dahi_Cheeni_Logo_draxao.png\"\n\ntry:\n    cust_list = _input.all(\"Customer Details\")\n    cust = cust_list[0].json if cust_list else {}\nexcept Exception:\n    cust = {}\n\nmenu_items = _input.all(\"Proposed Menu\")\nservices = _input.all(\"Other Services\")\nbrand = \"#5c1a1a\"\ncream = \"#f5ebe0\"\ngold = \"#c9a227\"\n\ndef fmt_money(val):\n    if val is None or val == \"\":\n        return \"\"\n    try:\n        s = str(val).replace(\",\", \"\").strip()\n        v = float(s)\n        return f\"\u20b9{int(v):,}\" if v == int(v) else f\"\u20b9{v:,.2f}\"\n    except Exception:\n        return str(val)\n\nhtml = f\"\"\"<!DOCTYPE html>\n<html>\n<head>\n<style>\n  @import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Source+Sans+3:wght@400;600;700&display=swap');\n  @page {{ \n    margin: 15mm;\n    @bottom-center {{\n        content: element(footer);\n    }}\n  }}\n  body {{ font-family: 'Source Sans 3', sans-serif; color: #222; margin: 0; line-height: 1.7; padding-bottom: 35mm; }}\n  \n  .footer {{ \n    position: fixed; \n    bottom: 0; \n    left: 0; \n    right: 0; \n    text-align: center; \n    font-size: 11px; \n    color: #444; \n    border-top: 1px solid #ccc; \n    padding-top: 12px;\n    line-height: 1.4;\n    background: white;\n  }}\n  .footer-title {{ font-weight: 700; font-size: 12px; color: #000; }}\n  \n  h1, h2, h3 {{ font-family: 'Cormorant Garamond', serif; color: {brand}; }}\n  \n  /* Logo and Layout Styling */\n  .logo-wrap {{ text-align: center; padding: 20px 0 30px; }}\n  .main-logo {{ max-width: 120px; height: auto; }}\n  \n  .intro-container {{ padding: 0 10px; }}\n  .welcome-text {{ color: {brand}; font-size: 22px; font-weight: 700; margin-bottom: 25px; font-family: 'Cormorant Garamond', serif; }}\n  .intro-body {{ font-size: 16px; color: #333; }}\n  .intro-body p {{ margin-bottom: 22px; text-align: justify; }}\n  .highlight {{ color: {brand}; font-weight: 700; }}\n  .signature {{ margin-top: 40px; font-size: 16px; line-height: 1.4; }}\n  .signature strong {{ color: {brand}; font-size: 18px; }}\n\n  /* Quotation Page Styling */\n  .header-banner {{ background: {brand}; color: {cream}; padding: 18px; border-radius: 8px; margin-bottom: 20px; }}\n  .header-banner h1 {{ color: {cream} !important; text-align: center; font-size: 28px; margin: 0; letter-spacing: 1px; }}\n  .header-details {{ margin-top: 12px; font-size: 14px; border-top: 1px solid rgba(255,255,255,0.25); padding-top: 10px; }}\n  .detail-row {{ display: table; width: 100%; }}\n  .detail-row > div {{ display: table-cell; width: 50%; padding: 4px 0; }}\n  \n  h2 {{ font-size: 22px; border-bottom: 2px solid {brand}; padding-bottom: 6px; margin-top: 25px; text-transform: uppercase; letter-spacing: 1px; }}\n  \n  .data-table {{ width: 100%; border-collapse: collapse; margin-top: 12px; table-layout: fixed; }}\n  .data-table th {{ background: {brand}; color: {cream}; padding: 10px; border: 1px solid {brand}; font-size: 13px; text-transform: uppercase; }}\n  .data-table td {{ padding: 10px; border: 1px solid #ddd; font-size: 14px; vertical-align: top; }}\n  .cat-row td {{ background: #fdf8f5; font-weight: 700; color: {brand}; font-family: 'Cormorant Garamond', serif; font-size: 18px; padding: 12px 10px; }}\n  \n  .description {{ font-size: 11px; color: #666; font-style: italic; display: block; margin-top: 5px; }}\n  .badge {{ font-size: 10px; padding: 2px 8px; border-radius: 4px; background: #f0f0f0; margin-left: 8px; color: {brand}; font-weight: 700; border: 0.5px solid #ccc; }}\n  .num {{ text-align: center; }}\n  .total-row td {{ font-weight: 700; background: #faf6f4; font-size: 15px; }}\n  \n  .note-list {{ font-size: 14px; padding-left: 20px; }}\n  .note-list li {{ margin-bottom: 12px; }}\n</style>\n</head>\n<body>\n\n<div class=\"footer\">\n  <div class=\"footer-title\">Dahi Cheeni Catering</div>\n  (Unit of NC Hospitality Pvt Ltd) CIN : U55101DL2009PTC188581<br>\n  Regd. Address : E 5 Kalindi Colony, Near New Friends Colony, New Delhi 110065<br>\n  Website : www.dahicheenicatering.com | Email : sales@dahicheenicatering.com\n</div>\n\n<!-- PAGE 1: INTRODUCTION -->\n<div class=\"intro-container\">\n    <div class=\"logo-wrap\">\n      <img src=\"{logo_url}\" class=\"main-logo\" alt=\"Dahi Cheeni\">\n    </div>\n\n    <div class=\"welcome-text\">Welcome to Dahi Cheeni \u2014 Pure Veg Home-Style Catering</div>\n\n    <div class=\"intro-body\">\n      <p>Thank you for considering <span class=\"highlight\">Dahi Cheeni</span> for your upcoming gathering. With over <span class=\"highlight\">10 years of dedicated experience</span> in the hospitality industry, we bring a refined legacy of excellence, taste, and trust to your doorstep.</p>\n      \n      <p>We specialize exclusively in <span class=\"highlight\">100% pure vegetarian catering</span>, designed specifically for your most <span class=\"highlight\">auspicious occasions</span>. Whether it is a housewarming, a traditional ceremony, or an intimate family milestone, our menus are thoughtfully curated to honor the sanctity and joy of your celebration.</p>\n      \n      <p>Our culinary philosophy is rooted in authentic <span class=\"highlight\">\"home-style\" preparation</span>. We prioritize the selection of the freshest seasonal ingredients, traditional spice blends, and the highest standards of hygiene. Our goal is to serve food that doesn't just satiate hunger but evokes a sense of comfort and nostalgia, much like a meal prepared in one\u2019s own family kitchen.</p>\n      \n      <p>We take pride in our smooth, stress-free service, allowing you to focus entirely on being a host while we take care of the flavors.</p>\n      \n      <p>We look forward to being a part of your celebration and creating a delightful, soul-satisfying dining experience for you and your loved ones.</p>\n    </div>\n\n    <div class=\"signature\">\n      Warm regards,<br>\n      <strong>Team Dahi Cheeni</strong><br>\n      Pure Veg. Authentic. Intimate.\n    </div>\n</div>\n\n<div style=\"page-break-before: always;\"></div>\n\n<!-- PAGE 2: QUOTATION -->\n<div class=\"logo-wrap\">\n  <img src=\"{logo_url}\" class=\"main-logo\" alt=\"Dahi Cheeni\">\n</div>\n\n<div class=\"header-banner\">\n  <h1>EVENT QUOTATION</h1>\n  <div class=\"header-details\">\n    <div class=\"detail-row\">\n      <div><strong>HOST:</strong> {cust.get('Host Name', 'N/A')}</div>\n      <div><strong>MOBILE:</strong> {cust.get('Mobile No', 'N/A')}</div>\n    </div>\n    <div class=\"detail-row\">\n      <div><strong>DATE:</strong> {cust.get('Event Date', 'N/A')}</div>\n      <div><strong>TIME:</strong> {cust.get('Time', 'N/A')}</div>\n    </div>\n    <div class=\"detail-row\">\n      <div><strong>LOCATION:</strong> {cust.get('Location', 'N/A')}</div>\n      <div><strong>PAX:</strong> {cust.get('Pax', 'N/A')}</div>\n    </div>\n  </div>\n</div>\n\n<h2>Proposed Menu</h2>\n\"\"\"\n\nfrom collections import OrderedDict\n\ncategories = OrderedDict()\nfor item in menu_items:\n    d = item.json\n    name = (d.get(\"Name\") or \"\").strip()\n    if not name:\n        continue\n    cat = d.get(\"Category\") or \"Other\"\n    categories.setdefault(cat, []).append(d)\n\nfor cat, items in categories.items():\n    html += f\"\"\"\n<table class=\"data-table\">\n  <colgroup>\n    <col style=\"width:50%\" />\n    <col style=\"width:14%\" />\n    <col style=\"width:18%\" />\n    <col style=\"width:18%\" />\n  </colgroup>\n  <thead>\n    <tr class=\"cat-row\"><td colspan=\"4\">{cat.upper()}</td></tr>\n    <tr>\n      <th>ITEM</th>\n      <th class=\"num\">QTY</th>\n      <th class=\"num\">RATE</th>\n      <th class=\"num\">AMOUNT</th>\n    </tr>\n  </thead>\n  <tbody>\n\"\"\"\n    for d in items:\n        # Veg/Non Veg logic removed here\n        qty = d.get(\"Qty\", d.get(\"Portions\", \"\"))\n        html += f\"\"\"\n    <tr>\n      <td><strong>{d.get('Name', '')}</strong>\n        <span class=\"description\">{d.get('Description', '')}</span>\n      </td>\n      <td class=\"num\">{qty}</td>\n      <td class=\"num\">{fmt_money(d.get('Rate', ''))}</td>\n      <td class=\"num\">{fmt_money(d.get('Amount', ''))}</td>\n    </tr>\n\"\"\"\n    html += \"</tbody></table>\"\n\nhtml += f\"\"\"\n<div style=\"page-break-before: always;\">\n  <div class=\"logo-wrap\">\n    <img src=\"{logo_url}\" class=\"main-logo\" alt=\"Dahi Cheeni\">\n  </div>\n  <h2>Other Services &amp; Summary</h2>\n  <table class=\"data-table\">\n    <tbody>\n\"\"\"\n\nfor s in services:\n    sd = s.json\n    label = (sd.get(\"Other Services\") or \"\").strip()\n    if not label:\n        continue\n    amount = fmt_money(sd.get(\"Amount\", \"\"))\n    row_class = \"total-row\" if any(x in label.upper() for x in (\"TOTAL\", \"SUBTOTAL\", \"GST\")) else \"\"\n    html += f'<tr class=\"{row_class}\"><td colspan=\"3\">{label}</td><td class=\"num\">{amount}</td></tr>'\n\nhtml += f\"\"\"\n    </tbody>\n  </table>\n</div>\n\n<div style=\"page-break-before: always; margin-top: 20px;\">\n  <div class=\"logo-wrap\">\n    <img src=\"{logo_url}\" class=\"main-logo\" alt=\"Dahi Cheeni\">\n  </div>\n  <h3 style=\"text-decoration: underline; font-size: 20px;\">Important Terms & Conditions</h3>\n  <ul class=\"note-list\">\n    <li><strong>Pricing Model:</strong> Final billing is based on the actual quantity ordered or the minimum guaranteed pax, whichever is higher.</li>\n    <li><strong>Taxation:</strong> 5% GST is applicable on the final subtotal as per government mandates.</li>\n    <li><strong>Menu Finalization:</strong> We request you to confirm your final menu selections at least 4\u20135 days prior to the event date.</li>\n    <li><strong>Booking Policy:</strong> Dates are blocked only upon receipt of the booking advance.</li>\n    <li><strong>Logistics:</strong> Basic kitchen access, electricity, and water supply should be provided at the venue.</li>\n    <li><strong>Cancellation:</strong> Please refer to our detailed cancellation policy provided at the time of booking.</li>\n  </ul>\n</div>\n\n</body>\n</html>\n\"\"\"\n\nreturn [{\"html_content\": html}]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        112,
        464
      ],
      "id": "43e4ea1d-0324-4c7c-97f9-feb8f6a9b500",
      "name": "JSON TO HTML"
    },
    {
      "parameters": {
        "operation": "toText",
        "sourceProperty": "html_content",
        "binaryPropertyName": "=data",
        "options": {
          "fileName": "=index.html"
        }
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        336,
        464
      ],
      "id": "11421d2c-8daf-490d-be58-fa1eca0539fd",
      "name": "Convert to File"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://168.231.122.119:3010/forms/chromium/convert/html",
        "sendBody": true,
        "contentType": "multipart-form-data",
        "bodyParameters": {
          "parameters": [
            {
              "parameterType": "formBinaryData",
              "name": "files",
              "inputDataFieldName": "data"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        560,
        464
      ],
      "id": "5f3d3c4d-549e-4bf7-a082-5b6cb5d4a350",
      "name": "HTML TO PDF"
    },
    {
      "parameters": {
        "respondWith": "binary",
        "responseDataSource": "set",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        784,
        368
      ],
      "id": "a977732e-ec0a-437a-afe0-9e79c75569c1",
      "name": "Respond to Webhook1"
    },
    {
      "parameters": {
        "name": "={{ $('Webhook Form').first().json.body.HostName }} - {{ $('Webhook Form').first().json.body.EventDate }}.pdf",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "value": "17HkrULgQ6MluWCSysJ19tb_GmW98r85p",
          "mode": "list",
          "cachedResultName": "Little Jalebis",
          "cachedResultUrl": "https://drive.google.com/drive/folders/17HkrULgQ6MluWCSysJ19tb_GmW98r85p"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        784,
        560
      ],
      "id": "079ae593-95a8-4937-9dad-ffe66f89acf2",
      "name": "Upload file",
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "disabled": true
    },
    {
      "parameters": {
        "language": "python",
        "pythonCode": "import json\n\n# Access the body from the first input item\nbody = _input.all()[0].json.get('body', {})\n\n# Helper function to extract numeric values\ndef extract_number(val):\n    if not val or isinstance(val, (int, float)):\n        return val or 0\n    str_val = str(val).strip()\n    import re\n    match = re.search(r'[\\d.]+', str_val)\n    if not match:\n        return 0\n    try:\n        return float(match.group())\n    except:\n        return 0\n\n# Prepare data for Supabase\nsupabase_data = {\n    \"quotation_id\": body.get(\"QuotationId\", \"\"),\n    \"host_name\": body.get(\"HostName\", \"\"),\n    \"mobile_no\": body.get(\"MobileNo\", \"\"),\n    \"event_date\": body.get(\"EventDate\", \"\"),\n    \"time\": body.get(\"Time\", \"\"),\n    \"pax\": body.get(\"Pax\", \"\"),\n    \"location\": body.get(\"Location\", \"\"),\n    \"image_grid\": body.get(\"ImageGrid\", []),\n    \"items\": body.get(\"Items\", []),\n    \"total\": extract_number(body.get(\"Total\", 0)),\n    \"chef_servers\": extract_number(body.get(\"ChefServers\", 0)),\n    \"table_decor\": extract_number(body.get(\"TableDecor\", 0)),\n    \"cutlery\": extract_number(body.get(\"Cutlery\", 0)),\n    \"chaffing\": extract_number(body.get(\"Chaffing\", 0)),\n    \"conveyance\": extract_number(body.get(\"Conveyance\", 0)),\n    \"venue_charges\": extract_number(body.get(\"VenueCharges\", 0)),\n    \"tables\": body.get(\"Tables\", \"\"),\n    \"kitchen_space\": body.get(\"KitchenSpace\", \"\")\n}\n\nreturn [supabase_data]"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        944
      ],
      "id": "cf609e4b-1619-4f63-9d8e-b835447380b3",
      "name": "Prepare Supabase Data"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://wtqtnpjliyhcwxjkincj.supabase.co/rest/v1/quotations?on_conflict=quotation_id",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "sb_publishable_JejvEEqBVuaYhS_6otvYuA_djCMsv-1"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Prefer",
              "value": "resolution=merge-duplicates,return=minimal"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json) }}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -112,
        944
      ],
      "id": "021b8597-e300-44ff-9977-ca0c03f6b396",
      "name": "Save to Supabase"
    },
    {
      "parameters": {
        "path": "quotations-list",
        "responseMode": "responseNode",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        160,
        1136
      ],
      "id": "29404384-feb7-4987-af5d-ab8388d6b607",
      "name": "Get Quotations List"
    },
    {
      "parameters": {
        "url": "https://wtqtnpjliyhcwxjkincj.supabase.co/rest/v1/quotations?select=quotation_id,host_name,event_date,created_at&order=created_at.desc&limit=100",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "sb_publishable_JejvEEqBVuaYhS_6otvYuA_djCMsv-1"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        400,
        1136
      ],
      "id": "2eef3cb5-a669-4989-bad3-503e23073827",
      "name": "Fetch Quotations List"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        704,
        1136
      ],
      "id": "6496ce39-9660-4ae5-b6e5-7f1bc90dc159",
      "name": "Respond Quotations List"
    },
    {
      "parameters": {
        "path": "quotation-by-id",
        "responseMode": "responseNode",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        128,
        1376
      ],
      "id": "203f3096-04f5-42d8-a853-5218aaa98f16",
      "name": "Get Quotation By ID"
    },
    {
      "parameters": {
        "url": "=https://wtqtnpjliyhcwxjkincj.supabase.co/rest/v1/quotations?quotation_id=eq.{{ $json.query.id }}&limit=1",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "sb_publishable_JejvEEqBVuaYhS_6otvYuA_djCMsv-1"
            },
            {
              "name": "Authorization",
              "value": "<redacted-credential>"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        432,
        1376
      ],
      "id": "3b0fd852-38ec-4f82-969b-ed72559355cd",
      "name": "Fetch Quotation By ID"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Access-Control-Allow-Origin",
                "value": "*"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        720,
        1376
      ],
      "id": "373d3f4f-8853-44fe-9d11-413f4002f20d",
      "name": "Respond Quotation By ID"
    },
    {
      "parameters": {
        "content": "Dahi Cheeni quotation workflow\nForm: form.html\nPricing: Qty \u00d7 Rate\nRe-import this JSON after edits, then activate workflow.\npython -m http.server 8000",
        "height": 112,
        "width": 464
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "id": "b2574559-2d26-45f4-94af-19a08bb79aac",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "sendTo": "vishwashchauhan77@gmail.com",
        "subject": "hello",
        "message": "={{ $('Webhook Form').first().json.body.HostName }} - {{ $('Webhook Form').first().json.body.EventDate }}.pdf",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        864,
        800
      ],
      "id": "af8eac50-45fe-4359-950e-046ecfa523c8",
      "name": "Send a message",
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "disabled": true
    },
    {
      "parameters": {
        "content": "## Data Transformation ",
        "height": 1200,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -512,
        32
      ],
      "id": "b199ef9b-7b9c-4014-933b-831865ed0713",
      "name": "Sticky Note1"
    }
  ],
  "connections": {
    "Webhook Form": {
      "main": [
        [
          {
            "node": "Code in Python (Beta)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Menu Item Transformation",
            "type": "main",
            "index": 0
          },
          {
            "node": "Code in Python (Beta)13",
            "type": "main",
            "index": 0
          },
          {
            "node": "Customer Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Supabase Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in Python (Beta)": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Code in Python (Beta)13": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 3
          }
        ]
      ]
    },
    "Customer Details": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "JSON TO HTML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Menu Item Transformation": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "JSON TO HTML": {
      "main": [
        [
          {
            "node": "Convert to File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File": {
      "main": [
        [
          {
            "node": "HTML TO PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML TO PDF": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upload file",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Supabase Data": {
      "main": [
        []
      ]
    },
    "Get Quotations List": {
      "main": [
        [
          {
            "node": "Fetch Quotations List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Quotations List": {
      "main": [
        [
          {
            "node": "Respond Quotations List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Quotation By ID": {
      "main": [
        [
          {
            "node": "Fetch Quotation By ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Quotation By ID": {
      "main": [
        [
          {
            "node": "Respond Quotation 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.

Pro

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

About this workflow

Quotation-Workflow. Uses httpRequest, googleDrive, gmail. Webhook trigger; 23 nodes.

Source: https://github.com/Vishwash-chauhan/dc_quotation_maker/blob/9e2a249a1a0efdd1c8acfa570e29bcb5489c6b20/n8n/quotation-workflow.json — 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

Advanced AI Powered Document Parsing & Text Extraction with Llama Parse. Uses gmail, gmailTrigger, httpRequest, googleSheets. Webhook trigger; 54 nodes.

Gmail, Gmail Trigger, HTTP Request +3
Email & Gmail

Fireflies to Drive and Email (Unified). Uses httpRequest, googleDrive, gmail, moveBinaryData. Webhook trigger; 44 nodes.

HTTP Request, Google Drive, Gmail +1
Email & Gmail

Purchase Approval system. Uses gmail, googleSheets, httpRequest, googleDrive. Webhook trigger; 26 nodes.

Gmail, Google Sheets, HTTP Request +1
Email & Gmail

Streamline and standardize your entire client onboarding process with a single end-to-end automation. 🚀📋 This workflow captures detailed client intake data via webhook, automatically creates a fully s

Slack, Asana, HTTP Request +4
Email & Gmail

This workflow receives a webhook payload with a PDF URL, form field values, and an email address, then downloads the fillable PDF, fills it using PDFops, and emails the completed PDF via Gmail. Receiv

HTTP Request, N8N Nodes Pdfops, Gmail +1