AutomationFlowsAI & RAG › Send Ranked Freight Quote Pdfs with Gpt-4o, Google Sheets, Gmail and Pdfshift

Send Ranked Freight Quote Pdfs with Gpt-4o, Google Sheets, Gmail and Pdfshift

ByRahul Joshi @rahul08 on n8n.io

This workflow receives shipment requests via webhook, pulls carrier rate data from Google Sheets, uses OpenAI GPT-4o to generate a ranked HTML freight quote, converts it to a PDF with PDFShift, and emails the PDF to the customer via Gmail, with Slack alerts on workflow errors.…

Webhook trigger★★★★☆ complexityAI-powered20 nodesGoogle SheetsOpenAIHTTP RequestGmailSlackError Trigger
AI & RAG Trigger: Webhook Nodes: 20 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Error 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": "8Deu7DEmE7N3xZ3q",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Logistics Quoting Platform with Carrier Intelligence",
  "tags": [],
  "nodes": [
    {
      "id": "52097498-3d4c-45ad-b9c4-b38913802994",
      "name": "\ud83d\udccb Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        2384
      ],
      "parameters": {
        "color": 2,
        "width": 716,
        "height": 624,
        "content": "## \ud83d\udccb AI Freight Quote Comparator\n\nBrokers and freight teams waste hours building rate quotes manually from spreadsheets and carrier emails. This workflow eliminates that \u2014 a shipment request comes in and a ranked PDF quote goes out automatically, in minutes.\n\n### How it works\n1. A customer submits shipment details (origin, destination, weight, mode) via webhook\n2. The workflow simultaneously fetches rates from 3 carrier sheets in Google Sheets\n3. GPT-4o normalises the data and builds a ranked HTML comparison table\n4. PDFShift converts the HTML to a clean A4 PDF\n5. Gmail delivers the quote to the customer as an attachment\n\n### Setup steps\n1. Connect your **OpenAI** credential to the GPT-4o node\n2. Connect **Google Sheets OAuth2** \u2014 your sheet ID is already pre-filled\n3. Add your **PDFShift API key** to the Generate Quote PDF node header\n4. Connect **Gmail OAuth2** to the Send Quote Email node\n5. Click **Test Workflow** \u2014 demo shipment data is pinned on the webhook"
      },
      "typeVersion": 1
    },
    {
      "id": "b814dcf6-ea94-4957-983c-1dfba5e66c03",
      "name": "Section \u2013 Trigger & Extraction",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1696,
        2928
      ],
      "parameters": {
        "color": 7,
        "width": 548,
        "height": 484,
        "content": "## \ud83d\udce5 Trigger & Field Extraction\nWebhook receives the customer's shipment request. The Set node unpacks body fields into clean named variables used downstream.\n\nDemo data is pinned \u2014 hit **Test Workflow** to run without a live HTTP call."
      },
      "typeVersion": 1
    },
    {
      "id": "6514ddbc-9876-43ea-9268-56e580567f79",
      "name": "Section \u2013 Carrier Lookup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2288,
        2736
      ],
      "parameters": {
        "color": 7,
        "width": 796,
        "height": 860,
        "content": "## \ud83d\udd0d Carrier Rate Lookup\nThree Google Sheets reads run in parallel \u2014 one per carrier tab. The Merge node waits for all three before passing data forward.\n\nEach tab shares the same spreadsheet; only the sheet name differs per carrier."
      },
      "typeVersion": 1
    },
    {
      "id": "2d25d9c6-6c9a-4418-a502-7cb6c35384b6",
      "name": "Section \u2013 AI & PDF",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3136,
        2912
      ],
      "parameters": {
        "color": 7,
        "width": 840,
        "height": 612,
        "content": "## \ud83e\udd16 AI Quote Generation & PDF\nThe Code node structures shipment and carrier data into a clean JSON payload. GPT-4o receives this and returns a complete HTML quote page.\n\nPDFShift converts that HTML to an A4 PDF binary, which is passed directly to Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "70efbfa6-642a-4826-921e-f1da77f598b3",
      "name": "Section \u2013 Email Delivery",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4048,
        2912
      ],
      "parameters": {
        "color": 7,
        "width": 340,
        "height": 500,
        "content": "## \ud83d\udce7 Customer Delivery\nGmail sends the ranked PDF quote to the customer's email address. Subject and body auto-fill from the shipment data.\n\nThe quote is valid for 7 days \u2014 update the footer prompt in the GPT-4o node if needed."
      },
      "typeVersion": 1
    },
    {
      "id": "ae57aa1f-d52f-4ecf-8c4c-1f23ed6d7e97",
      "name": "\ud83d\udd10 Credentials & Security",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4160,
        3552
      ],
      "parameters": {
        "color": 3,
        "width": 340,
        "height": 296,
        "content": "## \ud83d\udd10 Credentials & Security\nRequires: OpenAI API key, Google Sheets OAuth2, PDFShift API key, Gmail OAuth2.\n\nDo not hardcode API keys. Use n8n credential store. Remove personal emails before sharing this template."
      },
      "typeVersion": 1
    },
    {
      "id": "1b48bae4-b1df-4cb2-93c6-f0a10b2b625c",
      "name": "Shipment Request Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1792,
        3200
      ],
      "parameters": {
        "path": "freight-quote-request",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2
    },
    {
      "id": "f7630b0b-16d7-4823-b270-fa6574da95a4",
      "name": "Extract Shipment Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        2064,
        3200
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "customer_name",
              "type": "string",
              "value": "={{ $json.body.customer_name }}"
            },
            {
              "id": "a2",
              "name": "customer_email",
              "type": "string",
              "value": "={{ $json.body.customer_email }}"
            },
            {
              "id": "a3",
              "name": "origin",
              "type": "string",
              "value": "={{ $json.body.origin }}"
            },
            {
              "id": "a4",
              "name": "destination",
              "type": "string",
              "value": "={{ $json.body.destination }}"
            },
            {
              "id": "a5",
              "name": "weight_kg",
              "type": "number",
              "value": "={{ $json.body.weight_kg }}"
            },
            {
              "id": "a6",
              "name": "mode",
              "type": "string",
              "value": "={{ $json.body.mode }}"
            },
            {
              "id": "a7",
              "name": "shipment_date",
              "type": "string",
              "value": "={{ $json.body.shipment_date }}"
            },
            {
              "id": "a8",
              "name": "cargo_type",
              "type": "string",
              "value": "={{ $json.body.cargo_type }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bc97cf95-54c0-4860-a7df-ae8259ffba29",
      "name": "Fetch BlueDart Rates",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2464,
        2976
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 2100629485,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit#gid=21+1234567890",
          "cachedResultName": "BlueDart_Rates"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit?usp=drivesdk",
          "cachedResultName": "Carrier Rate Sheets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "02c2c378-1a0c-4691-88bf-38686108d2c5",
      "name": "Fetch DTDC Rates",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2480,
        3216
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1842667957,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit#gid=1842667957",
          "cachedResultName": "DTDC_Rates"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit?usp=drivesdk",
          "cachedResultName": "Carrier Rate Sheets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "ca1aecdf-50c1-4153-be6f-2ae078303b2f",
      "name": "Fetch Delhivery Rates",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2480,
        3424
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 323178608,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit#gid=323178608",
          "cachedResultName": "Delhivery_Rates"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1qqsY3yqAMeZm13wrmJwcx08jzWm8zwCJrrWU-Q0KtIg/edit#gid=323178608",
          "cachedResultName": "Carrier Rate Sheets"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "107ab114-c7e5-44a1-ad3c-3df885c9819a",
      "name": "Merge Carrier Rates",
      "type": "n8n-nodes-base.merge",
      "position": [
        2768,
        3200
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3
    },
    {
      "id": "5a35b084-f2a2-4ae9-b188-fe1ea4206c76",
      "name": "Normalize & Structure Rate Data",
      "type": "n8n-nodes-base.code",
      "position": [
        2960,
        3200
      ],
      "parameters": {
        "jsCode": "const shipment = {\n  customer_name: $('Extract Shipment Fields').first().json.customer_name,\n  customer_email: $('Extract Shipment Fields').first().json.customer_email,\n  origin: $('Extract Shipment Fields').first().json.origin,\n  destination: $('Extract Shipment Fields').first().json.destination,\n  weight_kg: Number($('Extract Shipment Fields').first().json.weight_kg),\n  mode: $('Extract Shipment Fields').first().json.mode,\n  shipment_date: $('Extract Shipment Fields').first().json.shipment_date,\n  cargo_type: $('Extract Shipment Fields').first().json.cargo_type\n};\n\nconst carriers = [\n  {\n    carrier: 'BlueDart',\n    rate_per_kg: Number($('Fetch BlueDart Rates').first().json['Rate_Per_Kg']) || 0,\n    transit_days: $('Fetch BlueDart Rates').first().json['Transit_Days'] || 'N/A',\n    reliability_score: $('Fetch BlueDart Rates').first().json['Reliability_Score'] || 'N/A',\n    tracking: $('Fetch BlueDart Rates').first().json['Tracking'] || 'Yes',\n    insurance: $('Fetch BlueDart Rates').first().json['Insurance'] || 'Optional'\n  },\n  {\n    carrier: 'DTDC',\n    rate_per_kg: Number($('Fetch DTDC Rates').first().json['Rate_Per_Kg']) || 0,\n    transit_days: $('Fetch DTDC Rates').first().json['Transit_Days'] || 'N/A',\n    reliability_score: $('Fetch DTDC Rates').first().json['Reliability_Score'] || 'N/A',\n    tracking: $('Fetch DTDC Rates').first().json['Tracking'] || 'Yes',\n    insurance: $('Fetch DTDC Rates').first().json['Insurance'] || 'Optional'\n  },\n  {\n    carrier: 'Delhivery',\n    rate_per_kg: Number($('Fetch Delhivery Rates').first().json['Rate_Per_Kg']) || 0,\n    transit_days: $('Fetch Delhivery Rates').first().json['Transit_Days'] || 'N/A',\n    reliability_score: $('Fetch Delhivery Rates').first().json['Reliability_Score'] || 'N/A',\n    tracking: $('Fetch Delhivery Rates').first().json['Tracking'] || 'Yes',\n    insurance: $('Fetch Delhivery Rates').first().json['Insurance'] || 'Optional'\n  }\n];\n\nconst enrichedCarriers = carriers.map(c => ({\n  ...c,\n  total_cost: Math.round(c.rate_per_kg * shipment.weight_kg)\n}));\n\nreturn [{ json: { shipment, carriers: enrichedCarriers } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2e6651b9-1b10-4c2c-96a2-b081f31b7f60",
      "name": "GPT-4o Generate Quote HTML",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        3280,
        3200
      ],
      "parameters": {
        "resource": "chat"
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "ae5fc641-92a0-4a25-a442-9379b4b7297b",
      "name": "Prepare Quote Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        3584,
        3200
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b1",
              "name": "html_quote",
              "type": "string",
              "value": "={{ $json.message.content }}"
            },
            {
              "id": "b2",
              "name": "customer_name",
              "type": "string",
              "value": "={{ $('Normalize & Structure Rate Data').item.json.shipment.customer_name }}"
            },
            {
              "id": "b3",
              "name": "customer_email",
              "type": "string",
              "value": "={{ $('Normalize & Structure Rate Data').item.json.shipment.customer_email }}"
            },
            {
              "id": "b4",
              "name": "origin",
              "type": "string",
              "value": "={{ $('Normalize & Structure Rate Data').item.json.shipment.origin }}"
            },
            {
              "id": "b5",
              "name": "destination",
              "type": "string",
              "value": "={{ $('Normalize & Structure Rate Data').item.json.shipment.destination }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "06c19b70-50ed-4a3f-bc1e-cbb65c2a157b",
      "name": "Generate Quote PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3792,
        3200
      ],
      "parameters": {
        "url": "https://api.pdfshift.io/v3/convert/pdf",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "jsonBody": "={\n  \"source\": {{ JSON.stringify($json.html_quote) }},\n  \"sandbox\": true,\n  \"landscape\": false,\n  \"format\": \"A4\"\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "YOUR_PDFSHIFT_API_KEY_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2b749950-2f7c-4e51-a4c3-420fde850a79",
      "name": "Send Quote Email to Customer",
      "type": "n8n-nodes-base.gmail",
      "position": [
        4160,
        3200
      ],
      "parameters": {
        "sendTo": "={{ $('Prepare Quote Fields').item.json.customer_email }}",
        "message": "=<p>Dear {{ $('Prepare Quote Fields').item.json.customer_name }},</p><p>Please find your freight quote attached for your shipment from <strong>{{ $('Prepare Quote Fields').item.json.origin }}</strong> to <strong>{{ $('Prepare Quote Fields').item.json.destination }}</strong>.</p><p>The PDF contains a ranked comparison from BlueDart, DTDC, and Delhivery \u2014 best-value option highlighted in green.</p><p>This quote is valid for <strong>7 days</strong>. Reply to this email to confirm your booking.</p><p>Best regards,<br/><strong>FreightPro Quotation Team</strong><br/>support@freightpro-demo.com | +91-98765-43210</p>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Your Freight Quote \u2013 {{ $('Prepare Quote Fields').item.json.origin }} to {{ $('Prepare Quote Fields').item.json.destination }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "b536e1e8-5c8f-40ed-9f2a-a95ff565e30a",
      "name": "Slack \u2014 Send Workflow Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        2000,
        3872
      ],
      "parameters": {
        "text": "=error in the workflow please check ",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0AN1UGL0RM",
          "cachedResultName": "all-n8n-automations"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "513c3eb4-8dfa-4636-b526-cf93d7409975",
      "name": "On Workflow Error",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        1744,
        3872
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "90e3d541-5979-4999-bafc-4fb1083fcc27",
      "name": "Section: Error Handler",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1648,
        3696
      ],
      "parameters": {
        "color": 7,
        "width": 588,
        "height": 384,
        "content": "## \u26a0\ufe0f Error Handler\nCatches any failure in the workflow and posts a Slack alert. Wire the error output of critical nodes here to prevent silent failures going unnoticed."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "cd4365f6-0974-423a-8e19-03d10275f018",
  "nodeGroups": [],
  "connections": {
    "Fetch DTDC Rates": {
      "main": [
        [
          {
            "node": "Merge Carrier Rates",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "On Workflow Error": {
      "main": [
        [
          {
            "node": "Slack \u2014 Send Workflow Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Quote PDF": {
      "main": [
        [
          {
            "node": "Send Quote Email to Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Carrier Rates": {
      "main": [
        [
          {
            "node": "Normalize & Structure Rate Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch BlueDart Rates": {
      "main": [
        [
          {
            "node": "Merge Carrier Rates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Quote Fields": {
      "main": [
        [
          {
            "node": "Generate Quote PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Delhivery Rates": {
      "main": [
        [
          {
            "node": "Merge Carrier Rates",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Extract Shipment Fields": {
      "main": [
        [
          {
            "node": "Fetch BlueDart Rates",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch DTDC Rates",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Delhivery Rates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Shipment Request Webhook": {
      "main": [
        [
          {
            "node": "Extract Shipment Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GPT-4o Generate Quote HTML": {
      "main": [
        [
          {
            "node": "Prepare Quote Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize & Structure Rate Data": {
      "main": [
        [
          {
            "node": "GPT-4o Generate Quote HTML",
            "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

This workflow receives shipment requests via webhook, pulls carrier rate data from Google Sheets, uses OpenAI GPT-4o to generate a ranked HTML freight quote, converts it to a PDF with PDFShift, and emails the PDF to the customer via Gmail, with Slack alerts on workflow errors.…

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

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

This workflow captures new leads via webhook, enriches and scores them with Apollo and Google Gemini, logs everything in Google Sheets, and automates outreach, reply handling, follow-ups, meeting prep

HTTP Request, Google Gemini, Google Sheets +3
AI & RAG

This workflow ingests construction incident webhooks, normalizes the payload, and uses OpenAI GPT-4o-mini to classify each incident by type and urgency, then routes alerts to Slack and Gmail and logs

OpenAI, Slack, Gmail +2
AI & RAG

Automate your inbound lead qualification pipeline by enriching raw lead data, scoring it with AI, and instantly creating follow-up tasks for your sales team. 🎯🤖 This workflow receives new leads via we

OpenAI, HTTP Request, Asana +3
AI & RAG

This workflow automates the initial screening process for new job applications, freeing up your recruitment team to focus on qualified candidates. It receives applications from a webhook, uses OpenAI

HTTP Request, OpenAI, Google Sheets +2
AI & RAG

This system meticulously guides each lead through a fully automated journey, from initial contact to a personalized follow-up and CRM integration.

OpenAI, @Elevenlabs/N8N Nodes Elevenlabs, Google Drive +4