{
  "name": "Carmentara \u2014 Daily SAM.gov + TED tenders to Slack",
  "meta": {
    "templateCredsSetupCompleted": false,
    "description": "DRAFT only. Runs carmentara/procurement-radar daily (onlyNew), posts new tenders to Slack. Brand: Carmentara. Not published."
  },
  "settings": {
    "executionOrder": "v1"
  },
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 7 * * *"
            }
          ]
        }
      },
      "id": "sched-1",
      "name": "Schedule 07:00 daily",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/acts/carmentara~procurement-radar/runs",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "waitForFinish",
              "value": "120"
            },
            {
              "name": "memory",
              "value": "512"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\n  \"sources\": [\n    \"sam\",\n    \"ted\"\n  ],\n  \"keywords\": [\n    \"software\",\n    \"cybersecurity\",\n    \"cloud\"\n  ],\n  \"cpvCodes\": [\n    \"72000000\",\n    \"48000000\"\n  ],\n  \"naicsCodes\": [\n    \"541511\",\n    \"541512\"\n  ],\n  \"countries\": [],\n  \"dateFilter\": \"publicationDate\",\n  \"noticeTypes\": [\n    \"cn-standard\"\n  ],\n  \"includeClosed\": false,\n  \"maxResults\": 50,\n  \"onlyNew\": true,\n  \"includeRaw\": false,\n  \"samApiKey\": \"{{$env.SAM_API_KEY}}\"\n}",
        "options": {}
      },
      "id": "apify-run-1",
      "name": "Run Procurement Radar",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        260,
        0
      ],
      "notes": "Auth: Header Authorization = Bearer <APIFY_TOKEN>. Or use public task RjTGcbPmC75xsQ2zp instead (TED-only EU IT). Do not rename that task."
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.data.status }}",
              "rightValue": "SUCCEEDED",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "if-ok-1",
      "name": "Run succeeded?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        520,
        0
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://api.apify.com/v2/actor-runs/{{ $json.data.id }}/dataset/items?limit=100&clean=true",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {}
      },
      "id": "fetch-ds-1",
      "name": "Fetch dataset items",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        780,
        -80
      ]
    },
    {
      "parameters": {
        "jsCode": "const items = Array.isArray($input.all()) ? $input.all().map(i => i.json) : [];\n// Apify returns array of tenders; flatten if wrapped\nconst rows = items.length === 1 && Array.isArray(items[0]) ? items[0] : items;\nconst tenders = rows.filter(r => r && (r.title || r.noticeId || r.source));\nif (!tenders.length) {\n  return [{ json: { text: ':white_check_mark: Procurement Radar: 0 new tenders today.', count: 0 } }];\n}\nconst lines = tenders.slice(0, 20).map((t, i) => {\n  const src = (t.source || '').toUpperCase();\n  const title = t.title || t.noticeTitle || '(no title)';\n  const buyer = t.buyer || t.buyerName || '';\n  const deadline = t.deadline || t.responseDeadLine || t.deadlineDate || '';\n  const url = t.url || t.noticeUrl || t.link || '';\n  const val = t.estimatedValue || t.value || '';\n  return `${i+1}. *[${src}]* <${url}|${title}>\\n    ${buyer}${deadline ? ' \u00b7 deadline ' + deadline : ''}${val ? ' \u00b7 ' + val : ''}`;\n});\nconst more = tenders.length > 20 ? `\\n_\u2026and ${tenders.length - 20} more in the dataset._` : '';\nconst text = `:mega: *${tenders.length} new government tender(s)* (SAM.gov + TED)\\n` + lines.join('\\n') + more + `\\n\\n_via Carmentara Procurement Radar_`;\nreturn [{ json: { text, count: tenders.length } }];"
      },
      "id": "fmt-1",
      "name": "Format Slack message",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1040,
        -80
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ text: $json.text }) }}",
        "options": {}
      },
      "id": "slack-1",
      "name": "Post to Slack webhook",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1300,
        -80
      ],
      "notes": "Or replace with Slack node + bot token. Incoming webhook URL in env SLACK_WEBHOOK_URL."
    },
    {
      "parameters": {
        "jsCode": "const st = $json.data?.status || $json.status || 'unknown';\nreturn [{ json: { text: `:warning: Procurement Radar run did not succeed (status=${st}). Check Apify Console.` } }];"
      },
      "id": "fmt-fail-1",
      "name": "Format failure",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        780,
        120
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $env.SLACK_WEBHOOK_URL }}",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ text: $json.text }) }}",
        "options": {}
      },
      "id": "slack-fail-1",
      "name": "Slack failure alert",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1040,
        120
      ]
    }
  ],
  "connections": {
    "Schedule 07:00 daily": {
      "main": [
        [
          {
            "node": "Run Procurement Radar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Procurement Radar": {
      "main": [
        [
          {
            "node": "Run succeeded?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run succeeded?": {
      "main": [
        [
          {
            "node": "Fetch dataset items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Format failure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch dataset items": {
      "main": [
        [
          {
            "node": "Format Slack message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Slack message": {
      "main": [
        [
          {
            "node": "Post to Slack webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format failure": {
      "main": [
        [
          {
            "node": "Slack failure alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}