{
  "name": "Find and score LinkedIn B2B leads with Bright Data, GPT-5.6 and Slack",
  "nodes": [
    {
      "id": "sticky-main",
      "name": "Sticky Note main",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -700,
        101
      ],
      "parameters": {
        "color": 1,
        "width": 560,
        "height": 946,
        "content": "## Find and score B2B leads from LinkedIn with Bright Data\n\nDescribe your ideal customer in a sentence. Get back a scored, evidence-backed company list in Google Sheets and a Slack digest.\n\n### How it works\n1. A form takes your ICP, a target country and how many companies you want.\n2. GPT-5.6 Luna turns the ICP into five search angles: industry wording, product category, hiring signals, technology used and adjacent tooling.\n3. Bright Data's SERP API runs each angle as a `site:linkedin.com/company` search. Results are deduped to one row per company.\n4. Bright Data's LinkedIn scraper enriches each company with size, industry, headquarters, founding year, specialties and about text.\n5. GPT-5.6 Terra scores every company against your ICP and has to quote the evidence it used, list what is missing, and name the likeliest objection.\n6. Companies at or above your bar go to a qualified sheet and a Slack digest. The rest go to a rejected sheet, so you can see what the filter threw away.\n\n### Setup\n- [ ] Create a Bright Data account, add a **SERP API** zone, and set `serp_zone` in **Set Search Parameters** to its name.\n- [ ] Add a **Header Auth** credential called `Bright Data API`: name `Authorization`, value `Bearer YOUR_KEY`. Attach it to both HTTP Request nodes.\n- [ ] Add OpenAI credentials to the two model nodes.\n- [ ] Add Google Sheets and Slack credentials, and paste your own sheet URL into both log nodes.\n\n### Customization\n`min_score` in **Set Search Parameters** sets the bar, default 60. Rejected rows are logged on purpose, so start low and tighten once you have seen a few runs."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-sec1",
      "name": "Sticky Note sec1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -60,
        310
      ],
      "parameters": {
        "color": 7,
        "width": 1064,
        "height": 590,
        "content": "## 1. Turn the ICP into search angles\nOne sentence of ICP becomes five different searches, so the run does not hang on a single phrasing."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-sec2",
      "name": "Sticky Note sec2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        301
      ],
      "parameters": {
        "color": 7,
        "width": 696,
        "height": 375,
        "content": "## 2. Search LinkedIn through Bright Data\nEach angle runs as a `site:linkedin.com/company` query. Results are deduped to one row per company slug."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-sec3",
      "name": "Sticky Note sec3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2060,
        301
      ],
      "parameters": {
        "color": 7,
        "width": 696,
        "height": 375,
        "content": "## 3. Enrich every company\nBright Data's LinkedIn scraper returns size, industry, headquarters, specialties and about text for each company found."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-sec4",
      "name": "Sticky Note sec4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2936,
        301
      ],
      "parameters": {
        "color": 7,
        "width": 584,
        "height": 599,
        "content": "## 4. Score against the ICP\nThe model has to quote its evidence, list what is missing and name the likeliest objection. A score with no evidence is a guess."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-sec5",
      "name": "Sticky Note sec5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3700,
        101
      ],
      "parameters": {
        "color": 7,
        "width": 936,
        "height": 815,
        "content": "## 5. Route and deliver\nAbove the bar goes to the qualified sheet and a Slack digest. Below it is still logged, so you can audit what the filter rejected."
      },
      "typeVersion": 1
    },
    {
      "id": "sticky-warn",
      "name": "Sticky Note warn",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2060,
        736
      ],
      "parameters": {
        "color": 3,
        "width": 380,
        "height": 247,
        "content": "## Sync scrape limit\nThis uses Bright Data's **sync** scrape endpoint, which gives up after about a minute. Past roughly 25 companies it returns a `snapshot_id` instead of rows. **Flatten Company Records** detects that and tells you to switch to the async endpoint."
      },
      "typeVersion": 1
    },
    {
      "id": "t1",
      "name": "When ICP Form Submitted",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        0,
        460
      ],
      "parameters": {
        "options": {
          "buttonLabel": "Find companies"
        },
        "formTitle": "B2B Lead Engine",
        "formFields": {
          "values": [
            {
              "fieldType": "textarea",
              "fieldLabel": "Ideal customer profile",
              "placeholder": "e.g. Series A-B cybersecurity companies in Israel, 50-200 staff, selling to enterprise CISOs",
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Country",
              "fieldOptions": {
                "values": [
                  {
                    "option": "us (United States)"
                  },
                  {
                    "option": "gb (United Kingdom)"
                  },
                  {
                    "option": "ca (Canada)"
                  },
                  {
                    "option": "au (Australia)"
                  },
                  {
                    "option": "de (Germany)"
                  },
                  {
                    "option": "fr (France)"
                  },
                  {
                    "option": "nl (Netherlands)"
                  },
                  {
                    "option": "es (Spain)"
                  },
                  {
                    "option": "it (Italy)"
                  },
                  {
                    "option": "se (Sweden)"
                  },
                  {
                    "option": "il (Israel)"
                  },
                  {
                    "option": "in (India)"
                  },
                  {
                    "option": "sg (Singapore)"
                  },
                  {
                    "option": "br (Brazil)"
                  },
                  {
                    "option": "jp (Japan)"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "How many companies",
              "fieldOptions": {
                "values": [
                  {
                    "option": "10"
                  },
                  {
                    "option": "25"
                  },
                  {
                    "option": "50"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        },
        "formDescription": "Describe your ideal customer. You get back a scored company list."
      },
      "typeVersion": 2.5
    },
    {
      "id": "c1",
      "name": "Set Search Parameters",
      "type": "n8n-nodes-base.set",
      "position": [
        240,
        460
      ],
      "parameters": {
        "mode": "manual",
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c0",
              "name": "icp",
              "type": "string",
              "value": "={{ $json['Ideal customer profile'] }}"
            },
            {
              "id": "c1",
              "name": "country",
              "type": "string",
              "value": "={{ $json.Country.split(' ')[0].toLowerCase() }}"
            },
            {
              "id": "c2",
              "name": "max_companies",
              "type": "number",
              "value": "={{ parseInt($json['How many companies']) }}"
            },
            {
              "id": "c3",
              "name": "min_score",
              "type": "number",
              "value": "60"
            },
            {
              "id": "c4",
              "name": "serp_zone",
              "type": "string",
              "value": "serp_api1"
            },
            {
              "id": "c5",
              "name": "run_id",
              "type": "string",
              "value": "={{ $execution.id }}"
            }
          ]
        },
        "includeOtherFields": false
      },
      "typeVersion": 3.4
    },
    {
      "id": "m1",
      "name": "OpenAI Query Planner Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "onError": "continueRegularOutput",
      "position": [
        488,
        700
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.6-luna"
        },
        "options": {
          "temperature": 0.3
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e1",
      "name": "Extract Queries from ICP",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "onError": "continueRegularOutput",
      "position": [
        480,
        460
      ],
      "parameters": {
        "text": "=Ideal customer profile:\n{{ $json.icp }}\nCountry: {{ $json.country }}\n\nWrite 5 Google queries that surface LinkedIn company pages matching this profile. Each query must contain the operator site:linkedin.com/company. Vary the angle across queries: industry wording, product category, the job titles such a company would be hiring, and the technology it would run. Return the query string only - no explanation inside the query.",
        "options": {},
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"queries\": [\n    { \"query\": \"site:linkedin.com/company cybersecurity israel series a\", \"angle\": \"funding stage\" }\n  ]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "sp1",
      "name": "Split Queries for Processing",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        848,
        460
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "output.queries"
      },
      "typeVersion": 1
    },
    {
      "id": "h1",
      "name": "Post to Bright Data API",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "maxTries": 3,
      "position": [
        1244,
        460
      ],
      "parameters": {
        "url": "https://api.brightdata.com/request",
        "method": "POST",
        "options": {
          "timeout": 120000,
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "jsonBody": "={{ JSON.stringify({ zone: $('Set Search Parameters').first().json.serp_zone, url: 'https://www.google.com/search?q=' + encodeURIComponent($json.query) + '&gl=' + encodeURIComponent($('Set Search Parameters').first().json.country) + '&brd_json=1', format: 'json' }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 2000
    },
    {
      "id": "cd1",
      "name": "Filter LinkedIn Company URLs",
      "type": "n8n-nodes-base.code",
      "position": [
        1484,
        460
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Keep only real LinkedIn company pages, one row per company.\nconst seen = new Set();\nconst out = [];\nconst errors = [];\n\nfor (const item of $input.all()) {\n  let payload = item.json.body ?? item.json;\n  if (typeof payload === 'string') {\n    try { payload = JSON.parse(payload); } catch { continue; }\n  }\n  // Bright Data answers 200 with an error body, so a bad request looks\n  // like an empty SERP unless we read it.\n  if (payload && payload.error) {\n    const detail = Array.isArray(payload.details)\n      ? payload.details.map((d) => d.message).join('; ')\n      : '';\n    errors.push(payload.error + (detail ? ': ' + detail : ''));\n    continue;\n  }\n  for (const r of (payload.organic ?? [])) {\n    const link = r.link || r.url;\n    if (!link) continue;\n    // /company/<slug> only - skip /jobs, /posts, /showcase and locale variants\n    const m = link.match(/linkedin\\.com\\/company\\/([a-z0-9\\-_.%]+)/i);\n    if (!m) continue;\n    const slug = m[1].toLowerCase();\n    if (seen.has(slug)) continue;\n    seen.add(slug);\n    out.push({ json: {\n      slug,\n      linkedin_url: `https://www.linkedin.com/company/${slug}`,\n      serp_title: r.title ?? '',\n      serp_snippet: r.description ?? '',\n    }});\n  }\n}\n\nif (out.length === 0 && errors.length) {\n  throw new Error(`Bright Data rejected the SERP request: ${errors[0]}`);\n}\n\nif (out.length === 0) {\n  throw new Error('No LinkedIn company pages found. Check that serp_zone in Search Config matches a zone in your Bright Data account, and that the ICP is specific enough to search for.');\n}\n\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "l1",
      "name": "Limit Company Count",
      "type": "n8n-nodes-base.limit",
      "position": [
        1724,
        460
      ],
      "parameters": {
        "maxItems": "={{ $('Set Search Parameters').first().json.max_companies }}"
      },
      "typeVersion": 1
    },
    {
      "id": "ag1",
      "name": "Aggregate URLs for Scraper",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        2120,
        460
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "targets"
      },
      "typeVersion": 1
    },
    {
      "id": "h2",
      "name": "Post to LinkedIn Scraper API",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "maxTries": 3,
      "position": [
        2360,
        460
      ],
      "parameters": {
        "url": "https://api.brightdata.com/datasets/v3/scrape?dataset_id=gd_l1vikfnt1wgvvqz95w&format=json",
        "method": "POST",
        "options": {
          "timeout": 180000,
          "response": {
            "response": {
              "neverError": true
            }
          }
        },
        "jsonBody": "={{ JSON.stringify($json.targets.map(t => ({ url: t.linkedin_url }))) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "retryOnFail": true,
      "typeVersion": 4.4,
      "waitBetweenTries": 2000
    },
    {
      "id": "cd2",
      "name": "Flatten Company Records",
      "type": "n8n-nodes-base.code",
      "position": [
        2600,
        460
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// The scraper returns one array of company objects. Flatten to n8n items and\n// keep only the fields the scorer needs - a full LinkedIn record is mostly noise.\n// Bright Data may hand back one item per company (n8n split the array) or a\n// single item holding the whole array. Read every input item, or we keep only\n// the first company and silently drop the rest.\nconst rows = [];\n\nfor (const item of $input.all()) {\n  let payload = item.json.body ?? item.json;\n  if (typeof payload === 'string') {\n    try { payload = JSON.parse(payload); } catch { continue; }\n  }\n  if (payload && payload.snapshot_id && !Array.isArray(payload)) {\n    throw new Error(`Bright Data returned snapshot_id ${payload.snapshot_id} instead of rows, which means the sync request passed its 1-minute limit. Lower \"How many companies\", or switch this node to the async endpoint /datasets/v3/trigger and poll /datasets/v3/progress.`);\n  }\n  if (Array.isArray(payload)) rows.push(...payload);\n  else if (payload) rows.push(payload);\n}\n\nconst out = [];\n\nfor (const c of rows) {\n  if (!c || (!c.name && !c.company_name)) continue;\n  out.push({ json: {\n    name: c.name ?? c.company_name ?? '',\n    linkedin_url: c.url ?? c.input?.url ?? '',\n    website: c.website ?? '',\n    industry: c.industries ?? c.industry ?? '',\n    employees: c.employees_in_linkedin ?? c.company_size ?? null,\n    headquarters: c.headquarters ?? c.locations?.[0] ?? '',\n    founded: c.founded ?? null,\n    specialties: Array.isArray(c.specialties) ? c.specialties.join(', ') : (c.specialties ?? ''),\n    about: (c.about ?? c.description ?? '').slice(0, 1500),\n    followers: c.followers ?? null,\n  }});\n}\n\nif (out.length === 0) {\n  throw new Error('The scraper returned no usable company records. The URLs may be private or region-blocked pages.');\n}\n\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "m2",
      "name": "OpenAI Scoring Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "onError": "continueRegularOutput",
      "position": [
        3004,
        700
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-5.6-luna"
        },
        "options": {
          "temperature": 0
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "e2",
      "name": "Evaluate ICP Scores",
      "type": "@n8n/n8n-nodes-langchain.informationExtractor",
      "onError": "continueRegularOutput",
      "position": [
        2996,
        460
      ],
      "parameters": {
        "text": "=IDEAL CUSTOMER PROFILE:\n{{ $('Set Search Parameters').first().json.icp }}\n\nCOMPANY:\nName: {{ $json.name }}\nIndustry: {{ $json.industry }}\nEmployees: {{ $json.employees }}\nHQ: {{ $json.headquarters }}\nFounded: {{ $json.founded }}\nSpecialties: {{ $json.specialties }}\nAbout: {{ $json.about }}\n\nScore 0-100 for fit against the profile. Judge only the company facts above - you have not been told what search found this company, and you should not assume it matches just because it surfaced.\n\nQuote the specific fact behind the score. If a criterion in the profile cannot be checked from these fields, list it under missing rather than assuming it passes.",
        "options": {},
        "schemaType": "fromJson",
        "jsonSchemaExample": "{\n  \"score\": 72,\n  \"tier\": \"warm\",\n  \"evidence\": \"180 employees, listed industry Computer and Network Security, HQ Tel Aviv\",\n  \"missing\": [\"funding stage not visible on the company page\"],\n  \"objection\": \"may already run a competing product\"\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "cd3",
      "name": "Associate Scores with Companies",
      "type": "n8n-nodes-base.code",
      "position": [
        3364,
        460
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Pair each score back to its company. informationExtractor preserves order.\nconst companies = $('Flatten Company Records').all();\nconst cfg = $('Set Search Parameters').first().json;\n\nreturn $input.all().map((item, i) => {\n  const c = companies[i]?.json ?? {};\n  const s = item.json.output ?? {};\n  const score = Number(s.score ?? 0);\n  return { json: {\n    run_id: cfg.run_id,\n    scored_at: $now.toISO(),\n    name: c.name,\n    website: c.website,\n    linkedin_url: c.linkedin_url,\n    industry: c.industry,\n    employees: c.employees,\n    headquarters: c.headquarters,\n    score,\n    tier: s.tier ?? '',\n    evidence: s.evidence ?? '',\n    missing: Array.isArray(s.missing) ? s.missing.join('; ') : (s.missing ?? ''),\n    objection: s.objection ?? '',\n    qualified: score >= Number(cfg.min_score),\n  }};\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "if1",
      "name": "Evaluate Qualification Status",
      "type": "n8n-nodes-base.if",
      "position": [
        3760,
        460
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond1",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.qualified }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "g1",
      "name": "Append Qualified to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        4000,
        260
      ],
      "parameters": {
        "columns": {
          "value": {},
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Qualified"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/REPLACE_WITH_YOUR_SHEET_ID/edit"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "g2",
      "name": "Append Rejected to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueRegularOutput",
      "position": [
        4000,
        700
      ],
      "parameters": {
        "columns": {
          "value": {},
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Rejected"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "https://docs.google.com/spreadsheets/d/REPLACE_WITH_YOUR_SHEET_ID/edit"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "ag2",
      "name": "Aggregate Qualified Leads",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        4240,
        260
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "leads"
      },
      "typeVersion": 1
    },
    {
      "id": "sl1",
      "name": "Post Lead Digest to Slack",
      "type": "n8n-nodes-base.slack",
      "onError": "continueRegularOutput",
      "position": [
        4480,
        260
      ],
      "parameters": {
        "text": "=*{{ $json.leads.length }} qualified companies*\\n\\n{{ $json.leads.sort((a,b) => b.score - a.score).slice(0, 15).map(l => `${l.score} - *${l.name}* (${l.employees || '?'} staff, ${l.headquarters || '?'})\\n   ${l.evidence}\\n   ${l.linkedin_url}`).join('\\n\\n') }}",
        "select": "channel",
        "resource": "message",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#alerts"
        },
        "operation": "post",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Evaluate ICP Scores": {
      "main": [
        [
          {
            "node": "Associate Scores with Companies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit Company Count": {
      "main": [
        [
          {
            "node": "Aggregate URLs for Scraper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Scoring Model": {
      "ai_languageModel": [
        [
          {
            "node": "Evaluate ICP Scores",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Set Search Parameters": {
      "main": [
        [
          {
            "node": "Extract Queries from ICP",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flatten Company Records": {
      "main": [
        [
          {
            "node": "Evaluate ICP Scores",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to Bright Data API": {
      "main": [
        [
          {
            "node": "Filter LinkedIn Company URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When ICP Form Submitted": {
      "main": [
        [
          {
            "node": "Set Search Parameters",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Queries from ICP": {
      "main": [
        [
          {
            "node": "Split Queries for Processing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Qualified Leads": {
      "main": [
        [
          {
            "node": "Post Lead Digest to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate URLs for Scraper": {
      "main": [
        [
          {
            "node": "Post to LinkedIn Scraper API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Qualified to Sheets": {
      "main": [
        [
          {
            "node": "Aggregate Qualified Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Query Planner Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Queries from ICP",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Filter LinkedIn Company URLs": {
      "main": [
        [
          {
            "node": "Limit Company Count",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Post to LinkedIn Scraper API": {
      "main": [
        [
          {
            "node": "Flatten Company Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Queries for Processing": {
      "main": [
        [
          {
            "node": "Post to Bright Data API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Evaluate Qualification Status": {
      "main": [
        [
          {
            "node": "Append Qualified to Sheets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Append Rejected to Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Associate Scores with Companies": {
      "main": [
        [
          {
            "node": "Evaluate Qualification Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}