AutomationFlowsData & Sheets › Generate Tender Eligibility Summaries and Bid Checklists with Gemini and…

Generate Tender Eligibility Summaries and Bid Checklists with Gemini and…

Original n8n title: Generate Tender Eligibility Summaries and Bid Checklists with Gemini and Google Sheets

ByWeblineIndia @weblineindia on n8n.io

This scheduled workflow ingests tender records, checks Google Sheets and Supabase for duplicates, uses Google Gemini to generate an eligibility summary, match score, and bid checklist, then stores the tender and checklist data and alerts the team via Slack and Gmail. Runs on a…

Cron / scheduled trigger★★★★☆ complexityAI-powered27 nodesGoogle SheetsSupabaseGoogle GeminiSlackGmail
Data & Sheets Trigger: Cron / scheduled Nodes: 27 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Gmail → Googlegemini 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": "3TLdxf36ZG9YRAki",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Tender Alert to Bid Checklist Generator",
  "tags": [],
  "nodes": [
    {
      "id": "712a39a7-f381-45f7-9b1c-02d03b54f330",
      "name": "Trigger Tender Monitoring Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -464,
        -16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "97e2670c-81ca-487d-8eb1-2aedad356a23",
      "name": "Seed Dummy Tender Dataset",
      "type": "n8n-nodes-base.set",
      "position": [
        -256,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "5ef8ee96-3f95-4c02-9d14-500f9f308299",
              "name": "data",
              "type": "array",
              "value": "=[\n  {\n    \"tender_id\": \"TDR-1001\",\n    \"source_name\": \"Dummy Tender API\",\n    \"tender_title\": \"Road Maintenance Work for District Zone A\",\n    \"tender_description\": \"Contract for periodic road repair, resurfacing, and safety signage installation.\",\n    \"authority_name\": \"Urban Infrastructure Department\",\n    \"category\": \"Infrastructure\",\n    \"state\": \"Gujarat\",\n    \"city\": \"Ahmedabad\",\n    \"published_date\": \"2026-05-12T09:00:00Z\",\n    \"bid_due_date\": \"2026-05-22T17:00:00Z\",\n    \"estimated_value\": 2500000,\n    \"emd_amount\": 50000,\n    \"document_fee\": 2500,\n    \"source_url\": \"https://example.com/tenders/TDR-1001\",\n    \"pdf_url\": \"https://example.com/tenders/TDR-1001.pdf\"\n  },\n  {\n    \"tender_id\": \"TDR-1002\",\n    \"source_name\": \"Dummy Tender API\",\n    \"tender_title\": \"Supply of Medical Equipment for Civil Hospital\",\n    \"tender_description\": \"Procurement of monitoring devices, ICU support equipment, and accessories.\",\n    \"authority_name\": \"State Health Procurement Cell\",\n    \"category\": \"Healthcare\",\n    \"state\": \"Gujarat\",\n    \"city\": \"Ahmedabad\",\n    \"published_date\": \"2026-05-12T10:00:00Z\",\n    \"bid_due_date\": \"2026-05-25T17:00:00Z\",\n    \"estimated_value\": 7200000,\n    \"emd_amount\": 100000,\n    \"document_fee\": 5000,\n    \"source_url\": \"https://example.com/tenders/TDR-1002\",\n    \"pdf_url\": \"https://example.com/tenders/TDR-1002.pdf\"\n  }\n]"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "57340c85-e5b8-46e4-b4d8-df9dc414c1ff",
      "name": "Normalize Tender Records",
      "type": "n8n-nodes-base.code",
      "position": [
        -48,
        -16
      ],
      "parameters": {
        "jsCode": "const records = $input.first().json.data || [];\nreturn records.map(record => ({ json: record }));"
      },
      "typeVersion": 2
    },
    {
      "id": "bf8f4a5c-5064-4665-8407-51ad136c6143",
      "name": "Enrich Tender Metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        256,
        -16
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "5e122db4-cca3-43b7-a64d-4fff0f07a6dc",
              "name": "duplicate_key",
              "type": "string",
              "value": "={{ $json.tender_id + \"_\" + $json.bid_due_date }}"
            },
            {
              "id": "28ffb757-feb6-4532-b570-67e88af83445",
              "name": "checklist_status",
              "type": "string",
              "value": "Pending"
            },
            {
              "id": "5d88f112-6ac3-4041-8df6-782f5d03fda1",
              "name": "match_score",
              "type": "number",
              "value": 0
            },
            {
              "id": "1685ad71-0369-4460-9624-5bc8c14a71a5",
              "name": "alert_sent",
              "type": "string",
              "value": "false"
            },
            {
              "id": "1b5a42a0-13f3-4a9e-aac9-b15356f9c89b",
              "name": "created_at",
              "type": "string",
              "value": "= {{ $now }}"
            },
            {
              "id": "4ed06ce3-bf01-4978-b167-b4604ed61167",
              "name": "updated_at",
              "type": "string",
              "value": "={{ $now }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "429fffde-fe3e-486e-b8e0-bd29f846df13",
      "name": "Lookup Tender in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        496,
        -112
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.duplicate_key }}",
              "lookupColumn": "duplicate_key"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit#gid=0",
          "cachedResultName": "Tender Master"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit?usp=drivesdk",
          "cachedResultName": "Tender Monitoring System"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "b4a62dad-77ff-4de7-8014-002abf19f7b3",
      "name": "Lookup Tender in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        496,
        96
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "duplicate_key",
              "keyValue": "={{ $json.duplicate_key }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "tenders",
        "operation": "getAll"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "ce9929f6-ee29-45fc-9626-3a743f319442",
      "name": "Consolidate Duplicate Check Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        880,
        0
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2,
      "alwaysOutputData": true
    },
    {
      "id": "1e8372db-54d9-4641-ad35-262684ee489d",
      "name": "Filter New Tender Records",
      "type": "n8n-nodes-base.if",
      "position": [
        1120,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a76d7ea0-2275-4581-91e1-9c78f8808ee2",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('Consolidate Duplicate Check Results').item.json.isEmpty() }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "8ccdb1a8-d453-4747-bba4-999cbf911675",
      "name": "Build AI Tender Analysis Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        1424,
        -16
      ],
      "parameters": {
        "jsCode": "const inputItems = $('Normalize Tender Records').all();\n\nreturn inputItems.map((item) => {\n  const tender = item.json;\n\n  const ai_input_text = `\nTender ID: ${tender.tender_id || \"\"}\nTitle: ${tender.tender_title || \"\"}\nDescription: ${tender.tender_description || \"\"}\nAuthority: ${tender.authority_name || \"\"}\nCategory: ${tender.category || \"\"}\nState: ${tender.state || \"\"}\nCity: ${tender.city || \"\"}\nPublished Date: ${tender.published_date || \"\"}\nBid Due Date: ${tender.bid_due_date || \"\"}\nEstimated Value: ${tender.estimated_value || \"\"}\nEMD Amount: ${tender.emd_amount || \"\"}\nDocument Fee: ${tender.document_fee || \"\"}\nSource URL: ${tender.source_url || \"\"}\nPDF URL: ${tender.pdf_url || \"\"}\n\nReturn strictly in JSON format with these top level keys only:\neligibility_summary\nai_summary\nchecklist_items\nmatch_score\n\nRules:\n1. eligibility_summary must be a short clear summary of likely eligibility requirements based on the tender details.\n2. ai_summary must be a short business summary for bid preparation.\n3. checklist_items must be an array of objects.\n4. Each checklist_items object must contain:\n   task_name\n   task_description\n   priority\n   due_date\n   owner\n   status\n   notes\n5. match_score must be a number from 1 to 100.\n6. Do not include markdown.\n7. Do not include code fences.\n8. Do not include any text before or after the JSON.\n`.trim();\n\n  return {\n    json: {\n      tender_id: tender.tender_id || \"\",\n      source_name: tender.source_name || \"\",\n      tender_title: tender.tender_title || \"\",\n      tender_description: tender.tender_description || \"\",\n      authority_name: tender.authority_name || \"\",\n      category: tender.category || \"\",\n      state: tender.state || \"\",\n      city: tender.city || \"\",\n      published_date: tender.published_date || \"\",\n      bid_due_date: tender.bid_due_date || \"\",\n      estimated_value: tender.estimated_value || 0,\n      emd_amount: tender.emd_amount || 0,\n      document_fee: tender.document_fee || 0,\n      source_url: tender.source_url || \"\",\n      pdf_url: tender.pdf_url || \"\",\n      duplicate_key: `${tender.tender_id || \"\"}_${tender.bid_due_date || \"\"}`,\n      checklist_status: \"Pending\",\n      alert_sent: false,\n      created_at: new Date().toISOString(),\n      updated_at: new Date().toISOString(),\n      ai_input_text\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "17b5effb-c7c5-4dc8-b96b-2a847bcaf66d",
      "name": "Generate Tender Eligibility and Bid Checklist",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        1648,
        -112
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {
          "systemMessage": "=You are a tender analysis assistant.\nRead the tender data and produce:\neligibility_summary,\nai_summary,\nmatch_score,\nchecklist_items.\nChecklist items must be practical bid preparation tasks.\nReturn clean JSON only."
        },
        "messages": {
          "values": [
            {
              "content": "={{ $json.ai_input_text }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "74ee6548-4616-4ca7-ae0c-90980a1d0558",
      "name": "Parse AI Tender Analysis Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1984,
        -112
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\n\nreturn items.map((item) => {\n  const rawText = item.json.content?.parts?.[0]?.text || \"{}\";\n\n  let parsed;\n  try {\n    parsed = JSON.parse(rawText);\n  } catch (error) {\n    parsed = {\n      eligibility_summary: \"\",\n      ai_summary: \"\",\n      match_score: 0,\n      checklist_items: [],\n      parsing_error: error.message,\n      raw_output: rawText\n    };\n  }\n\n  return {\n    json: {\n      ...item.json,\n      eligibility_summary: parsed.eligibility_summary || \"\",\n      ai_summary: parsed.ai_summary || \"\",\n      match_score: parsed.match_score || 0,\n      checklist_items: Array.isArray(parsed.checklist_items) ? parsed.checklist_items : [],\n      raw_ai_output: rawText\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "4af1cf96-684e-4831-974a-71e5b0de836e",
      "name": "Combine Tender Source and AI Analysis",
      "type": "n8n-nodes-base.merge",
      "position": [
        2336,
        -32
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "f1579af0-c66b-4817-a320-5e7285a00746",
      "name": "Create Tender Master Row in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2496,
        -224
      ],
      "parameters": {
        "columns": {
          "value": {
            "city": "={{ $json.city }}",
            "state": "={{ $json.state }}",
            "pdf_url": "={{ $json.pdf_url }}",
            "category": "={{ $json.category }}",
            "tender_id": "={{ $json.tender_id }}",
            "ai_summary": "={{ $json.ai_summary }}",
            "alert_sent": "={{ $json.alert_sent }}",
            "created_at": "={{ $json.created_at }}",
            "emd_amount": "={{ $json.emd_amount }}",
            "source_url": "={{ $json.source_url }}",
            "updated_at": "={{ $json.updated_at }}",
            "match_score": "={{ $json.match_score }}",
            "source_name": "={{ $json.source_name }}",
            "bid_due_date": "={{ $json.bid_due_date }}",
            "document_fee": "={{ $json.document_fee }}",
            "tender_title": "={{ $json.tender_title }}",
            "duplicate_key": "={{ $json.duplicate_key }}",
            "authority_name": "={{ $json.authority_name }}",
            "published_date": "={{ $json.published_date }}",
            "estimated_value": "={{ $json.estimated_value }}",
            "checklist_status": "={{ $json.checklist_items }}",
            "tender_description": "={{ $json.tender_description }}",
            "eligibility_summary": "={{ $json.eligibility_summary }}"
          },
          "schema": [
            {
              "id": "tender_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tender_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "source_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "source_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tender_title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tender_title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tender_description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tender_description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "authority_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "authority_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "state",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "state",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "city",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "city",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "published_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "published_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "bid_due_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "bid_due_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "estimated_value",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "estimated_value",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "emd_amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "emd_amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "document_fee",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "document_fee",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "eligibility_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "eligibility_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ai_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "checklist_status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checklist_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "source_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "source_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "pdf_url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "pdf_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "duplicate_key",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "duplicate_key",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "match_score",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "match_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "alert_sent",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "alert_sent",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "updated_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "updated_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit#gid=0",
          "cachedResultName": "Tender Master"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit?usp=drivesdk",
          "cachedResultName": "Tender Monitoring System"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "03a8d91a-07b4-4192-974a-deaf45806f19",
      "name": "Create Tender Master Record in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2736,
        -144
      ],
      "parameters": {
        "tableId": "tenders",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "tender_id",
              "fieldValue": "={{ $json.tender_id }}"
            },
            {
              "fieldId": "source_name",
              "fieldValue": "={{ $json.source_name }}"
            },
            {
              "fieldId": "tender_title",
              "fieldValue": "={{ $json.tender_title }}"
            },
            {
              "fieldId": "tender_description",
              "fieldValue": "={{ $json.tender_description }}"
            },
            {
              "fieldId": "authority_name",
              "fieldValue": "={{ $json.authority_name }}"
            },
            {
              "fieldId": "category",
              "fieldValue": "={{ $json.category }}"
            },
            {
              "fieldId": "state",
              "fieldValue": "={{ $json.state }}"
            },
            {
              "fieldId": "city",
              "fieldValue": "={{ $json.city }}"
            },
            {
              "fieldId": "published_date",
              "fieldValue": "={{ $json.published_date }}"
            },
            {
              "fieldId": "bid_due_date",
              "fieldValue": "={{ $json.bid_due_date }}"
            },
            {
              "fieldId": "estimated_value",
              "fieldValue": "={{ $json.estimated_value }}"
            },
            {
              "fieldId": "emd_amount",
              "fieldValue": "={{ $json.emd_amount }}"
            },
            {
              "fieldId": "document_fee",
              "fieldValue": "={{ $json.document_fee }}"
            },
            {
              "fieldId": "source_url",
              "fieldValue": "={{ $json.source_url }}"
            },
            {
              "fieldId": "pdf_url",
              "fieldValue": "={{ $json.pdf_url }}"
            },
            {
              "fieldId": "duplicate_key",
              "fieldValue": "={{ $json.duplicate_key }}"
            },
            {
              "fieldId": "checklist_status",
              "fieldValue": "={{ $json.checklist_status }}"
            },
            {
              "fieldId": "alert_sent",
              "fieldValue": "={{ $json.alert_sent }}"
            },
            {
              "fieldId": "created_at",
              "fieldValue": "={{ $json.created_at }}"
            },
            {
              "fieldId": "updated_at",
              "fieldValue": "={{ $json.updated_at }}"
            },
            {
              "fieldId": "eligibility_summary",
              "fieldValue": "={{ $json.eligibility_summary }}"
            },
            {
              "fieldId": "ai_summary",
              "fieldValue": "={{ $json.ai_summary }}"
            },
            {
              "fieldId": "match_score",
              "fieldValue": "={{ $json.match_score }}"
            },
            {
              "fieldId": "checklist_status",
              "fieldValue": "={{ $json.checklist_items }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "76f6cbff-7e04-4fdd-9b44-fce137799176",
      "name": "Flatten Bid Checklist Line Items",
      "type": "n8n-nodes-base.code",
      "position": [
        2496,
        128
      ],
      "parameters": {
        "jsCode": "const inputItems = $input.all();\nconst output = [];\n\nfor (const item of inputItems) {\n  const tender = item.json;\n  const checklistItems = Array.isArray(tender.checklist_items) ? tender.checklist_items : [];\n\n  checklistItems.forEach((checklist, index) => {\n    output.push({\n      json: {\n        checklist_id: `${tender.tender_id}-CHK-${index + 1}`,\n        tender_id: tender.tender_id || \"\",\n        tender_title: tender.tender_title || \"\",\n        authority_name: tender.authority_name || \"\",\n        category: tender.category || \"\",\n        source_url: tender.source_url || \"\",\n        pdf_url: tender.pdf_url || \"\",\n        bid_due_date: tender.bid_due_date || \"\",\n        task_name: checklist.task_name || \"\",\n        task_description: checklist.task_description || \"\",\n        owner: checklist.owner || \"Bid Team\",\n        priority: checklist.priority || \"Medium\",\n        due_date: checklist.due_date || tender.bid_due_date || \"\",\n        status: checklist.status || \"Pending\",\n        notes: checklist.notes || \"\",\n        created_at: new Date().toISOString()\n      }\n    });\n  });\n}\n\nreturn output;"
      },
      "typeVersion": 2
    },
    {
      "id": "e7e62e29-15a9-43d4-b328-0e7f565d7168",
      "name": "Create Checklist Rows in Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2736,
        48
      ],
      "parameters": {
        "columns": {
          "value": {
            "notes": "={{ $json.notes }}",
            "owner": "={{ $json.owner }}",
            "status": "={{ $json.status }}",
            "due_date": "={{ $json.due_date }}",
            "priority": "={{ $json.priority }}",
            "task_name": "={{ $json.task_name }}",
            "tender_id": "={{ $json.tender_id }}",
            "created_at": "={{ $json.created_at }}",
            "checklist_id": "={{ $json.checklist_id }}",
            "task_description": "={{ $json.task_description }}"
          },
          "schema": [
            {
              "id": "checklist_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checklist_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tender_id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "tender_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "task_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "task_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "task_description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "task_description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "owner",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "owner",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "priority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "priority",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "due_date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "due_date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "notes",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1576668866,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit#gid=1576668866",
          "cachedResultName": "Bid Checklist"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1W6s_v9tMB2qf50kStS5K-m8sgU8ZgOZ7OqV9vkIozeg/edit?usp=drivesdk",
          "cachedResultName": "Tender Monitoring System"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d1673c2d-192c-41a4-a6f0-0d95b01c430a",
      "name": "Create Checklist Rows in Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2736,
        240
      ],
      "parameters": {
        "tableId": "tender_checklists",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "checklist_id",
              "fieldValue": "={{ $json.checklist_id }}"
            },
            {
              "fieldId": "tender_id",
              "fieldValue": "={{ $json.tender_id }}"
            },
            {
              "fieldId": "task_name",
              "fieldValue": "={{ $json.task_name }}"
            },
            {
              "fieldId": "task_description",
              "fieldValue": "={{ $json.task_description }}"
            },
            {
              "fieldId": "owner",
              "fieldValue": "={{ $json.owner }}"
            },
            {
              "fieldId": "priority",
              "fieldValue": "={{ $json.priority }}"
            },
            {
              "fieldId": "due_date",
              "fieldValue": "={{ $json.due_date }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "={{ $json.status }}"
            },
            {
              "fieldId": "notes",
              "fieldValue": "={{ $json.notes }}"
            },
            {
              "fieldId": "created_at",
              "fieldValue": "={{ $json.created_at }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3634fab0-eea5-45f5-b5f9-fd11ee7d98bb",
      "name": "Compose Tender Alert Message",
      "type": "n8n-nodes-base.set",
      "position": [
        3088,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e2a70fbb-11fa-4d80-a65e-9a23d25b97ac",
              "name": "message",
              "type": "string",
              "value": "=New tender detected\n\nTender ID: {{ $json.tender_id }}\nTitle: {{ $json.tender_title }}\nAuthority: {{ $json.authority_name }}\nCategory: {{ $json.category }}\nDue Date: {{ $json.bid_due_date }}\nEstimated Value: {{ $json.estimated_value }}\nEligibility: {{ $json.eligibility_summary }}\nSummary: {{ $json.ai_summary }}\nSource: {{ $json.source_url }}"
            },
            {
              "id": "24fe97f3-afeb-46b0-8f5c-faa2b30e5ddf",
              "name": "tender_id",
              "type": "string",
              "value": "={{ $json.tender_id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ad3ad67f-0afa-4b7c-9955-6548a15e03e4",
      "name": "Send Tender Alert to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        3328,
        -192
      ],
      "parameters": {
        "text": "={{ $json.message }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0B1LNY15GW",
          "cachedResultName": "n8n-workflow-testing"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "49c1d9c0-6189-4d54-81ca-f33bfa9ae599",
      "name": "Send Tender Alert by Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3344,
        80
      ],
      "parameters": {
        "sendTo": "info@gmail.com",
        "message": "={{ $json.message }}",
        "options": {},
        "subject": "=New Tender Alert - {{ $json.tender_id }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8d92ffa2-707e-4337-9db0-62430a1ce695",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 672,
        "height": 352,
        "content": "## Scheduled Intake\n\nThis section starts the workflow on a timed schedule and loads tender records into a structured format. It prepares the incoming data so every tender has a consistent shape before duplicate checking and analysis begin."
      },
      "typeVersion": 1
    },
    {
      "id": "5e1001e3-8979-4105-8729-a38de2cdf88f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2256,
        -400
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 832,
        "content": "## Data Storage\nThis section combines the source tender data with the AI output, stores the final tender record, expands checklist items into separate rows, and saves each checklist task. It creates a complete tender history and bid action list in both storage systems.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b449d502-488b-4936-9a9c-cd3109147f84",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        800,
        -192
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 400,
        "content": "## Duplicate Control\n\nThis section merges the results from both duplicate lookups and sends forward only those records that are truly new. It acts as the main gatekeeper of the workflow, keeping the downstream AI and storage steps clean and accurate."
      },
      "typeVersion": 1
    },
    {
      "id": "ee1c8bad-c51e-4212-9a17-ee75b09b0118",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1360,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 464,
        "content": "## AI Analysis\nThis section prepares the tender text for the AI model, generates an eligibility summary and checklist, then converts the returned JSON into usable structured fields. It turns raw tender details into practical bid preparation guidance."
      },
      "typeVersion": 1
    },
    {
      "id": "c65bc303-488e-4574-81b8-8d61525a353d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        -256
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 528,
        "content": "## Record Enrichment\nThis section builds the duplicate key, assigns default status values, and checks existing tender records in both storage systems. It helps prevent duplicate entries and ensures only fresh tenders move to the next stage of the workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "cd4acadc-9996-410c-81d4-9531d6d488c5",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3024,
        -352
      ],
      "parameters": {
        "color": 7,
        "width": 544,
        "height": 656,
        "content": "## Team Alerts\nThis section builds a clear alert message and sends it to the team through Slack and Gmail. It makes sure the tender opportunity is visible immediately, so the bid team can review, prioritize, and begin preparation without delay.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c2113c18-776c-45da-b590-62407c9256c9",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1136,
        -192
      ],
      "parameters": {
        "width": 560,
        "height": 368,
        "content": "\n## How it works\nThis workflow runs on a schedule, loads tender records, normalizes them, and builds a duplicate key for each tender. It checks Google Sheets and Supabase to avoid repeated records, then sends only new tenders to AI for eligibility summary and bid checklist generation. After that, it stores the tender and checklist data, then sends Slack and email alerts for quick action.\n\n## Setup Steps\n1. Trigger the workflow with the schedule node.\n2. Load the tender records from the source dataset.\n3. Normalize tender fields and build the duplicate key.\n4. Check Google Sheets and Supabase for duplicates.\n5. Filter only new tender records.\n6. Send the tender details to AI for summary and checklist generation.\n7. Save the tender and checklist rows, then send Slack and email alerts.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "37806ec6-d751-4438-bc34-73ab2d6ad713",
  "connections": {
    "Enrich Tender Metadata": {
      "main": [
        [
          {
            "node": "Lookup Tender in Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Lookup Tender in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Tender Records": {
      "main": [
        [
          {
            "node": "Enrich Tender Metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter New Tender Records": {
      "main": [
        [
          {
            "node": "Build AI Tender Analysis Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lookup Tender in Supabase": {
      "main": [
        [
          {
            "node": "Consolidate Duplicate Check Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Seed Dummy Tender Dataset": {
      "main": [
        [
          {
            "node": "Normalize Tender Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compose Tender Alert Message": {
      "main": [
        [
          {
            "node": "Send Tender Alert to Slack",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Tender Alert by Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lookup Tender in Google Sheets": {
      "main": [
        [
          {
            "node": "Consolidate Duplicate Check Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build AI Tender Analysis Payload": {
      "main": [
        [
          {
            "node": "Generate Tender Eligibility and Bid Checklist",
            "type": "main",
            "index": 0
          },
          {
            "node": "Combine Tender Source and AI Analysis",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Flatten Bid Checklist Line Items": {
      "main": [
        [
          {
            "node": "Create Checklist Rows in Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create Checklist Rows in Supabase",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Checklist Rows in Supabase": {
      "main": [
        []
      ]
    },
    "Parse AI Tender Analysis Response": {
      "main": [
        [
          {
            "node": "Combine Tender Source and AI Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger Tender Monitoring Schedule": {
      "main": [
        [
          {
            "node": "Seed Dummy Tender Dataset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Consolidate Duplicate Check Results": {
      "main": [
        [
          {
            "node": "Filter New Tender Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Tender Source and AI Analysis": {
      "main": [
        [
          {
            "node": "Create Tender Master Row in Google Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Create Tender Master Record in Supabase",
            "type": "main",
            "index": 0
          },
          {
            "node": "Flatten Bid Checklist Line Items",
            "type": "main",
            "index": 0
          },
          {
            "node": "Compose Tender Alert Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Checklist Rows in Google Sheets": {
      "main": [
        []
      ]
    },
    "Generate Tender Eligibility and Bid Checklist": {
      "main": [
        [
          {
            "node": "Parse AI Tender Analysis Response",
            "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 scheduled workflow ingests tender records, checks Google Sheets and Supabase for duplicates, uses Google Gemini to generate an eligibility summary, match score, and bid checklist, then stores the tender and checklist data and alerts the team via Slack and Gmail. Runs on a…

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

• Multi-Layer Message Analysis - Every customer interaction passes through three specialized AI classifiers: privacy detection (identifies sensitive data and security requirements), intent recognition

OpenAI, OpenAI Chat, Tool Think +13
Data & Sheets

Scheduled processes retrieve customer feedback from multiple channels. The system performs sentiment analysis to classify tone, then uses OpenAI models to extract themes, topics, and urgency indicator

HTTP Request, Lm Chat Azure Open Ai, Sentiment Analysis +5
Data & Sheets

This workflow transforms raw SaaS metrics into a fully automated Product Health Monitoring & Incident Management system.

Postgres, OpenAI, Slack +2
Data & Sheets

Handles GDPR Article 15 (access) and Article 17 (erasure) requests end-to-end — from inbound email to legally-compliant response — with zero manual intervention and a full audit trail. 📬 Monitors Gmai

Gmail Trigger, Agent, OpenAI Chat +5
Data & Sheets

This workflow is designed for Customer Success Managers, Growth Teams, and SaaS Business Owners who want to proactively reduce churn using AI. It automates the analysis of customer health and the deli

HTTP Request, Postgres, OpenAI +2