{
  "name": "Dievio B2B Lead Collector (API -> Google Sheets)",
  "settings": {
    "executionOrder": "v1",
    "availableInMCP": false,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "dievio-b2b-leads",
        "responseMode": "responseNode",
        "options": {},
        "authentication": "headerAuth"
      },
      "id": "webhook-in",
      "name": "Webhook In",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -1248,
        128
      ],
      "webhookId": "048c046d-2738-4d80-92bd-75c1d58760f8"
    },
    {
      "parameters": {
        "jsCode": "const payload = $json.body ?? $json;\nconst spreadsheetId = 'REPLACE_WITH_SPREADSHEET_ID';\nconst sheetName = 'Leads';\n\nfunction invalid(error) {\n  return [{ json: { ok: false, error } }];\n}\n\nif (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n  return invalid('Send a JSON object.');\n}\nif (spreadsheetId === 'REPLACE_WITH_SPREADSHEET_ID' || !/^[A-Za-z0-9_-]+$/.test(spreadsheetId)) {\n  return invalid('Set the spreadsheet ID in Prepare Request before running this workflow.');\n}\nconst fixedSettings = ['endpoint', 'spreadsheetId', 'sheetId', 'sheetName', 'googleSheets', 'includeRaw', '_include_raw'];\nif (fixedSettings.some(key => Object.hasOwn(payload, key))) {\n  return invalid('The API endpoint and Google Sheets destination are configured in the workflow.');\n}\nconst maxResults = Number(payload.maxResults ?? 1);\nif (!Number.isInteger(maxResults) || maxResults < 1 || maxResults > 100) {\n  return invalid('maxResults must be an integer from 1 to 100.');\n}\nconst filters = payload.filters ?? {};\nif (!filters || typeof filters !== 'object' || Array.isArray(filters)) {\n  return invalid('filters must be a JSON object.');\n}\nconst emailStatus = payload.emailStatus ?? 'all';\nif (!['all', 'verified', 'likely', 'work'].includes(emailStatus)) {\n  return invalid('emailStatus must be all, verified, likely or work.');\n}\nif (emailStatus === 'work' && payload.includeEmails === false) {\n  return invalid('Use includeEmails: true when requesting work email.');\n}\n\nreturn [{ json: {\n  ok: true,\n  requestId: 'dievio-' + $execution.id,\n  config: { spreadsheetId, sheetName, maxResults },\n  filters,\n  includeEmails: payload.includeEmails !== false,\n  includePhones: payload.includePhones === true,\n  emailStatus\n} }];"
      },
      "id": "prepare-request",
      "name": "Prepare Request",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1024,
        128
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "request-is-valid",
              "leftValue": "={{ $json.ok }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "is-valid",
      "name": "Is Request Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -800,
        128
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{$json}}",
        "options": {
          "responseCode": 400
        }
      },
      "id": "respond-validation-error",
      "name": "Respond Validation Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        -576,
        272
      ]
    },
    {
      "parameters": {
        "jsCode": "const { config, filters, requestId, includeEmails, includePhones, emailStatus } = $json;\n\nreturn [{ json: {\n  requestId,\n  config,\n  dievioBody: {\n    ...filters,\n    _page: 1,\n    _per_page: config.maxResults,\n    max_results: config.maxResults,\n    _include_raw: false,\n    include_raw: false,\n    include_emails: includeEmails,\n    include_phones: includePhones,\n    email_status: emailStatus\n  }\n} }];"
      },
      "id": "fetch-dievio",
      "name": "Fetch Dievio Leads",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -576,
        48
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "has-matching-leads",
              "leftValue": "={{ $json.leadsCount }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "has-leads",
      "name": "Has Leads?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -320,
        224
      ]
    },
    {
      "parameters": {
        "jsCode": "return [{ json: {\n  ok: true,\n  requestId: $json.requestId,\n  totalLeads: 0,\n  writtenRows: 0,\n  pagesFetched: $json.pagesFetched,\n  hasMore: $json.hasMore,\n  sheetWritten: false\n} }];"
      },
      "id": "build-empty-response",
      "name": "Build Empty Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -96,
        368
      ]
    },
    {
      "parameters": {
        "jsCode": "return $json.leads.map(lead => ({ json: lead }));"
      },
      "id": "expand-leads",
      "name": "Expand Lead Items",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -96,
        160
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Prepare Request').first().json.config.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $('Prepare Request').first().json.config.sheetName }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "request_id",
              "displayName": "request_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "collected_at",
              "displayName": "collected_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "first_name",
              "displayName": "first_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "last_name",
              "displayName": "last_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "full_name",
              "displayName": "full_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "job_title",
              "displayName": "job_title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company",
              "displayName": "company",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "city",
              "displayName": "city",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "state",
              "displayName": "state",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "country",
              "displayName": "country",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "work_email",
              "displayName": "work_email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "email_status",
              "displayName": "email_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mobile_phone",
              "displayName": "mobile_phone",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "phone_status",
              "displayName": "phone_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "linkedin_url",
              "displayName": "linkedin_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "linkedin_status",
              "displayName": "linkedin_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "twitter_status",
              "displayName": "twitter_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "facebook_status",
              "displayName": "facebook_status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "cellFormat": "RAW",
          "useAppend": true
        }
      },
      "id": "append-to-sheets",
      "name": "Append Rows To Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        160,
        160
      ]
    },
    {
      "parameters": {
        "jsCode": "const run = $('Normalize Dievio Leads').first().json;\n\nreturn [{ json: {\n  ok: true,\n  requestId: run.requestId,\n  totalLeads: run.leadsCount,\n  writtenRows: run.leadsCount,\n  pagesFetched: run.pagesFetched,\n  hasMore: run.hasMore,\n  sheetWritten: true\n} }];"
      },
      "id": "build-success-response",
      "name": "Build Success Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        368,
        160
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{$json}}",
        "options": {}
      },
      "id": "respond-final",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        592,
        256
      ]
    },
    {
      "parameters": {
        "content": "## Dievio B2B leads to Google Sheets\nConfigure separate Header Auth credentials in Webhook In and Run Dievio Search. Set the destination in Prepare Request and connect your Google Sheets credential. Test with maxResults: 1 before activating.",
        "height": 700,
        "width": 760,
        "color": 7
      },
      "id": "note-guide",
      "name": "Workflow Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1824,
        -768
      ]
    },
    {
      "parameters": {
        "content": "## Test request body\n```json\n{ \"maxResults\": 1, \"emailStatus\": \"work\", \"filters\": { \"company_websites\": [\"stripe.com\"], \"job_titles\": [\"Founder\"] } }\n```",
        "height": 760,
        "width": 780,
        "color": 5
      },
      "id": "note-example",
      "name": "Request Example Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -1024,
        -768
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://dievio.com/api/public/search",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{$json.dievioBody}}",
        "options": {
          "timeout": 120000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        },
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "id": "run-dievio-search",
      "name": "Run Dievio Search",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -368,
        -32
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = $json;\nconst ctx = $('Fetch Dievio Leads').first().json;\nif (response.success !== true || !Array.isArray(response.preview_data)) {\n  throw new Error('Dievio search did not return the expected results.');\n}\nconst rows = response.preview_data;\n\nconst leads = rows.slice(0, ctx.config.maxResults).map((lead) => ({\n  request_id: ctx.requestId,\n  collected_at: new Date().toISOString(),\n  first_name: lead.first_name ?? '',\n  last_name: lead.last_name ?? '',\n  full_name: lead.full_name ?? [lead.first_name, lead.last_name].filter(Boolean).join(' '),\n  job_title: lead.job_title ?? '',\n  company: lead.company ?? '',\n  city: lead.city ?? '',\n  state: lead.state ?? '',\n  country: lead.country ?? '',\n  work_email: lead.work_email ?? '',\n  email_status: lead.email_status ?? '',\n  mobile_phone: lead.mobile_phone ?? '',\n  phone_status: lead.phone_status ?? '',\n  linkedin_url: lead.linkedin_url ?? '',\n  linkedin_status: lead.linkedin_status ?? '',\n  twitter_status: lead.twitter_status ?? '',\n  facebook_status: lead.facebook_status ?? ''\n}));\n\nreturn [{\n  json: {\n    ok: true,\n    requestId: ctx.requestId,\n    config: ctx.config,\n    pagesFetched: 1,\n    hasMore: response.has_more === true,\n    leadsCount: leads.length,\n    leads\n  }\n}];"
      },
      "id": "normalize-dievio-leads",
      "name": "Normalize Dievio Leads",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -80,
        -32
      ]
    }
  ],
  "connections": {
    "Webhook In": {
      "main": [
        [
          {
            "node": "Prepare Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Request": {
      "main": [
        [
          {
            "node": "Is Request Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Request Valid?": {
      "main": [
        [
          {
            "node": "Fetch Dievio Leads",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Validation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Dievio Leads": {
      "main": [
        [
          {
            "node": "Run Dievio Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Leads?": {
      "main": [
        [
          {
            "node": "Expand Lead Items",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Empty Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Expand Lead Items": {
      "main": [
        [
          {
            "node": "Append Rows To Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Rows To Google Sheets": {
      "main": [
        [
          {
            "node": "Build Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Success Response": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Empty Response": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Dievio Search": {
      "main": [
        [
          {
            "node": "Normalize Dievio Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Dievio Leads": {
      "main": [
        [
          {
            "node": "Has Leads?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "versionId": "6f3fb5ed-4df4-4f7a-8c7c-0c32a57731b5"
}
