{
  "name": "Monocrawl — New Indeed jobs to Slack",
  "nodes": [
    {
      "id": "indeed-jobs-to-slack-manual-test",
      "name": "Manual test",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        -100
      ],
      "parameters": {}
    },
    {
      "id": "indeed-jobs-to-slack-daily-schedule",
      "name": "Daily schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        100
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "daysInterval": 1,
              "triggerAtHour": 9
            }
          ]
        }
      }
    },
    {
      "id": "indeed-jobs-to-slack-configure",
      "name": "Configure",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        220,
        0
      ],
      "parameters": {
        "jsCode": "const c = { baseUrl: 'https://www.monocrawl.com', query: 'REPLACE_JOB_SEARCH', location: 'New York, NY', countryCode: 'us', slackChannelId: 'REPLACE_SLACK_CHANNEL_ID' };for(const v of Object.values(c))if(String(v).startsWith('REPLACE_'))throw Error('Fill in the settings in this Configure node before running.');return [{json:c}];"
      }
    },
    {
      "id": "indeed-jobs-to-slack-get-data",
      "name": "Get data",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        450,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $('Configure').first().json.baseUrl + '/v1/jobs/indeed/search' }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ $('Configure').first().json.query }}"
            },
            {
              "name": "location",
              "value": "={{ $('Configure').first().json.location }}"
            },
            {
              "name": "country_code",
              "value": "={{ $('Configure').first().json.countryCode }}"
            }
          ]
        },
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      }
    },
    {
      "id": "indeed-jobs-to-slack-prepare-rows",
      "name": "Prepare rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        0
      ],
      "parameters": {
        "jsCode": "const r=$input.first().json;if(r.success!==true)throw Error(r.error?.message||'Monocrawl request failed');if(r.synthetic||r.degraded||r.stale||r.data?._synthetic)throw Error('The API returned sample or stale fallback data. No destination was updated.');if(!Array.isArray(r.data?.items))throw Error('Expected a job list');\nconst state=$getWorkflowStaticData('global'),seen=state.seen??{};\nconst escape=s=>String(s??'').replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('>','&gt;');\nconst rows=r.data.items.filter(j=>{if(!j.id)throw Error('Job ID missing');return !seen[j.id];});\nreturn rows.map(j=>({json:{id:j.id,text:escape(j.title)+' — '+escape(j.company?.name??j.company)+'\\n'+escape(j.location)+'\\n'+escape(j.url??j.apply_url)}}));"
      }
    },
    {
      "id": "indeed-jobs-to-slack-send-to-slack",
      "name": "Send to Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [
        910,
        0
      ],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "={{ $('Configure').first().json.slackChannelId }}",
          "mode": "id"
        },
        "messageType": "text",
        "text": "={{ $json.text }}",
        "otherOptions": {
          "includeLinkToWorkflow": false,
          "mrkdwn": false,
          "unfurl_links": false,
          "unfurl_media": false
        }
      }
    },
    {
      "id": "indeed-jobs-to-slack-remember-delivered-data",
      "name": "Remember delivered data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1140,
        0
      ],
      "parameters": {
        "jsCode": "const state=$getWorkflowStaticData('global');const seen=state.seen??{};for(const item of $('Prepare rows').all())seen[item.json.id]=Date.now();state.seen=Object.fromEntries(Object.entries(seen).sort((a,b)=>b[1]-a[1]).slice(0,5000));return $input.all();"
      }
    },
    {
      "id": "indeed-jobs-to-slack-setup-notes",
      "name": "Setup notes",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        260,
        -390
      ],
      "parameters": {
        "width": 680,
        "height": 290,
        "content": "# New Indeed jobs to Slack\n1. Edit Configure (source, destination and API base URL).\n2. Select a Header Auth credential on Get data: name x-api-key, value your Monocrawl key. Use a key from the same environment as baseUrl.\n3. Connect the Slack credential and invite its app to your channel.\n4. Run a manual test (charges for one API request; sends/writes real data), then publish to enable the daily schedule.\n\nSends the first returned page on the first scheduled run. Remembers up to 5,000 delivered IDs. n8n only persists this state for successful scheduled/published executions, so manual tests can send duplicates.\n\nNo automatic request retry or pagination. See the request log for charges. Keep workflow concurrency at 1 for remembered state."
      }
    }
  ],
  "connections": {
    "Manual test": {
      "main": [
        [
          {
            "node": "Configure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily schedule": {
      "main": [
        [
          {
            "node": "Configure",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure": {
      "main": [
        [
          {
            "node": "Get data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get data": {
      "main": [
        [
          {
            "node": "Prepare rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare rows": {
      "main": [
        [
          {
            "node": "Send to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to Slack": {
      "main": [
        [
          {
            "node": "Remember delivered data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "timezone": "Europe/London"
  },
  "pinData": {},
  "tags": []
}
