AutomationFlowsAI & RAG › Generate Vendor Negotiation Strategies From Pricing Data with Gpt-4 and Sendgrid

Generate Vendor Negotiation Strategies From Pricing Data with Gpt-4 and Sendgrid

ByOneclick AI Squad @oneclick-ai on n8n.io

This workflow ingests vendor pricing via a webhook or a weekly schedule, analyzes variance against historical and market benchmarks, uses OpenAI to draft negotiation strategies for high-priority cases, then emails recommendations through SendGrid and appends the analysis to a…

Webhook trigger★★★★☆ complexityAI-powered15 nodesAgentHTTP RequestOpenAI Chat
AI & RAG Trigger: Webhook Nodes: 15 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → HTTP Request 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": "DJmH7bvvHbbKYaQs",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Analyze vendor pricing and generate AI negotiation strategies via email",
  "tags": [],
  "nodes": [
    {
      "id": "e6fbc4ae-8de5-400f-a8ac-38c5dd499c61",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        80,
        -224
      ],
      "parameters": {
        "width": 980,
        "height": 1088,
        "content": "## AI-Powered Vendor Negotiation System\n\nThis workflow automates vendor pricing analysis and procurement cost reduction through intelligent negotiation recommendations. It ingests vendor pricing data, benchmarks it against historical and market rates, flags high-priority opportunities, and outputs structured negotiation strategies with confidence scores and projected savings.\n\n### Who's it for\n- Procurement teams managing 5+ vendors\n- Finance leads seeking cost reduction opportunities\n- Supply chain managers reviewing contract renewals\n- Operations teams benchmarking vendor performance\n\n### How it works\n1. Accepts vendor pricing data via webhook or weekly scheduled poll\n2. Normalizes and enriches the pricing context into a consistent schema\n3. Python node calculates price variance vs historical and market benchmarks, computes potential savings, and flags high-priority opportunities\n4. Filter passes through only high-priority opportunities for AI analysis\n5. AI generates a ranked negotiation strategy with tactics, target price, walk-away price, and risk flags\n6. The recommendation is emailed to the procurement team and logged to Google Sheets\n7. Webhook caller receives a confirmation response\n\n### How to set up\n1. Import this workflow into n8n\n2. Add credentials: OpenAI (or Anthropic), SendGrid, Google Sheets OAuth2\n3. Replace YOUR_SHEET_ID in the Google Sheets node with your actual Spreadsheet ID\n4. Replace both placeholder emails (sender and procurement recipient) in the SendGrid node\n5. Adjust the priority thresholds in the Python node to match your savings targets\n6. Activate the workflow\n\n### Requirements\n- Webhook endpoint or scheduled vendor data source\n- Google Sheets with OAuth2 credentials\n- SendGrid (or swap for the native Gmail node) for recommendation delivery\n- OpenAI / Anthropic API key\n\n### How to customize\n- Adjust the overpricing and savings thresholds in the Python node's `is_overpriced` and `is_material` checks\n- Tune the renewal urgency window (default: 60 days) to match your contract review cycle\n- Modify the AI prompt's tone, depth, or industry framing for your procurement category\n- Add more Google Sheet columns for extended tracking (e.g. vendor scorecards, past negotiation outcomes)\n- Add a Slack notification alongside the email for faster team visibility"
      },
      "typeVersion": 1
    },
    {
      "id": "d98b7d52-a165-4126-80b6-56c1e220ba00",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        -192
      ],
      "parameters": {
        "color": 4,
        "width": 760,
        "height": 756,
        "content": "## 1. Trigger & Intake\n\nAccepts new vendor pricing data via webhook POST, or polls a vendor pricing source every Monday at 8am as a fallback.\n\nThe Set node normalizes all incoming fields (price, volume, currency, renewal date, vendor contact) into one consistent schema regardless of which trigger fired."
      },
      "typeVersion": 1
    },
    {
      "id": "e1cfffbd-6dd9-42c1-b3b5-d85d47bfe581",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1952,
        -224
      ],
      "parameters": {
        "color": 4,
        "width": 820,
        "height": 864,
        "content": "## 2. Analysis & AI Recommendations\n\nThe Python node calculates how far the current price deviates from historical and market benchmarks, estimates maximum potential savings, assigns a confidence score, and flags whether this is a high-priority negotiation opportunity (factoring in both overpricing severity and contract renewal urgency).\n\nOnly high-priority opportunities pass the filter. A short wait buffer respects API rate limits before the AI node generates a structured negotiation strategy: tactics, target price, walk-away price, projected savings range, and risk flags."
      },
      "typeVersion": 1
    },
    {
      "id": "404dac0e-d36d-4da3-a99a-567f60fe8b4b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2800,
        -208
      ],
      "parameters": {
        "color": 4,
        "width": 980,
        "height": 824,
        "content": "## 3. Send & Track\n\nThe AI's negotiation strategy is formatted into a priority-labeled email and sent to the procurement team via SendGrid, with the projected savings amount in the subject line for quick triage.\n\nEvery analyzed opportunity \u2014 high priority or not \u2014 should be logged to the Google Sheets tracker for historical reference and negotiation outcome tracking over time."
      },
      "typeVersion": 1
    },
    {
      "id": "3881d309-f218-4a64-bcf7-47d2cb5564b1",
      "name": "Webhook - New Vendor Pricing",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1312,
        192
      ],
      "parameters": {
        "path": "vendor-pricing-inbound",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 1.1
    },
    {
      "id": "9bffa67f-1f7c-431d-aa65-31ef6f518366",
      "name": "Poll Vendor Pricing Weekly",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1312,
        384
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 1"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b0427b4a-00d7-4c37-aa51-c0bce89a0643",
      "name": "Prepare Vendor Pricing Context",
      "type": "n8n-nodes-base.set",
      "position": [
        1552,
        288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "name": "vendorName",
              "type": "string",
              "value": "={{ $json.vendorName || $json.body?.vendorName || 'Unknown Vendor' }}"
            },
            {
              "name": "vendorCategory",
              "type": "string",
              "value": "={{ $json.vendorCategory || $json.body?.vendorCategory || 'General' }}"
            },
            {
              "name": "currentUnitPrice",
              "type": "number",
              "value": "={{ $json.currentUnitPrice || $json.body?.currentUnitPrice || 0 }}"
            },
            {
              "name": "historicalAvgPrice",
              "type": "number",
              "value": "={{ $json.historicalAvgPrice || $json.body?.historicalAvgPrice || 0 }}"
            },
            {
              "name": "marketBenchmarkPrice",
              "type": "number",
              "value": "={{ $json.marketBenchmarkPrice || $json.body?.marketBenchmarkPrice || 0 }}"
            },
            {
              "name": "contractVolume",
              "type": "number",
              "value": "={{ $json.contractVolume || $json.body?.contractVolume || 1 }}"
            },
            {
              "name": "contractCurrency",
              "type": "string",
              "value": "={{ $json.contractCurrency || $json.body?.contractCurrency || 'USD' }}"
            },
            {
              "name": "renewalDate",
              "type": "string",
              "value": "={{ $json.renewalDate || $json.body?.renewalDate || '' }}"
            },
            {
              "name": "vendorContact",
              "type": "string",
              "value": "={{ $json.vendorContact || $json.body?.vendorContact || '' }}"
            },
            {
              "name": "additionalNotes",
              "type": "string",
              "value": "={{ $json.additionalNotes || $json.body?.additionalNotes || '' }}"
            },
            {
              "name": "submissionId",
              "type": "string",
              "value": "={{ $json.submissionId || Date.now().toString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c14503f3-0ca1-48cc-a4ec-6a9de8caee9c",
      "name": "Python - Analyze Pricing & Flag Opportunities",
      "type": "n8n-nodes-base.code",
      "position": [
        1760,
        288
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "language": "pythonNative",
        "pythonCode": "item = _input.item['json']\n\ncurrent_price    = float(item.get('currentUnitPrice', 0) or 0)\nhistorical_price  = float(item.get('historicalAvgPrice', 0) or 0)\nmarket_price      = float(item.get('marketBenchmarkPrice', 0) or 0)\nvolume            = float(item.get('contractVolume', 1) or 1)\n\n# --- Percentage difference vs historical and market ---\ndef pct_diff(current, baseline):\n    if baseline == 0:\n        return 0.0\n    return round(((current - baseline) / baseline) * 100, 2)\n\nprice_vs_historical_pct = pct_diff(current_price, historical_price)\nprice_vs_market_pct     = pct_diff(current_price, market_price)\n\n# --- Determine the best available reference price for savings calc ---\nreference_prices = [p for p in [historical_price, market_price] if p > 0]\nbest_reference_price = min(reference_prices) if reference_prices else current_price\n\n# --- Max potential savings (only if current price is above reference) ---\nunit_savings = max(0.0, current_price - best_reference_price)\nmax_potential_savings = round(unit_savings * volume, 2)\n\n# --- Confidence score (0.0\u20131.0) ---\n# Higher confidence when both historical AND market data exist, and the\n# overpricing signal is consistent across both sources.\nconfidence_score = 0.3\nif historical_price > 0:\n    confidence_score += 0.3\nif market_price > 0:\n    confidence_score += 0.3\nif price_vs_historical_pct > 0 and price_vs_market_pct > 0:\n    confidence_score += 0.1  # consistent overpricing signal across sources\nconfidence_score = round(min(confidence_score, 1.0), 2)\n\n# --- Priority flag ---\n# High priority if overpriced by 10%+ vs either benchmark AND savings are material\nis_overpriced = price_vs_historical_pct >= 10 or price_vs_market_pct >= 10\nis_material   = max_potential_savings >= 1000\n\nis_high_priority = is_overpriced and is_material\n\n# --- Days until renewal (renewal urgency signal) ---\ndays_until_renewal = None\nrenewal_date_str = item.get('renewalDate', '')\nif renewal_date_str:\n    try:\n        from datetime import datetime\n        renewal_dt = datetime.fromisoformat(renewal_date_str[:10])\n        days_until_renewal = (renewal_dt - datetime.now()).days\n    except Exception:\n        days_until_renewal = None\n\nis_renewal_urgent = days_until_renewal is not None and 0 <= days_until_renewal <= 60\n\n# --- Bump priority if renewal is urgent, even with smaller savings ---\nif is_renewal_urgent and max_potential_savings >= 500:\n    is_high_priority = True\n\nreturn {\n    'json': {\n        **item,\n        'priceVsHistoricalPct': price_vs_historical_pct,\n        'priceVsMarketPct': price_vs_market_pct,\n        'maxPotentialSavings': max_potential_savings,\n        'confidenceScore': confidence_score,\n        'isHighPriority': is_high_priority,\n        'isOverpriced': is_overpriced,\n        'daysUntilRenewal': days_until_renewal,\n        'isRenewalUrgent': is_renewal_urgent,\n        'analyzedAt': __import__('datetime').datetime.now().isoformat()\n    }\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "2c748f83-3e9b-432c-8058-67f6677c8ab3",
      "name": "Filter High-Priority Opportunities",
      "type": "n8n-nodes-base.filter",
      "position": [
        2032,
        288
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "true"
              },
              "leftValue": "={{ $json.isHighPriority }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c730e5ab-0c07-4162-9f26-364c932aa474",
      "name": "AI - Generate Negotiation Strategy",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2496,
        288
      ],
      "parameters": {
        "text": "=You are an expert procurement strategist and vendor negotiation advisor. Analyze the following vendor pricing data and generate a structured negotiation strategy.\n\n---\n\n**Vendor:** {{ $json.vendorName }}\n**Category:** {{ $json.vendorCategory }}\n**Current Unit Price:** {{ $json.contractCurrency }} {{ $json.currentUnitPrice }}\n**Historical Average Price:** {{ $json.contractCurrency }} {{ $json.historicalAvgPrice }}\n**Market Benchmark Price:** {{ $json.contractCurrency }} {{ $json.marketBenchmarkPrice }}\n**Contract Volume:** {{ $json.contractVolume }} units\n**Price vs Historical (%):** {{ $json.priceVsHistoricalPct }}%\n**Price vs Market (%):** {{ $json.priceVsMarketPct }}%\n**Max Potential Savings:** {{ $json.contractCurrency }} {{ $json.maxPotentialSavings }}\n**Contract Renewal Date:** {{ $json.renewalDate }}\n**Confidence Score:** {{ $json.confidenceScore }}\n**Additional Notes:** {{ $json.additionalNotes }}\n\n---\n\nProvide your response in this exact format:\n\n**NEGOTIATION PRIORITY:** [HIGH / MEDIUM / LOW]\n\n**EXECUTIVE SUMMARY:**\n(2-3 sentence overview of the situation and opportunity)\n\n**TOP 3 NEGOTIATION TACTICS:**\n1. [Tactic name]: [Description and how to execute it, 1-2 sentences]\n2. [Tactic name]: [Description and how to execute it, 1-2 sentences]\n3. [Tactic name]: [Description and how to execute it, 1-2 sentences]\n\n**PROJECTED SAVINGS RANGE:** {{ $json.contractCurrency }} [Low estimate] \u2013 {{ $json.contractCurrency }} [High estimate] annually\n\n**RECOMMENDED TARGET PRICE:** {{ $json.contractCurrency }} [Target price per unit]\n\n**WALK-AWAY PRICE:** {{ $json.contractCurrency }} [Maximum acceptable unit price]\n\n**RISK FLAGS:**\n- [Any risks, vendor dependencies, or caution points]\n\n**CONFIDENCE SCORE:** {{ $json.confidenceScore }} / 1.0\n\nKeep the full response under 300 words. Be direct, data-driven, and actionable.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 1.6
    },
    {
      "id": "3e4076e7-0a13-4221-902d-dd417940e3ee",
      "name": "JS - Format Negotiation Report",
      "type": "n8n-nodes-base.code",
      "position": [
        2928,
        288
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $input.item.json;\nconst today = new Date().toISOString().split('T')[0];\nconst savings = item.maxPotentialSavings || 0;\nconst priority = savings > 20000 ? 'HIGH' : savings > 5000 ? 'MEDIUM' : 'LOW';\n\nreturn {\n  json: {\n    ...item,\n    negotiationStrategy: item.response || item.text || 'Strategy generation failed. Please retry.',\n    overallPriority: priority,\n    reportDate: today,\n    status: 'Recommendation Sent',\n    formattedSavings: new Intl.NumberFormat('en-US', { style: 'currency', currency: item.contractCurrency || 'USD' }).format(savings)\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "f5c19b75-8d58-4296-95ef-71a80e3abdfb",
      "name": "Send Negotiation Recommendation",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3296,
        192
      ],
      "parameters": {
        "url": "https://api.sendgrid.com/v3/mail/send",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"personalizations\": [{\"to\": [{\"email\": \"procurement@yourcompany.com\"}]}],\n  \"from\": {\"email\": \"your-email@yourcompany.com\", \"name\": \"Vendor Negotiation AI\"},\n  \"subject\": \"[{{ $json.overallPriority }} PRIORITY] Negotiation Strategy: {{ $json.vendorName }} \u2014 Potential Savings {{ $json.formattedSavings }}\",\n  \"content\": [{\"type\": \"text/plain\", \"value\": \"Vendor Negotiation Recommendation\\n\\nVendor: {{ $json.vendorName }}\\nCategory: {{ $json.vendorCategory }}\\nReport Date: {{ $json.reportDate }}\\nMax Potential Savings: {{ $json.formattedSavings }}\\n\\n{{ $json.negotiationStrategy }}\\n\\n---\\nGenerated by AI Vendor Negotiation System\\nConfidence Score: {{ $json.confidenceScore }}\"}]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "463666ae-4572-450c-bf45-96ea35ad8d26",
      "name": "Update Vendor Negotiation Tracker",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3296,
        384
      ],
      "parameters": {
        "url": "https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/VendorNegotiations!A1:append?valueInputOption=USER_ENTERED",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"values\": [[\n    \"{{ $json.reportDate }}\",\n    \"{{ $json.vendorName }}\",\n    \"{{ $json.vendorCategory }}\",\n    \"{{ $json.currentUnitPrice }}\",\n    \"{{ $json.historicalAvgPrice }}\",\n    \"{{ $json.marketBenchmarkPrice }}\",\n    \"{{ $json.priceVsHistoricalPct }}%\",\n    \"{{ $json.priceVsMarketPct }}%\",\n    \"{{ $json.formattedSavings }}\",\n    \"{{ $json.overallPriority }}\",\n    \"{{ $json.confidenceScore }}\",\n    \"{{ $json.renewalDate }}\",\n    \"{{ $json.status }}\",\n    \"{{ new Date().toISOString() }}\"\n  ]]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2
    },
    {
      "id": "acff594a-2ae1-4597-a7b4-642de70adbbc",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2368,
        496
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "9c0bffff-1145-4cd6-b326-0b3f431595b2",
      "name": "Wait - Rate Limit",
      "type": "n8n-nodes-base.wait",
      "position": [
        2272,
        288
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d9475d4b-bf16-4d98-a98d-f9fb2daff19c",
  "connections": {
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI - Generate Negotiation Strategy",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Wait - Rate Limit": {
      "main": [
        [
          {
            "node": "AI - Generate Negotiation Strategy",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Poll Vendor Pricing Weekly": {
      "main": [
        [
          {
            "node": "Prepare Vendor Pricing Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - New Vendor Pricing": {
      "main": [
        [
          {
            "node": "Prepare Vendor Pricing Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JS - Format Negotiation Report": {
      "main": [
        [
          {
            "node": "Send Negotiation Recommendation",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update Vendor Negotiation Tracker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Vendor Pricing Context": {
      "main": [
        [
          {
            "node": "Python - Analyze Pricing & Flag Opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI - Generate Negotiation Strategy": {
      "main": [
        [
          {
            "node": "JS - Format Negotiation Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter High-Priority Opportunities": {
      "main": [
        [
          {
            "node": "Wait - Rate Limit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Python - Analyze Pricing & Flag Opportunities": {
      "main": [
        [
          {
            "node": "Filter High-Priority Opportunities",
            "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 ingests vendor pricing via a webhook or a weekly schedule, analyzes variance against historical and market benchmarks, uses OpenAI to draft negotiation strategies for high-priority cases, then emails recommendations through SendGrid and appends the analysis to a…

Source: https://n8n.io/workflows/16737/ — 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

VEP WAPP. Uses openAi, lmChatOpenAi, toolCalculator, agent. Webhook trigger; 100 nodes.

OpenAI, OpenAI Chat, Tool Calculator +7
AI & RAG

⏺ 🚀 How it works

Agent, Anthropic Chat, Output Parser Structured +6
AI & RAG

L&D_AgentsAI_ATIVO. Uses httpRequest, agent, googleCalendarTool, toolSerpApi. Webhook trigger; 93 nodes.

HTTP Request, Agent, Google Calendar Tool +9
AI & RAG

AI Customer Service Automation - Portfolio. Uses googleSheets, httpRequest, agent, memoryBufferWindow. Webhook trigger; 91 nodes.

Google Sheets, HTTP Request, Agent +9
AI & RAG

CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.

Postgres, Mcp Client Tool, Google Drive Tool +14