This workflow corresponds to n8n.io template #15886 — we link there as the canonical source.
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 →
{
"id": "zAUNmHPItpviDVoV",
"name": "Tender result on frontend",
"tags": [],
"nodes": [
{
"id": "d2fbcba5-ad52-49d1-9534-c92bfaad8383",
"name": "Overview Sticky",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
320
],
"parameters": {
"width": 406,
"height": 577,
"content": "## \ud83c\udfaf Indian Tender Search & Email Report\n\n### How it works\nThis workflow fetches live tenders from TendersInfo.net based on user-provided keywords, filters for GEM (Government e-Marketplace) and MSE (Micro & Small Enterprises) eligible opportunities, and generates a professional HTML email report grouped by company. The webhook receives search criteria, queries the tender API, parses responses, filters relevant tenders, and formats results into a readable table.\n\n### Setup steps\n1. **Replace API authentication**: Update the `Cookie` header in \"Fetch Tender Data from API\" node with your valid `ANTI_FORGERY_TOKEN` and `SESSION_ID` from TendersInfo.net\n2. **Configure webhook**: Copy the production webhook URL from the \"Webhook Trigger\" node\n3. **Test with sample data**: Send a POST request with `{\"keywords\": \"software\", \"msme\": \"eligible\", \"email\": \"user@example.com\"}` to verify the flow\n4. **Activate workflow**: Enable the workflow to start processing real tender searches"
},
"typeVersion": 1
},
{
"id": "bbb26d0c-d3b7-4ee3-85c1-9d3833cc5f45",
"name": "Webhook Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
272
],
"parameters": {
"color": 2,
"content": "## \ud83d\udce5 Webhook Entry\nReceives POST requests with search parameters including keywords, MSME preferences, and recipient email address."
},
"typeVersion": 1
},
{
"id": "42c2b9b5-654d-466a-959d-6a08cd3ab1e5",
"name": "API Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
416,
288
],
"parameters": {
"color": 2,
"width": 360,
"height": 132,
"content": "## \ud83d\udd0d API Fetch & Parse\nQueries TendersInfo.net API with user keywords and extracts all tender listings from the JSON response into structured individual records."
},
"typeVersion": 1
},
{
"id": "4f2c0770-4536-4369-801c-114865c3be88",
"name": "Filter Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
848,
288
],
"parameters": {
"color": 2,
"width": 360,
"height": 132,
"content": "## \u2705 Filter & Format\nKeeps only GEM and MSE-eligible tenders, then maps fields for email presentation including links, dates, and company details."
},
"typeVersion": 1
},
{
"id": "192b7f46-c130-4f25-8107-4bf2ee1e450b",
"name": "Output Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
1280,
272
],
"parameters": {
"color": 2,
"width": 340,
"height": 148,
"content": "## \ud83d\udcca HTML Generation & Response\nBuilds a styled HTML table grouped by company name and returns it as the webhook response for email delivery or display."
},
"typeVersion": 1
},
{
"id": "39341326-4c08-440c-9134-938aebd23644",
"name": "Security Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
144
],
"parameters": {
"color": 3,
"width": 320,
"height": 140,
"content": "## \ud83d\udd10 Credentials & Security\nReplace `__REPLACE__` tokens in the Cookie header with valid session credentials from TendersInfo.net. Never share personal session IDs or API keys publicly."
},
"typeVersion": 1
},
{
"id": "661c29a8-c3ad-44bf-a878-a33ee6099232",
"name": "Webhook Trigger1",
"type": "n8n-nodes-base.webhook",
"position": [
176,
464
],
"parameters": {
"path": "ec731146-5297-410c-bfc4-f6fbe59a8f3f",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "bfe068d0-b93a-43f0-a614-50fa6cc459f0",
"name": "Parse Tender Response1",
"type": "n8n-nodes-base.code",
"position": [
624,
464
],
"parameters": {
"jsCode": "// Get the input data\nconst inputData = $input.all();\n\n// Initialize array to store all tenders\nlet allTenders = [];\n\n// Loop through each input item\nfor (const item of inputData) {\n // Parse the JSON string if it's a string, otherwise use directly\n let parsedData;\n \n if (typeof item.json.data === 'string') {\n parsedData = JSON.parse(item.json.data);\n } else {\n parsedData = item.json.data || item.json;\n }\n \n // Extract TenderList\n if (parsedData.TenderList && Array.isArray(parsedData.TenderList)) {\n allTenders = allTenders.concat(parsedData.TenderList);\n }\n}\n\n// Format each tender as a separate output item\nconst formattedOutput = allTenders.map(tender => ({\n json: {\n tenderRefNo: tender.tenderrefno,\n tcNo: tender.tcno,\n tenderProcId: tender.tenderprocid,\n country: tender.countryname,\n state: tender.statename,\n city: tender.cityname,\n keyword: tender.keywordname,\n subIndustry: tender.subindustryname,\n earnestMoney: tender.earnestmoney,\n address: tender.address,\n quantity: tender.quantity,\n tenderBrief: tender.tendersbriefnew || tender.tendersbrief,\n companyName: tender.companyname,\n tenderDate: tender.tenderdate,\n openingDate: tender.openingdate,\n closingDate: tender.closingdate,\n tenderValue: tender.tendervalue,\n currency: tender.currcode,\n isGEM: tender.isgem,\n isPQ: tender.ispq,\n isBOQ: tender.isboq,\n isDocument: tender.isdocument,\n isFreeTender: tender.isfreetender,\n isMSE: tender.ismse,\n isCorrigendum: tender.iscorrigendum,\n biddingType: tender.biddingtype,\n publicationDate: tender.publicationdate,\n fundAgency: tender.fundagencyname,\n docFees: tender.docfees,\n descriptionLink: tender.descriptionlink,\n originalSource: tender.originalsource,\n scorePercentage: tender.scorePercentage,\n elasticScore: tender.elastic_score\n }\n}));\n\nreturn formattedOutput;"
},
"typeVersion": 2
},
{
"id": "1850abac-3bbe-4424-a78a-3ed4fd2901af",
"name": "Select Email Fields1",
"type": "n8n-nodes-base.set",
"position": [
1072,
464
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "96e09add-c473-4795-949f-0e8e87c7b764",
"name": "=Name",
"type": "string",
"value": "={{ $json.companyName }}"
},
{
"id": "02a76031-a5a3-4075-aacd-97f79b539e8e",
"name": "Description Link",
"type": "string",
"value": "={{ $json.descriptionLink }}"
},
{
"id": "8a6b0b2d-e689-41cb-9f2b-cad8c179d01d",
"name": "TenderRefNo",
"type": "string",
"value": "={{ $json.tenderRefNo }}"
},
{
"id": "b6e779fb-2464-48f6-9160-0ad77c6d13f1",
"name": "TcNo",
"type": "string",
"value": "={{ $json.tcNo }}"
},
{
"id": "9b59a6da-4b6d-4a65-b094-e7b12cbfb57b",
"name": "TenderProcId",
"type": "string",
"value": "={{ $json.tenderProcId }}"
},
{
"id": "afc1819d-2a84-47b1-a3e3-46bbc85c2061",
"name": "Country",
"type": "string",
"value": "={{ $json.country }}"
},
{
"id": "d8d658ba-59db-4276-9aa2-4d4a9520a079",
"name": "State",
"type": "string",
"value": "= {{$json.state }}"
},
{
"id": "420cfa86-e752-4a7f-8a74-ce806fd29eca",
"name": "City",
"type": "string",
"value": "={{ $json.city }}"
},
{
"id": "479b39bf-b616-4c76-ad68-7286e2ee6df9",
"name": "TenderBrief",
"type": "string",
"value": "={{ $json.tenderBrief }}"
},
{
"id": "9f39f749-1cc8-4ebe-bac1-c1bb8175c86c",
"name": "Company Name",
"type": "string",
"value": "={{ $json.companyName }}"
},
{
"id": "d25bac11-4278-48c7-a4d7-4821af82bfca",
"name": "Tender Date",
"type": "string",
"value": "={{ $json.tenderDate }}"
},
{
"id": "10c45fcd-2da8-4050-b3eb-119ed216cbd0",
"name": "Opening Date",
"type": "string",
"value": "={{ $json.openingDate }}"
},
{
"id": "854b9608-f6d9-447d-8545-cd237374c5bf",
"name": "Closing Date",
"type": "string",
"value": "={{ $json.closingDate }}"
},
{
"id": "a2a7bf56-e720-44f9-b1e6-740e2d1672de",
"name": "Original_Source",
"type": "string",
"value": "={{ $json.originalSource }}"
},
{
"id": "ad528850-f5aa-436a-bb05-2dd9a169b8f2",
"name": "Responder email",
"type": "string",
"value": "={{ $('Webhook Trigger1').item.json.body.email }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "3c071e78-a5a5-4698-b1cd-99cc00e71073",
"name": "Fetch Tender Data from API1",
"type": "n8n-nodes-base.httpRequest",
"position": [
400,
464
],
"parameters": {
"url": "https://tendersinfo.net/TenderAI/GetTendersList",
"method": "POST",
"options": {},
"sendBody": true,
"contentType": "form-urlencoded",
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "searchkeyword",
"value": "={{ $json.body.keywords }} tenders from {{ $json.body.location }} {{ $json.body.msme }}"
},
{
"name": "tabindex",
"value": "1"
},
{
"name": "maintabindex",
"value": "0"
},
{
"name": "total",
"value": "200"
},
{
"name": "tender_typewise",
"value": "live"
},
{
"name": "rescount",
"value": "0"
},
{
"name": "categoryflag",
"value": "1"
},
{
"name": "last_rescount",
"value": "20"
},
{
"name": "sortingScore",
"value": "0"
},
{
"name": "gemtender",
"value": "1"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Origin",
"value": "https://tendersinfo.net"
},
{
"name": "Referer",
"value": "https://tendersinfo.net/TenderAI/TenderAIList"
},
{
"name": "X-Requested-With",
"value": "XMLHttpRequest"
},
{
"name": "User-Agent",
"value": "Mozilla/5.0"
},
{
"name": "Cookie",
"value": "ANTI_FORGERY_TOKEN=__REPLACE__; SESSION_ID=__REPLACE__; TenderTypewise=live;"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "6203e9be-f85e-49be-8cae-0d5f7bcfb004",
"name": "Filter GEM Tenders Only1",
"type": "n8n-nodes-base.filter",
"position": [
848,
464
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "6e683df5-0eca-4fa8-8459-1abbd816a790",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.isGEM }}",
"rightValue": "1"
},
{
"id": "70c84182-508f-4ba4-96fc-5f9a1e0a2be4",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.isMSE }}",
"rightValue": "=1"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "a2899512-ed5b-4da3-9d6b-37e26503303b",
"name": "Respond to Webhook1",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1520,
464
],
"parameters": {
"options": {},
"respondWith": "text",
"responseBody": "={{$node['Build HTML Table'].json['html']}}\n"
},
"typeVersion": 1.4
},
{
"id": "6e3b9ca1-d8ac-4711-909d-8fbb27334249",
"name": "Build HTML Table",
"type": "n8n-nodes-base.code",
"position": [
1296,
464
],
"parameters": {
"jsCode": "const items = $input.all().map(i => i.json);\n\n// ---------- Helpers ----------\nfunction toTitleCase(str) {\n if (!str) return \"Unknown Department\";\n return str\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .trim()\n .split(\" \")\n .map(w => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n// ---------- Group by Department ----------\nconst grouped = {};\n\nitems.forEach(t => {\n const rawDept = t[\"Company Name\"] || t.Name || \"Unknown Department\";\n const deptTitle = toTitleCase(rawDept);\n\n if (!grouped[deptTitle]) grouped[deptTitle] = [];\n grouped[deptTitle].push(t);\n});\n\n// ---------- CSS ----------\nlet html = `\n<style>\nbody {\n font-family: Inter, Arial, sans-serif;\n background: #f6f8fb;\n}\n.tender-wrapper {\n max-width: 1100px;\n margin: auto;\n}\n.department {\n margin: 30px 0 15px;\n padding: 14px 18px;\n background: linear-gradient(135deg, #1e3c72, #2a5298);\n color: #fff;\n border-radius: 10px;\n font-size: 20px;\n font-weight: 600;\n}\n.tender-card {\n background: #fff;\n border-radius: 12px;\n padding: 18px 20px;\n margin-bottom: 16px;\n box-shadow: 0 6px 16px rgba(0,0,0,0.08);\n border-left: 5px solid #2a5298;\n}\n.tender-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));\n gap: 10px 20px;\n}\n.tender-item {\n font-size: 14px;\n}\n.tender-item strong {\n color: #1e3c72;\n}\n.tender-brief {\n grid-column: 1 / -1;\n margin-top: 8px;\n}\n.tender-link {\n margin-top: 14px;\n display: inline-block;\n padding: 8px 14px;\n background: #2a5298;\n color: #fff !important;\n border-radius: 6px;\n text-decoration: none;\n font-size: 13px;\n}\n.tender-link:hover {\n background: #1e3c72;\n}\n.footer-note {\n margin-top: 40px;\n text-align: center;\n font-size: 12px;\n color: #666;\n}\n</style>\n\n<div class=\"tender-wrapper\">\n`;\n\n// ---------- HTML ----------\nObject.entries(grouped).forEach(([dept, tenders]) => {\n html += `<div class=\"department\">${dept}</div>`;\n\n tenders.forEach(t => {\n html += `\n <div class=\"tender-card\">\n <div class=\"tender-grid\">\n <div class=\"tender-item\"><strong>Tender Ref:</strong> ${t.TenderRefNo || \"-\"}</div>\n <div class=\"tender-item\"><strong>TC No:</strong> ${t.TcNo || \"-\"}</div>\n <div class=\"tender-item\"><strong>Proc ID:</strong> ${t.TenderProcId || \"-\"}</div>\n <div class=\"tender-item\"><strong>Country:</strong> ${toTitleCase(t.Country)}</div>\n <div class=\"tender-item\"><strong>State:</strong> ${toTitleCase(t.State)}</div>\n <div class=\"tender-item\"><strong>City:</strong> ${toTitleCase(t.City)}</div>\n <div class=\"tender-item\"><strong>Tender Date:</strong> ${t[\"Tender Date\"] || \"-\"}</div>\n <div class=\"tender-item\"><strong>Opening Date:</strong> ${t[\"Opening Date\"] || \"-\"}</div>\n <div class=\"tender-item\"><strong>Closing Date:</strong> ${t[\"Closing Date\"] || \"-\"}</div>\n\n <div class=\"tender-brief\">\n <strong>Brief:</strong><br>\n ${t.TenderBrief || \"-\"}\n </div>\n </div>\n\n <a class=\"tender-link\" href=\"${t[\"Description Link\"]}\" target=\"_blank\">\n View Tender Details\n </a>\n </div>\n `;\n });\n});\n\nhtml += `\n <div class=\"footer-note\">\n Source: GeM / TenderTiger \u2022 Generated Automatically\n </div>\n</div>\n`;\n\n// ---------- Return ----------\nreturn [{ json: { html } }];\n\n"
},
"typeVersion": 2
}
],
"active": true,
"settings": {
"binaryMode": "separate",
"availableInMCP": false,
"executionOrder": "v1"
},
"versionId": "67845b2e-27a6-45c3-963d-c0a4efed0e60",
"connections": {
"Build HTML Table": {
"main": [
[
{
"node": "Respond to Webhook1",
"type": "main",
"index": 0
}
]
]
},
"Webhook Trigger1": {
"main": [
[
{
"node": "Fetch Tender Data from API1",
"type": "main",
"index": 0
}
]
]
},
"Select Email Fields1": {
"main": [
[
{
"node": "Build HTML Table",
"type": "main",
"index": 0
}
]
]
},
"Parse Tender Response1": {
"main": [
[
{
"node": "Filter GEM Tenders Only1",
"type": "main",
"index": 0
}
]
]
},
"Filter GEM Tenders Only1": {
"main": [
[
{
"node": "Select Email Fields1",
"type": "main",
"index": 0
}
]
]
},
"Fetch Tender Data from API1": {
"main": [
[
{
"node": "Parse Tender Response1",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow fetches live tenders from TendersInfo.net based on user-provided keywords, filters for GEM (Government e-Marketplace) and MSE (Micro & Small Enterprises) eligible opportunities, and generates a professional HTML email report grouped by company. The webhook receives…
Source: https://n8n.io/workflows/15886/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.
This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia
This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c