AutomationFlowsWeb Scraping › Lever Job Ingestion

Lever Job Ingestion

Lever Job Ingestion. Uses httpRequest. Scheduled trigger; 8 nodes.

Cron / scheduled trigger★★★★☆ complexity8 nodesHTTP Request
Web Scraping Trigger: Cron / scheduled Nodes: 8 Complexity: ★★★★☆ Added:

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
{
  "name": "Lever Job Ingestion",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "id": "schedule-lever",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -400,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Lever public job posting API \u2014 no auth required.\n// API: GET https://api.lever.co/v0/postings/{slug}?mode=json\n// Add company slugs here. Find slugs at: https://jobs.lever.co/{slug}\nconst companies = [\n  'contentful',\n  'netlify',\n  'elastic',\n  'shopify',\n  'auth0',\n  'twilio',\n  'heap',\n  'bitrise',\n  'miro',\n  'hotjar',\n  'personio',\n  'pleo',\n  'deliveroo',\n  'babylon',\n  'transfer-wise',\n  'bereal',\n];\nreturn companies.map(slug => ({ json: { slug } }));"
      },
      "id": "companies-lever",
      "name": "Companies",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -176,
        0
      ]
    },
    {
      "parameters": {
        "url": "=https://api.lever.co/v0/postings/{{ $json.slug }}",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "mode",
              "value": "json"
            }
          ]
        },
        "options": {}
      },
      "id": "fetch-lever",
      "name": "Fetch Jobs",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        48,
        0
      ],
      "continueOnFail": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "// Lever response is a JSON array at root or wrapped in {data:[]}\n// NOTE: Lever's API does not include a company field in posting objects.\n// Use the slug from the Companies node as the company name.\nfunction stripHtml(html) {\n  return (html || '').replace(/<[^>]*>/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&nbsp;/g, ' ').replace(/&#39;/g, \"'\").replace(/&quot;/g, '\"').replace(/\\s+/g, ' ').trim();\n}\nconst companySlug = $('Companies').item.json.slug || '';\nconst raw = $json;\nconst jobs = Array.isArray(raw) ? raw : (Array.isArray(raw.data) ? raw.data : []);\nreturn jobs.map(j => {\n  const workplaceType = (j.workplaceType || '').toLowerCase();\n  const loc = (j.categories && j.categories.location) || '';\n  const isRemote = workplaceType === 'remote' || loc.toLowerCase().includes('remote');\n  // Build description from lists\n  const lists = (j.lists || []).map(l => l.content || '').join(' ');\n  const descText = stripHtml((j.descriptionPlain || j.description || '') + ' ' + lists).slice(0, 8000);\n  return {\n    json: {\n      source: 'lever',\n      external_id: String(j.id ?? ''),\n      company: companySlug,\n      title: (j.text || j.title || '').trim(),\n      location: loc,\n      remote: isRemote ? 'remote' : 'unknown',\n      url: j.hostedUrl || j.applyUrl || '',\n      description: descText,\n      posted_at: j.createdAt ? new Date(j.createdAt).toISOString() : null,\n    }\n  };\n});"
      },
      "id": "normalize-lever",
      "name": "Normalize",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        272,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "function simpleHash(str) {\n  let hash = 0;\n  for (let i = 0; i < str.length; i++) {\n    hash = ((hash << 5) - hash) + str.charCodeAt(i);\n    hash |= 0;\n  }\n  return Math.abs(hash).toString(16).padStart(8, '0');\n}\nreturn items.map(({ json }) => {\n  const base = [json.source, json.external_id, json.company, json.title, json.url].join('|');\n  return { json: { ...json, content_hash: simpleHash(base) } };\n});"
      },
      "id": "hash-lever",
      "name": "Hash",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        496,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://matchpilot-production-a08d.up.railway.app/api/ingest",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "source",
              "value": "={{ $json.source }}"
            },
            {
              "name": "external_id",
              "value": "={{ $json.external_id }}"
            },
            {
              "name": "company",
              "value": "={{ $json.company }}"
            },
            {
              "name": "title",
              "value": "={{ $json.title }}"
            },
            {
              "name": "location",
              "value": "={{ $json.location }}"
            },
            {
              "name": "remote",
              "value": "={{ $json.remote }}"
            },
            {
              "name": "url",
              "value": "={{ $json.url }}"
            },
            {
              "name": "description",
              "value": "={{ $json.description }}"
            },
            {
              "name": "posted_at",
              "value": "={{ $json.posted_at }}"
            },
            {
              "name": "content_hash",
              "value": "={{ $json.content_hash }}"
            }
          ]
        },
        "options": {
          "timeout": 15000
        }
      },
      "id": "ingest-lever",
      "name": "Ingest",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        0
      ],
      "continueOnFail": true,
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "return Array.from({length: 100}, (_, i) => ({ json: { i } }));"
      },
      "id": "loop-lever",
      "name": "Loop 100",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        944,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://matchpilot-production-a08d.up.railway.app/api/worker/score",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "x-worker-secret",
              "value": "3eb2bf26e739c83044d5b6c7ea851c4e4c7e6f58afd401f267fa98f78445e6bf"
            }
          ]
        },
        "options": {
          "timeout": 60000
        }
      },
      "id": "worker-lever",
      "name": "Trigger Worker",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1168,
        0
      ],
      "continueOnFail": true,
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Companies": {
      "main": [
        [
          {
            "node": "Fetch Jobs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Jobs": {
      "main": [
        [
          {
            "node": "Normalize",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize": {
      "main": [
        [
          {
            "node": "Hash",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hash": {
      "main": [
        [
          {
            "node": "Ingest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ingest": {
      "main": [
        [
          {
            "node": "Loop 100",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop 100": {
      "main": [
        [
          {
            "node": "Trigger Worker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Lever Job Ingestion. Uses httpRequest. Scheduled trigger; 8 nodes.

Source: https://github.com/OskarsZvingulis/MatchPilot/blob/b94053498fa3f8fe4a8479b24d74a099cb9dfe73/n8n-workflows/lever.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

Birthday Automation - Production (Fixed). Uses stopAndError, httpRequest, emailSend, bannerbear. Scheduled trigger; 86 nodes.

Stop And Error, HTTP Request, Email Send +1
Web Scraping

This template runs two scheduled workflows to govern Microsoft Entra ID (Azure AD) guest accounts by detecting stale users via Microsoft Graph, staging deletions in SharePoint with a 72-hour window, n

Microsoft SharePoint, Microsoft Teams, Microsoft Entra +1
Web Scraping

Jira-Allure-Auto-Qa. Uses httpRequest, jira. Scheduled trigger; 68 nodes.

HTTP Request, Jira
Web Scraping

Spotify-Sync-Surrealdb-V1. Uses httpRequest, n8n-nodes-surrealdb, spotify. Scheduled trigger; 62 nodes.

HTTP Request, N8N Nodes Surrealdb, Spotify
Web Scraping

As n8n instances scale, teams often lose track of sub-workflows—who uses them, where they are referenced, and whether they can be safely updated. This leads to inefficiencies like unnecessary copies o

HTTP Request, n8n, N8N Trigger +1