{
  "nodes": [
    {
      "id": "05250a10-aa6e-4455-b0e4-596932620af4",
      "name": "SerpAPI",
      "type": "@n8n/n8n-nodes-langchain.toolSerpApi",
      "position": [
        -1216,
        864
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "serpApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4f6e4b5b-d504-4637-84c1-3bcebcffedd6",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -960,
        -368
      ],
      "parameters": {
        "color": 5,
        "width": 464,
        "height": 976,
        "content": "## How to Get Credentials\n\n### 1. SerpAPI Node\n- Go to [SerpAPI](https://serpapi.com/) and sign up\n- After logging in, find your **API Key** in your dashboard\n- In n8n: **Credentials** > **Create New** > **SerpAPI**\n- Paste your API Key and save\n\n### 2. OpenRouter (Gemini 2.5 Pro) Node\n- Go to [OpenRouter](https://openrouter.ai/) and create an account\n- Navigate to **Keys** section\n- Copy your **API Key**\n- In n8n: **Credentials** > **Create New** > **OpenRouter API**\n- Enter your API Key and save\n\n### 3. Telegram Nodes (Trigger & Send Message)\n- Open Telegram and search for [@BotFather](https://t.me/botfather)\n- Send `/newbot` and follow instructions to create your bot\n- Copy the **Bot Token** provided\n- In n8n: **Credentials** > **Create New** > **Telegram API**\n- Paste your Bot Token and save\n\n### 4. Gmail Node\n- In n8n: **Credentials** > **Create New** > **Gmail OAuth2**\n- Click **Connect my account**\n- Authorize with your Google account\n- Grant necessary permissions\n\n### 5. Data Table Nodes\n- **No credentials needed** - Data Tables are built into n8n\n- Create tables directly in your n8n instance\n\n**Required columns for this workflow:**\n- `platform` (string)\n- `promoCode` (string)\n- `value` (string)\n- `termsConditions` (string)\n- `validUntil` (dateTime)\n\n---\n**Security Note:** Keep all API keys secure and never share them publicly."
      },
      "typeVersion": 1
    },
    {
      "id": "9b6787e7-9f3c-4b00-8af4-ddaf68930cf4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2208,
        432
      ],
      "parameters": {
        "width": 672,
        "height": 240,
        "content": "## How This Workflow Works (Sticky Note)\n\n- This workflow is designed to help you find valid and working promo codes and vouchers from across the internet.\n- When you send a message, the AI Agent uses search tools (SerpAPI) to look for the latest discounts and vouchers.\n- The AI Agent checks and filters results to show only new and active promos.\n- All results are displayed in the chat for easy access.\n- Just type what kind of promo you want and let the workflow do the rest!"
      },
      "typeVersion": 1
    },
    {
      "id": "baebe25f-d3d7-4f49-9785-a81180032773",
      "name": "Promo Seeker Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -1280,
        640
      ],
      "parameters": {
        "text": "=platform: {{ $('Platform').item.json.query }}",
        "options": {
          "systemMessage": "=# Voucher & Discount Finder Expert\n\nYou are a specialized assistant focused on finding valid, working vouchers and discount codes across the internet.\n\n## Your Primary Objectives:\n1. Search for current, active discount codes and vouchers\n2. Verify codes are recent and likely to be working (within last 30 days)\n3. Present results clearly with code and discount value upfront\n4. Focus on the most recent and reliable sources\n\n## Search Strategy:\n- Use web_search to find current voucher codes\n- Look for codes posted within the last 30 days from today's date\n- Prioritize reputable coupon sites and official brand sources\n- Cross-reference multiple sources when possible\n- Check for expiration dates\n\n## Response Format:\nWhen you find vouchers, present them as:\n- **CODE**: [the actual voucher code]\n- **VALUE**: [discount amount or percentage]\n- **EXPIRES**: [expiration date if available]\n- **SOURCE**: [where you found it]\n- **VERIFIED**: [date it was posted/verified]\n\n## Important Notes:\n- Current date: {{$now}}\n- Only search for codes from the last 30 days maximum\n- Be direct - provide codes immediately without lengthy explanations\n- If no valid codes are found, clearly state this and suggest alternatives"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "37983435-354d-4c0c-b6c0-94d27160d563",
      "name": "Gemini 2.5Pro",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        -1344,
        864
      ],
      "parameters": {
        "model": "google/gemini-2.5-pro",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "78f91869-bc57-4ce9-9df6-b7b7e959cc69",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -2464,
        592
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1169ebb4-b2f9-4786-8f97-7228f17420aa",
      "name": "Platform",
      "type": "n8n-nodes-base.set",
      "position": [
        -2016,
        240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e7641500-13e1-46ec-8240-0b32e4fec715",
              "name": "query",
              "type": "string",
              "value": "={{ $json.Platform || $json.message?.text || $json.body.platform || '' }}"
            },
            {
              "id": "2813a353-96d0-4a90-906e-8b6340b9d099",
              "name": "receiver",
              "type": "string",
              "value": "={{ $json.chatId || $json.email || $json.body.email || '' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "28bd7fdd-5810-4742-b953-c068981da584",
      "name": "No Operation, do nothing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -2240,
        240
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "65c389a3-30fd-45d9-9677-194e2f46f2ac",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -2464,
        192
      ],
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "2422da6d-98c1-4f1b-92ce-9a6e39df0060",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -1088,
        864
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"platform\": \"platform\",\t\n  \"code1\": \"code1\",\n\t\"value\": \"value\",\n    \"terms\": \"terms and conditions\",\n    \"validUntil\": \"promo code period valid until(date)\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "9761d0fa-448a-4f85-b00a-75dcff57b101",
      "name": "Get row(s)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -1792,
        240
      ],
      "parameters": {
        "limit": 3,
        "filters": {
          "conditions": [
            {
              "keyName": "platform",
              "keyValue": "={{ $json.query }}"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "taO6FckoITHcml0P",
          "cachedResultUrl": "/projects/HdidsWtKEV9HXZzb/datatables/taO6FckoITHcml0P",
          "cachedResultName": "Kode Promo Valid"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "6f75fcf8-5d94-4c7f-a51d-4111f6ac6491",
      "name": "Code Exist?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1568,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4a12f7e0-f301-4efd-9b06-31489a31b6a3",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.platform }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8383580c-8c71-4f47-a521-5b6f7d89ad68",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -2464,
        0
      ],
      "parameters": {
        "options": {},
        "formTitle": "Promo Seeker",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Platform",
              "placeholder": "nama platformnya",
              "requiredField": true
            },
            {
              "fieldLabel": "email",
              "placeholder": "nanti kodenya bakal dikirim kesini",
              "requiredField": true
            }
          ]
        },
        "formDescription": "temukan promocode disini"
      },
      "typeVersion": 2.3
    },
    {
      "id": "bd7d5a97-15f3-442a-9e73-0dbda8511982",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "onError": "continueErrorOutput",
      "position": [
        -1216,
        336
      ],
      "parameters": {
        "sendTo": "={{ $('Webhook').item.json.body.email }}",
        "message": "=<!DOCTYPE html>\n<html lang=\"id\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Kode Promo Spesial</title>\n</head>\n<body style=\"margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4;\">\n    <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color: #f4f4f4; padding: 20px;\">\n        <tr>\n            <td align=\"center\">\n                <table width=\"600\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);\">\n                    <!-- Header -->\n                    <tr>\n                        <td style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center; border-radius: 8px 8px 0 0;\">\n                            <h1 style=\"margin: 0; color: #ffffff; font-size: 28px;\">\ud83c\udf89 Kode Promo Buatmu nih!</h1>\n                        </td>\n                    </tr>\n                    \n                    <!-- Content -->\n                    <tr>\n                        <td style=\"padding: 40px 30px;\">\n                            <table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n                                <tr>\n                                    <td style=\"padding-bottom: 20px;\">\n                                        <table width=\"100%\" cellpadding=\"10\" cellspacing=\"0\" style=\"background-color: #f8f9fa; border-radius: 6px;\">\n                                            <tr>\n                                                <td style=\"font-weight: bold; color: #333333; width: 40%;\">Platform:</td>\n                                                <td style=\"color: #666666;\">{{ $json.platform }}</td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"font-weight: bold; color: #333333;\">Kode Promo:</td>\n                                                <td>\n                                                    <span style=\"background-color: #667eea; color: #ffffff; padding: 8px 16px; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 18px; font-weight: bold; display: inline-block;\">{{ $json.promoCode }}</span>\n                                                </td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"font-weight: bold; color: #333333;\">Value Promo:</td>\n                                                <td style=\"color: #28a745; font-weight: bold; font-size: 18px;\">{{ $json.value }}</td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"font-weight: bold; color: #333333; vertical-align: top;\">Keterangan:</td>\n                                                <td style=\"color: #666666; line-height: 1.6;\">{{ $json.termsConditions }}</td>\n                                            </tr>\n                                            <tr>\n                                                <td style=\"font-weight: bold; color: #333333;\">Masa Berlaku:</td>\n                                                <td style=\"color: #dc3545; font-weight: bold;\">{{ $json.validUntil.split('T')[0] }}</td>\n                                            </tr>\n                                        </table>\n                                    </td>\n                                </tr>\n                            </table>\n                        </td>\n                    </tr>\n                    \n                    <!-- Footer -->\n                    <tr>\n                        <td style=\"background-color: #f8f9fa; padding: 20px; text-align: center; border-radius: 0 0 8px 8px; border-top: 1px solid #e9ecef;\">\n                            <p style=\"margin: 0; color: #6c757d; font-size: 14px;\">\n                                Just for you by <a href=\"https://khmuhtadin.com\" style=\"color: #667eea; text-decoration: none; font-weight: bold;\">khmuhtadin.com</a>\n                            </p>\n                        </td>\n                    </tr>\n                </table>\n            </td>\n        </tr>\n    </table>\n</body>\n</html>",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Kode Promo {{ $json.platform.toUpperCase() || $json.platform }} Sudah Tersedia"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "429dd741-9c1f-4c85-a07e-250e38620e4a",
      "name": "Upsert row(s)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -880,
        640
      ],
      "parameters": {
        "columns": {
          "value": {
            "value": "={{ $json.output.value }}",
            "platform": "={{ $json.output.platform }}",
            "promoCode": "={{ $json.output.code1 }}",
            "validUntil": "={{ $json.output.validUntil }}",
            "termsConditions": "={{ $json.output.terms }}"
          },
          "schema": [
            {
              "id": "platform",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "platform",
              "defaultMatch": false
            },
            {
              "id": "promoCode",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "promoCode",
              "defaultMatch": false
            },
            {
              "id": "value",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "value",
              "defaultMatch": false
            },
            {
              "id": "termsConditions",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "termsConditions",
              "defaultMatch": false
            },
            {
              "id": "validUntil",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "validUntil",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyName": "promoCode",
              "keyValue": "={{ $json.output.code1 }}"
            }
          ]
        },
        "options": {},
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "taO6FckoITHcml0P",
          "cachedResultUrl": "/projects/HdidsWtKEV9HXZzb/datatables/taO6FckoITHcml0P",
          "cachedResultName": "Kode Promo Valid"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5cacc658-19de-4d0d-9e18-012ae7db8ea6",
      "name": "notify telegram",
      "type": "n8n-nodes-base.telegram",
      "onError": "continueErrorOutput",
      "position": [
        -1216,
        144
      ],
      "parameters": {
        "text": "=<b>\ud83c\udf89 Kode Promo Buatmu nih!</b>\n\n<b>Platform:</b> {{ $json.platform }}\n<b>Kode Promo:</b> <code>{{ $json.promoCode }}</code>\n<b>Value Promo:</b> {{ $json.value }}\n<b>Keterangan:</b> {{ $json.termsConditions }}\n<b>Masa Berlaku:</b> {{ $json.validUntil.split('T')[0] }}",
        "chatId": "={{ $('Telegram Trigger').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "17d33219-8587-406b-9243-6ea8f00a9aef",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2464,
        384
      ],
      "parameters": {
        "path": "v1/promo-seeker",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "38d077ac-91eb-41ba-b58a-5122df0df77a",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "disabled": true,
      "position": [
        -1216,
        -48
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.4
    },
    {
      "id": "b1ff0780-cb28-4d52-aae3-ed20ebf2b987",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2208,
        688
      ],
      "parameters": {
        "color": 3,
        "width": 370,
        "height": 100,
        "content": "## \u2615 Appreciate This Workflow?\n\nSupport the creator by sending coffee:\n\n**PayPal:** [paypal.me/khmuhtadin](https://paypal.me/khmuhtadin)\n\nThank you! \ud83d\ude80"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "SerpAPI": {
      "ai_tool": [
        [
          {
            "node": "Promo Seeker Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Platform": {
      "main": [
        [
          {
            "node": "Get row(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s)": {
      "main": [
        [
          {
            "node": "Code Exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code Exist?": {
      "main": [
        [
          {
            "node": "notify telegram",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          },
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Promo Seeker Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini 2.5Pro": {
      "ai_languageModel": [
        [
          {
            "node": "Promo Seeker Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "No Operation, do nothing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Promo Seeker Agent": {
      "main": [
        [
          {
            "node": "Upsert row(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Operation, do nothing": {
      "main": [
        [
          {
            "node": "Platform",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Promo Seeker Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}