{
  "id": "GuwtmolHpSZYA8lW",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Tax-ID Verification - Groq + PDF + Lovable",
  "tags": [
    {
      "id": "7O26FSCVRdaD3J6i",
      "name": "lovable",
      "createdAt": "2026-08-06T11:54:17.397Z",
      "updatedAt": "2026-08-06T11:54:17.397Z"
    },
    {
      "id": "Fs23y8VBhrRrZSjQ",
      "name": "groq",
      "createdAt": "2026-08-06T11:54:17.338Z",
      "updatedAt": "2026-08-06T11:54:17.338Z"
    },
    {
      "id": "V6qrZh5OMy0YYKis",
      "name": "tax-verification",
      "createdAt": "2026-08-06T11:54:17.369Z",
      "updatedAt": "2026-08-06T11:54:17.369Z"
    },
    {
      "id": "fAc4NquWRUBXKvh2",
      "name": "google-sheets",
      "createdAt": "2026-08-06T11:54:17.421Z",
      "updatedAt": "2026-08-06T11:54:17.421Z"
    },
    {
      "id": "sU9NqRnBGLmULKHh",
      "name": "pdf-intake",
      "createdAt": "2026-08-06T11:54:17.450Z",
      "updatedAt": "2026-08-06T11:54:17.450Z"
    }
  ],
  "nodes": [
    {
      "id": "f33029c2-37a2-4fba-a601-c37c1e93291d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4512,
        -992
      ],
      "parameters": {
        "width": 480,
        "height": 704,
        "content": "## AI Tax ID Verification - Groq + PDF + Lovable\n\n### How it works\n\n1. The workflow is triggered by a webhook from Lovable.\n2. It checks for duplicate filenames in Google Sheets.\n3. If a duplicate is found, it returns a cached result.\n4. Otherwise, it extracts the text layer from a PDF and sends it to Groq for parsing.\n5. The parsed tax document is then validated and checked against a database.\n6. Based on the validation result, it updates the database record or logs an unknown tax ID.\n\n### Setup steps\n\n- - [ ] Set up a Google Sheets node with the verification log.\n- - [ ] Configure a webhook trigger from Lovable.\n- - [ ] Set up a Groq API endpoint for parsing tax documents.\n\n### Customization\n\nThe workflow can be customized by modifying the Groq API endpoint, Google Sheets node, or the webhook trigger."
      },
      "typeVersion": 1
    },
    {
      "id": "17931b2d-36af-484b-b552-e778a091164d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3888,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 304,
        "content": "## Initial Trigger & Normalisation\n\nWebhook trigger from Lovable"
      },
      "typeVersion": 1
    },
    {
      "id": "6d16aff9-74a4-4ea3-a669-28f453bf9e74",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3504,
        -592
      ],
      "parameters": {
        "color": 7,
        "width": 1200,
        "height": 448,
        "content": "## Duplicate Check\n\nChecks for duplicates and returns cached result if found"
      },
      "typeVersion": 1
    },
    {
      "id": "47b72932-1f91-4b90-9f04-f4d3b90315b6",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2720,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 464,
        "content": "## PDF Extraction and Groq Parsing\n\nExtracts text layer from PDF and sends to Groq for parsing"
      },
      "typeVersion": 1
    },
    {
      "id": "c419cf6c-c707-4cf6-aa01-b4c45215cc94",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2160,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 912,
        "height": 288,
        "content": "## Tax ID Extraction and Validation\n\nExtracts tax ID and validates it"
      },
      "typeVersion": 1
    },
    {
      "id": "38c70368-5fd7-4614-9884-55a34b98fe61",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 272,
        "content": "## Final Compliance Verdict\n\nSends the final compliance verdict to Groq"
      },
      "typeVersion": 1
    },
    {
      "id": "29801a58-275b-4989-8c49-b5162fe12e90",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        -592
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 560,
        "content": "## Verification Log and DB Update\n\nWrites the verification log and updates the database record"
      },
      "typeVersion": 1
    },
    {
      "id": "9ed96a8c-53f1-44c1-ba9d-3358c9b7b9cd",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        -448
      ],
      "parameters": {
        "color": 7,
        "height": 336,
        "content": "## Route by Final Status\n\nRoutes the workflow based on the final status"
      },
      "typeVersion": 1
    },
    {
      "id": "ebe92df6-5928-4a88-ae81-d67478a6d5b7",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -672
      ],
      "parameters": {
        "color": 7,
        "height": 800,
        "content": "## Send Messages\n\nSends messages based on the final status"
      },
      "typeVersion": 1
    },
    {
      "id": "32d21bf8-8727-4ab1-a8c3-c9d0f88d811f",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        624,
        -448
      ],
      "parameters": {
        "color": 7,
        "height": 304,
        "content": "## Return JSON to Lovable\n\nReturns the JSON response to Lovable"
      },
      "typeVersion": 1
    },
    {
      "id": "01e0537b-11b8-4f72-8e78-73f8ea8e7368",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1888,
        -112
      ],
      "parameters": {
        "color": 7,
        "height": 304,
        "content": "## No Tax ID Found\n\nResponds with no tax ID found"
      },
      "typeVersion": 1
    },
    {
      "id": "d41c20b7-0925-432e-bf61-da88d62a69b7",
      "name": "Filename Duplicate Check",
      "type": "n8n-nodes-base.code",
      "position": [
        -3456,
        -304
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\n\nconst fileName = (\n  item[\"File Name\"] || item.file_name || ''\n).trim().toLowerCase();\n\nconst submitter = (\n  item[\"Submitted By\"] || item.submitted_by || ''\n).trim().toLowerCase();\n\nconst org = (\n  item[\"Organization\"] || item.organization || ''\n).trim().toLowerCase();\n\nconst fingerprint = fileName || org || submitter || '';\n\nreturn [{ json: {\n  ...item,\n  quick_tax_id:       '',\n  duplicate_check_id: fingerprint,\n  fingerprint:        fingerprint,\n  fingerprint_type:   fileName ? 'filename'\n                    : org      ? 'organization'\n                    : 'submitter'\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "7ab1c8e2-9dcb-4b23-b098-c07d1ea9dd5b",
      "name": "Sheets \u2014 Lookup Verification Log",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -3264,
        -304
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "headerRow": 3,
              "firstDataRow": 4,
              "rangeDefinition": "specifyRange"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1692878098,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit#gid=1692878098",
          "cachedResultName": "Verification_Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit?usp=drivesdk",
          "cachedResultName": "TaxID verify&Logs"
        },
        "combineFilters": "OR"
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "2e3609d2-e163-4601-8ccd-eb00613b73c1",
      "name": "Duplicate Decision",
      "type": "n8n-nodes-base.code",
      "position": [
        -3088,
        -304
      ],
      "parameters": {
        "jsCode": "const incoming  = $('Filename Duplicate Check').first().json;\nconst rows      = $input.all();\nconst fp        = (incoming.fingerprint || '').toLowerCase();\n\nconst existingRows = rows.filter(r => {\n  const f = (\n    r.json['File Name'] || r.json['file_name'] || ''\n  ).trim().toLowerCase();\n  return f.length > 0 && f === fp;\n});\n\nconst isDuplicate    = existingRows.length > 0;\nconst existingRecord = isDuplicate\n  ? existingRows[existingRows.length - 1].json\n  : null;\n\n// \u2500\u2500 Calculate cache freshness \u2500\u2500\nlet cacheHit   = false;\nlet hoursSince = 999;\n\nif (existingRecord) {\n  const completedRaw = \n    existingRecord['Completed At'] ||\n    existingRecord['completed_at'] || '';\n\n  if (completedRaw) {\n    const completedAt = new Date(completedRaw);\n    // Check it parsed correctly\n    if (!isNaN(completedAt.getTime())) {\n      hoursSince = (Date.now() - completedAt.getTime()) / 3600000;\n      cacheHit   = hoursSince < 24;\n    }\n  }\n}\n\n// \u2500\u2500 IMPORTANT: do NOT spread ...incoming \u2500\u2500\n// Build output fresh so no stale cache_hit leaks through\nreturn [{ json: {\n  // Carry forward only what we need\n  \"Request ID\":      incoming[\"Request ID\"]    || incoming.request_id,\n  \"Received At\":     incoming[\"Received At\"]   || incoming.received_at,\n  \"Completed At\":    incoming[\"Completed At\"]  || incoming.received_at,\n  \"Submitted By\":    incoming[\"Submitted By\"]  || incoming.submitted_by,\n  \"Email\":           incoming[\"Email\"]         || incoming.submission_email,\n  \"Organization\":    incoming[\"Organization\"]  || incoming.organization,\n  \"File Name\":       incoming[\"File Name\"]     || incoming.file_name,\n  pdf_base64:        incoming.pdf_base64,\n  request_id:        incoming[\"Request ID\"]    || incoming.request_id,\n  submitted_by:      incoming[\"Submitted By\"]  || incoming.submitted_by,\n  submission_email:  incoming[\"Email\"]         || incoming.submission_email,\n  organization:      incoming[\"Organization\"]  || incoming.organization,\n  file_name:         incoming[\"File Name\"]     || incoming.file_name,\n  received_at:       incoming[\"Received At\"]   || incoming.received_at,\n  fingerprint:       incoming.fingerprint,\n  fingerprint_type:  incoming.fingerprint_type,\n\n  // \u2500\u2500 Duplicate result \u2014 set explicitly, never from spread \u2500\u2500\n  is_duplicate:          isDuplicate,\n  cache_hit:             cacheHit,           // \u2190 explicitly calculated\n  hours_since_last_run:  parseFloat(hoursSince.toFixed(1)),\n  existing_final_status: existingRecord ? (existingRecord['Final Status']      || '') : '',\n  existing_risk_score:   existingRecord ? (existingRecord['Risk Score']         || 0)  : 0,\n  existing_risk_level:   existingRecord ? (existingRecord['Risk Level']         || '') : '',\n  existing_ai_summary:   existingRecord ? (existingRecord['AI Summary']         || '') : '',\n  existing_completed_at: existingRecord ? (existingRecord['Completed At']       || '') : '',\n  existing_request_id:   existingRecord ? (existingRecord['Request ID']         || '') : '',\n  existing_entity_name:  existingRecord ? (existingRecord['Entity Name (Doc)']  || '') : '',\n  existing_tax_id:       existingRecord ? (existingRecord['Tax ID Normalized']  || '') : '',\n\n  // \u2500\u2500 Debug (remove after confirmed) \u2500\u2500\n  _debug_fp:             fp,\n  _debug_rows_found:     existingRows.length,\n  _debug_completed_raw:  existingRecord ? (existingRecord['Completed At'] || 'EMPTY') : 'NO_RECORD',\n  _debug_hours:          parseFloat(hoursSince.toFixed(1)),\n  _debug_cache_hit:      cacheHit\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "e1266690-bc28-4ce3-aaf6-2dda6549f43a",
      "name": "Switch \u2014 Duplicate Route",
      "type": "n8n-nodes-base.switch",
      "position": [
        -2912,
        -304
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Output 1 \u2014 Cache hit",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3c804646-aa9f-4560-b3fd-c3842dde1047",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.is_duplicate }}",
                    "rightValue": "true"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Output 2 \u2014 New ",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "906a1da3-cc87-4d56-84e7-8273b74a37c1",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.is_duplicate }}",
                    "rightValue": "false"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {},
        "looseTypeValidation": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "a7fc659d-8225-46f0-b03e-dcbb8a3c821b",
      "name": "Return Cached Result",
      "type": "n8n-nodes-base.code",
      "position": [
        -2672,
        -480
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\n\nreturn [{ json: {\n  success:            true,\n  final_status:       'DUPLICATE',\n  is_duplicate:       true,\n  cache_hit:          true,\n  request_id:         item.existing_request_id,\n  new_request_id:     item['Request ID'] || item.request_id,\n  tax_id_normalized:  item.existing_tax_id,\n  entity_name:        item.existing_entity_name,\n  risk_score:         item.existing_risk_score,\n  risk_level:         item.existing_risk_level,\n  ai_confidence:      100,\n  compliance_flags:   [],\n  summary:            item.existing_ai_summary,\n  recommended_action: 'No action required \u2014 cached result',\n  hours_since:        item.hours_since_last_run,\n  completed_at:       item.existing_completed_at,\n  message:            'This document was verified ' + item.hours_since_last_run + ' hours ago. Returning cached result.',\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b08c42ee-53ca-4d1c-ba2a-2c6c3a5721c9",
      "name": "Webhook \u2014 Lovable Form POST1",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -3840,
        -304
      ],
      "parameters": {
        "path": "tax-ID-verify",
        "options": {
          "allowedOrigins": "*"
        },
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "4d60e321-c15b-4e79-ac97-a11c9b04c9dc",
      "name": "Normalize Lovable Payload1",
      "type": "n8n-nodes-base.code",
      "position": [
        -3648,
        -304
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 INTAKE: normalize Lovable form payload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst body = $input.first().json.body || $input.first().json;\n\nconst requestId = 'TXID-'\n  + new Date().toISOString().slice(0,10).replace(/-/g,'')\n  + '-'\n  + Math.random().toString(36).substring(2,8).toUpperCase();\n\nconst pdfBase64 = (body.pdf_base64 || '').replace(/^data:application\\/pdf;base64,/, '');\nconst fileName  = body.file_name   || body.fileName || 'tax_document.pdf';\nconst submitter = body.submitted_by || body.name    || 'Unknown';\nconst email     = body.email        || '';\nconst org       = body.organization || '';\n\nif (!pdfBase64) {\n  throw new Error('NO_PDF: pdf_base64 field is empty or missing');\n}\n\nconst now = new Date().toISOString();\n\nreturn [{ json: {\n  // \u2500\u2500 Matches sheet Row 3 headers EXACTLY (capitals + spaces) \u2500\u2500\n  \"Request ID\":           requestId,\n  \"Received At\":          now,\n  \"Completed At\":         now,\n  \"Submitted By\":         submitter,\n  \"Email\":                email,\n  \"Organization\":         org,\n  \"File Name\":            fileName,\n  \"Entity Name (Doc)\":    '',\n  \"Tax ID Raw\":           '',\n  \"Tax ID Normalized\":    '',\n  \"Tax ID Type\":          '',\n  \"Doc Type\":             '',\n  \"Tax Year\":             '',\n  \"Signature\":            false,\n  \"Format Valid\":         false,\n  \"Format Error\":         '',\n  \"DB Match Score\":       0,\n  \"DB Entity Name\":       '',\n  \"DB Status\":            '',\n  \"Name Mismatch\":        false,\n  \"Final Status\":         'PROCESSING',\n  \"Risk Level\":           '',\n  \"Risk Score\":           0,\n  \"AI Confidence\":        0,\n  \"Compliance Flags\":     '',\n  \"AI Summary\":           '',\n  \"Recommended Action\":   '',\n  \"Parse Confidence\":     0,\n\n  // \u2500\u2500 Internal fields (not written to sheet, used by pipeline nodes) \u2500\u2500\n  pdf_base64:             pdfBase64,\n  request_id:             requestId,\n  submitted_by:           submitter,\n  submission_email:       email,\n  organization:           org,\n  file_name:              fileName,\n  received_at:            now,\n  status:                 'PROCESSING'\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "a8cdfcb1-1bb2-4947-9d5f-5a35f388ca5b",
      "name": "Extract PDF Text Layer1",
      "type": "n8n-nodes-base.code",
      "position": [
        -2672,
        208
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst b64  = item.pdf_base64 || '';\n\nlet extractedText = '';\n\ntry {\n  const buf = Buffer.from(b64, 'base64');\n  const raw = buf.toString('binary');\n\n  const found = [];\n\n  // \u2500\u2500 Pull all literal strings from PDF parenthesis notation (Tj / TJ ops) \u2500\u2500\n  const parenStrings = raw.match(/\\(([^\\)\\\\]{1,200})\\)/g) || [];\n  for (const s of parenStrings) {\n    const inner = s.slice(1, -1).trim();\n    // Keep only strings with real alphanumeric content\n    if (/[a-zA-Z0-9@\\.\\-]/.test(inner) && inner.length >= 2) {\n      found.push(inner);\n    }\n  }\n\n  // \u2500\u2500 Directly scan for EIN / SSN / 9-digit patterns \u2500\u2500\n  const eins = raw.match(/\\b\\d{2}[-\\s]?\\d{7}\\b/g) || [];\n  const ssns = raw.match(/\\b\\d{3}[-\\s]?\\d{2}[-\\s]?\\d{4}\\b/g) || [];\n  const nine = raw.match(/\\b\\d{9}\\b/g) || [];\n\n  // \u2500\u2500 Also try UTF-8 decode for modern PDFs \u2500\u2500\n  let utf8text = '';\n  try {\n    utf8text = Buffer.from(b64, 'base64').toString('utf8');\n    // pull any lines that look like real text\n    const lines = utf8text.split(/[\\r\\n]+/);\n    for (const line of lines) {\n      const clean = line.replace(/[^\\x20-\\x7E]/g, ' ').trim();\n      if (clean.length > 4 && /[a-zA-Z]{2,}/.test(clean)) {\n        found.push(clean);\n      }\n    }\n  } catch(e) {}\n\n  // \u2500\u2500 Combine everything \u2500\u2500\n  const allText = [\n    ...found,\n    ...eins,\n    ...ssns,\n    ...nine\n  ].join(' ').replace(/\\s+/g, ' ').trim();\n\n  // \u2500\u2500 Remove pure PDF operator noise \u2500\u2500\n  extractedText = allText\n    .replace(/\\b(obj|endobj|stream|endstream|xref|trailer|startxref|BT|ET)\\b/g, ' ')\n    .replace(/\\/(BaseFont|Subtype|Encoding|Type|FontDescriptor|WinAnsiEncoding|Name)\\b/g, ' ')\n    .replace(/\\s+/g, ' ')\n    .substring(0, 5000)\n    .trim();\n\n} catch(e) {\n  extractedText = '[extraction error: ' + e.message + ']';\n}\n\nreturn [{\n  json: {\n    ...item,\n    pdf_text:     extractedText || '[no readable text found]',\n    pdf_text_len: extractedText.length\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "bde51d20-9cdd-4224-8bee-381a4d59a9c3",
      "name": "Groq \u2014 Parse PDF Tax Document1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2496,
        16
      ],
      "parameters": {
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({\n  \"model\": \"llama-3.3-70b-versatile\",\n  \"temperature\": 0.05,\n  \"max_tokens\": 600,\n  \"response_format\": { \"type\": \"json_object\" },\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"You are a tax document parser. The text may be messy or extracted from a PDF binary. Search aggressively for any 9-digit number, XX-XXXXXXX pattern, or XXX-XX-XXXX pattern. Return ONLY a JSON object.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": \"Find the Tax ID in this text. Look for patterns like 12-3456789 (EIN) or 123-45-6789 (SSN) or any 9 consecutive digits. The document is a W-9 form.\\n\\nReturn JSON: {tax_id, tax_id_raw, tax_id_type, entity_name, doc_type, tax_year, signature_present, parse_confidence, parse_notes}\\n\\nText:\\n\" + $json.pdf_text\n    }\n  ]\n}) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7f876872-4051-4e20-a2c9-6a25a365cabf",
      "name": "Parse Groq Extract Response1",
      "type": "n8n-nodes-base.code",
      "position": [
        -2304,
        16
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst prev = $('Normalize Lovable Payload1').first().json;\n\nlet raw = '';\ntry {\n  raw = item.choices[0].message.content;\n} catch(e) {\n  raw = '';\n}\n\nraw = raw.replace(/\\\\n/g, ' ').replace(/\\n/g, ' ').trim();\n\nlet parsed = {};\ntry {\n  parsed = JSON.parse(raw);\n} catch(e) {\n  const match = raw.match(/\\{[\\s\\S]+\\}/);\n  if (match) {\n    try { parsed = JSON.parse(match[0]); } catch(e2) {\n      parsed = {\n        tax_id: '', tax_id_raw: '', tax_id_type: 'UNKNOWN',\n        entity_name: '', doc_type: 'UNKNOWN',\n        tax_year: null, signature_present: false,\n        parse_confidence: 0,\n        parse_notes: 'Parse failed: ' + e.message\n      };\n    }\n  }\n}\n\nreturn [{\n  json: {\n    // \u2500\u2500 Sheet headers (capitals + spaces) \u2500\u2500\n    \"Request ID\":        prev[\"Request ID\"]    || prev.request_id,\n    \"Received At\":       prev[\"Received At\"]   || prev.received_at,\n    \"Completed At\":      prev[\"Completed At\"]  || prev.received_at,\n    \"Submitted By\":      prev[\"Submitted By\"]  || prev.submitted_by,\n    \"Email\":             prev[\"Email\"]         || prev.submission_email,\n    \"Organization\":      prev[\"Organization\"]  || prev.organization,\n    \"File Name\":         prev[\"File Name\"]     || prev.file_name,\n    \"Entity Name (Doc)\": parsed.entity_name    || '',\n    \"Tax ID Raw\":        parsed.tax_id_raw     || parsed.tax_id || '',\n    \"Tax ID Normalized\": parsed.tax_id         || '',\n    \"Tax ID Type\":       parsed.tax_id_type    || 'UNKNOWN',\n    \"Doc Type\":          parsed.doc_type       || 'UNKNOWN',\n    \"Tax Year\":          parsed.tax_year       || '',\n    \"Signature\":         parsed.signature_present || false,\n    \"Format Valid\":      false,\n    \"Format Error\":      '',\n    \"DB Match Score\":    0,\n    \"DB Entity Name\":    '',\n    \"DB Status\":         '',\n    \"Name Mismatch\":     false,\n    \"Final Status\":      'PROCESSING',\n    \"Risk Level\":        '',\n    \"Risk Score\":        0,\n    \"AI Confidence\":     0,\n    \"Compliance Flags\":  '',\n    \"AI Summary\":        '',\n    \"Recommended Action\":'',\n    \"Parse Confidence\":  parsed.parse_confidence || 0,\n\n    // \u2500\u2500 Internal pipeline fields (used by downstream nodes) \u2500\u2500\n    request_id:          prev[\"Request ID\"]    || prev.request_id,\n    submitted_by:        prev[\"Submitted By\"]  || prev.submitted_by,\n    submission_email:    prev[\"Email\"]         || prev.submission_email,\n    organization:        prev[\"Organization\"]  || prev.organization,\n    file_name:           prev[\"File Name\"]     || prev.file_name,\n    received_at:         prev[\"Received At\"]   || prev.received_at,\n    tax_id:              parsed.tax_id         || '',\n    tax_id_raw:          parsed.tax_id_raw     || parsed.tax_id || '',\n    tax_id_type:         parsed.tax_id_type    || 'UNKNOWN',\n    entity_name:         parsed.entity_name    || '',\n    doc_type:            parsed.doc_type       || 'UNKNOWN',\n    tax_year:            parsed.tax_year       || null,\n    signature_present:   parsed.signature_present || false,\n    parse_confidence:    parsed.parse_confidence  || 0,\n    parse_notes:         parsed.parse_notes       || ''\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "10490a9b-050d-4ffc-a7a3-053766510ddb",
      "name": "Tax ID Extracted?1",
      "type": "n8n-nodes-base.if",
      "position": [
        -2112,
        -304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-has-taxid",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.tax_id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "01818249-868a-4a0b-aa60-c91fd82391ab",
      "name": "Format Validation1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1888,
        -320
      ],
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst rawId  = item[\"Tax ID Normalized\"] || item.tax_id_normalized ||\n               item[\"Tax ID Raw\"]        || item.tax_id_raw        ||\n               item.tax_id              || '';\nconst taxType = item[\"Tax ID Type\"] || item.tax_id_type || 'UNKNOWN';\n\nlet ok = false, normalized = rawId.replace(/-/g,''), err = null;\nconst raw = normalized;\n\nif (taxType === 'EIN' && /^\\d{9}$/.test(raw)) {\n  const prefix = parseInt(raw.substring(0,2));\n  const bad    = [0,7,8,9,17,18,19,28,29,49,69,70,78,79,89,96,97];\n  normalized   = raw.substring(0,2) + '-' + raw.substring(2);\n  ok           = !bad.includes(prefix);\n  if (!ok) err = 'EIN prefix ' + prefix + ' is not a valid IRS-assigned prefix';\n\n} else if (taxType === 'SSN' && /^\\d{9}$/.test(raw)) {\n  normalized = raw.substring(0,3)+'-'+raw.substring(3,5)+'-'+raw.substring(5);\n  if (raw==='+1234567890'||raw.substring(0,3)==='000'||raw.substring(3,5)==='00'||raw.substring(5)==='0000') {\n    err = 'SSN contains all-zero segment'; ok = false;\n  } else if (raw.substring(0,3)==='666'||parseInt(raw.substring(0,3))>=900) {\n    err = 'SSN area 666 or 900-999 is invalid'; ok = false;\n  } else { ok = true; }\n\n} else if (taxType === 'ITIN' && /^\\d{9}$/.test(raw)) {\n  normalized = raw.substring(0,3)+'-'+raw.substring(3,5)+'-'+raw.substring(5);\n  ok = raw[0]==='9' && ['70','71','72','73','74','75','76','77','78','79',\n       '80','81','82','83','84','85','86','87','88'].includes(raw.substring(3,5));\n  if (!ok) err = 'ITIN must start with 9 and have specific 4th-5th digit values';\n\n} else if (taxType === 'VAT' && raw.length >= 5) {\n  normalized = raw.toUpperCase(); ok = true;\n\n} else if (raw.length >= 5) {\n  ok = true;\n  err = 'Tax ID type unrecognized \u2014 proceeding with caution';\n\n} else {\n  err = 'Tax ID too short or unrecognized for type ' + taxType;\n}\n\nif (ok && /^(.)\\1+$/.test(raw)) {\n  ok = false; err = 'Tax ID is all repeating digits \u2014 invalid';\n}\n\nreturn [{ json: {\n  ...item,\n  // \u2500\u2500 Sheet-header keys \u2500\u2500\n  \"Tax ID Normalized\": normalized,\n  \"Format Valid\":      ok,\n  \"Format Error\":      err || '',\n  // \u2500\u2500 Internal keys \u2500\u2500\n  normalized_tax_id:   normalized,\n  format_valid:        ok,\n  format_error:        err || ''\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d1e99328-1c0b-41ec-b3a5-54af77aa523b",
      "name": "Google Sheets \u2014 Read TaxID Database1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1632,
        -320
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "headerRow": 3,
              "firstDataRow": 4,
              "rangeDefinition": "specifyRange"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1971988441,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit#gid=1971988441",
          "cachedResultName": "TaxID_Database"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit?usp=drivesdk",
          "cachedResultName": "TaxID verify&Logs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "3cd6b706-931e-42d6-8031-a8da8dc6a307",
      "name": "Database Lookup + Match Logic1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1392,
        -320
      ],
      "parameters": {
        "jsCode": "const incoming = $('Format Validation1').first().json;\n\n// \u2500\u2500 THIS is the only line that was wrong \u2014 reads BOTH formats \u2500\u2500\nconst submittedRaw =\n  incoming[\"Tax ID Normalized\"] ||\n  incoming[\"Tax ID Raw\"]        ||\n  incoming.normalized_tax_id    ||\n  incoming.tax_id_raw           ||\n  incoming.tax_id               || '';\n\nconst submitted = submittedRaw.replace(/-/g, '').toUpperCase();\n\nconst dbRows = $input.all();\nlet matchedRow = null, matchScore = 0;\n\nfor (const row of dbRows) {\n  const d     = row.json;\n  const rawId = d['Tax ID'] || d['tax_id'] || d['TAX ID'] || '';\n  const dbId  = rawId.replace(/[^0-9A-Za-z]/g, '').toUpperCase();\n  if (!dbId) continue;\n  if (dbId === submitted) { matchedRow = d; matchScore = 100; break; }\n  if (dbId.substring(0,6) === submitted.substring(0,6) && submitted.length >= 6) {\n    matchedRow = d; matchScore = 60;\n  }\n}\n\nconst exact   = matchScore === 100;\nconst partial = matchScore === 60;\n\nconst dbName  = matchedRow ? (matchedRow['Entity Name']              || matchedRow['entity_name']              || '') : '';\nconst dbStat  = matchedRow ? (matchedRow['Status']                   || matchedRow['status']                   || 'NOT_FOUND') : 'NOT_FOUND';\nconst dbActive= matchedRow ? (matchedRow['Active Since']             || matchedRow['active_since']             || '') : '';\nconst dbType  = matchedRow ? (matchedRow['Tax ID Type']              || matchedRow['tax_id_type']              || '') : '';\nconst dbState = matchedRow ? (matchedRow['Registered State']         || matchedRow['registered_state']         || '') : '';\nconst dbSource= matchedRow ? (matchedRow['Source']                   || matchedRow['source']                   || '') : '';\nconst dbLastV = matchedRow ? (matchedRow['Last Verified']            || matchedRow['last_verified']            || '') : '';\nconst dbLastR = matchedRow ? (matchedRow['Last Verification Result'] || matchedRow['last_verification_result'] || '') : '';\nconst dbRisk  = matchedRow ? (matchedRow['Last Risk Score']          || matchedRow['last_risk_score']          || '') : '';\nconst dbNotes = matchedRow ? (matchedRow['Notes']                    || matchedRow['notes']                    || '') : '';\n\nconst entityFromDoc = incoming[\"Entity Name (Doc)\"] || incoming.entity_name || '';\nconst formatValid   = incoming[\"Format Valid\"] ?? incoming.format_valid ?? false;\n\nlet nameMismatch = false;\nif (exact && dbName && entityFromDoc) {\n  const clean   = s => s.toLowerCase().replace(/[^a-z0-9 ]/g,'').split(' ').filter(w => w.length > 2);\n  const overlap = clean(dbName).filter(w => clean(entityFromDoc).includes(w)).length;\n  nameMismatch  = overlap === 0;\n}\n\nlet vr = 'UNVERIFIED';\nif (!formatValid)                                          vr = 'FORMAT_INVALID';\nelse if (!exact && !partial)                               vr = 'NOT_IN_DATABASE';\nelse if (exact && dbStat.toUpperCase().includes('REVOK'))  vr = 'REVOKED';\nelse if (exact && dbStat.toUpperCase().includes('SUSPEND'))vr = 'SUSPENDED';\nelse if (exact && nameMismatch)                            vr = 'ID_NAME_MISMATCH';\nelse if (partial && !exact)                                vr = 'POSSIBLE_MATCH_REVIEW';\nelse if (exact)                                            vr = 'VERIFIED';\n\nreturn [{ json: {\n  ...incoming,\n  // \u2500\u2500 Sheet-header keys \u2500\u2500\n  \"DB Match Score\":  matchScore,\n  \"DB Entity Name\":  dbName,\n  \"DB Status\":       dbStat,\n  \"Name Mismatch\":   nameMismatch,\n  \"Final Status\":    vr,\n  // \u2500\u2500 Internal keys \u2500\u2500\n  db_match_score:      matchScore,\n  db_exact_match:      exact,\n  db_partial_match:    partial,\n  db_entity_name:      dbName,\n  db_status:           dbStat,\n  db_active:           dbActive,\n  db_type:             dbType,\n  db_state:            dbState,\n  db_source:           dbSource,\n  db_last_verified:    dbLastV,\n  db_last_result:      dbLastR,\n  db_risk_score:       dbRisk,\n  db_notes:            dbNotes,\n  db_row:              matchedRow,\n  name_mismatch:       nameMismatch,\n  verification_result: vr,\n  is_verified:         vr === 'VERIFIED',\n  format_valid:        formatValid,\n  looked_up_at:        new Date().toISOString(),\n  // \u2500\u2500 Debug (remove after confirmed working) \u2500\u2500\n  _debug_submitted:    submitted,\n  _debug_raw_field:    submittedRaw,\n  _debug_rows:         dbRows.length\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "5d5cf0a3-6ca5-4fe1-ac3f-587223aab2af",
      "name": "Groq \u2014 Final Compliance Verdict1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1152,
        -320
      ],
      "parameters": {
        "url": "https://api.groq.com/openai/v1/chat/completions",
        "body": "={\"model\":\"llama-3.3-70b-versatile\",\"temperature\":0.05,\"max_tokens\":500,\"response_format\":{\"type\":\"json_object\"},\"messages\":[{\"role\":\"system\",\"content\":\"You are a tax compliance analyst. Return ONLY a JSON object.\"},{\"role\":\"user\",\"content\":\"Given these verification facts, issue a final compliance verdict. Return ONLY a JSON object with keys: final_status (VERIFIED or REJECTED or MANUAL_REVIEW), risk_level (LOW or MEDIUM or HIGH or CRITICAL), risk_score (integer 0-100), confidence (integer 0-100), flags (array of strings), summary (2 sentences plain English), recommended_action (string).\\n\\nFacts: tax_id={{ $json.normalized_tax_id }}, type={{ $json.tax_id_type }}, doc_entity={{ $json.entity_name }}, db_entity={{ $json.db_entity_name }}, format_valid={{ $json.format_valid }}, format_error={{ $json.format_error }}, db_match_score={{ $json.db_match_score }}, db_status={{ $json.db_status }}, name_mismatch={{ $json.name_mismatch }}, signature={{ $json.signature_present }}, parse_confidence={{ $json.parse_confidence }}, system_result={{ $json.verification_result }}\"}]}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "raw",
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "rawContentType": "application/json",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b06e6f66-3390-4916-91c3-8e50838bf9b3",
      "name": "Parse Groq Verdict1",
      "type": "n8n-nodes-base.code",
      "position": [
        -960,
        -320
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 Groq raw response comes via $input \u2500\u2500\nconst inputJson = $input.first().json;\n\n// \u2500\u2500 DB + document fields come from the named upstream node \u2500\u2500\nconst incoming = $('Database Lookup + Match Logic1').first().json;\n\n// \u2500\u2500 Parse Groq verdict from choices[0].message.content \u2500\u2500\nlet groqVerdict = {};\ntry {\n  const raw =\n    inputJson?.choices?.[0]?.message?.content ||\n    inputJson?.content ||\n    inputJson?.message?.content ||\n    '{}';\n  const cleaned = raw.replace(/```json|```/gi, '').trim();\n  groqVerdict = JSON.parse(cleaned);\n} catch (e) {\n  groqVerdict = {};\n}\n\nconst aiSummary         = groqVerdict.summary            || groqVerdict.ai_summary          || '';\nconst riskLevel         = groqVerdict.risk_level         || '';\nconst riskScore         = groqVerdict.risk_score         ?? 0;\nconst aiConfidence      = groqVerdict.confidence         ?? groqVerdict.ai_confidence       ?? 0;\nconst complianceFlags   = groqVerdict.flags              || groqVerdict.compliance_flags    || [];\nconst recommendedAction = groqVerdict.recommended_action || '';\nconst parseConfidence   = groqVerdict.parse_confidence   ?? groqVerdict.confidence          ?? 0;\n\n// \u2500\u2500 Read Tax ID \u2500\u2500\nconst submittedRaw =\n  incoming[\"Tax ID Normalized\"] ||\n  incoming.tax_id_normalized    ||\n  incoming[\"Tax ID Raw\"]        ||\n  incoming.tax_id_raw           ||\n  incoming.tax_id               || '';\nconst submitted = submittedRaw.replace(/-/g, '').toUpperCase();\n\n// \u2500\u2500 Read DB match results (already computed upstream) \u2500\u2500\nconst matchScore = incoming[\"DB Match Score\"] ?? incoming.db_match_score ?? 0;\nconst exact      = matchScore === 100;\nconst partial    = matchScore === 60;\n\nconst dbName   = incoming[\"DB Entity Name\"]           || incoming.db_entity_name   || '';\nconst dbStat   = incoming[\"DB Status\"]                || incoming.db_status        || 'NOT_FOUND';\nconst dbActive = incoming[\"Active Since\"]             || incoming.db_active        || '';\nconst dbType   = incoming[\"Tax ID Type\"]              || incoming.db_type          || '';\nconst dbState  = incoming[\"Registered State\"]         || incoming.db_state         || '';\nconst dbSource = incoming[\"Source\"]                   || incoming.db_source        || '';\nconst dbLastV  = incoming[\"Last Verified\"]            || incoming.db_last_verified || '';\nconst dbLastR  = incoming[\"Last Verification Result\"] || incoming.db_last_result   || '';\nconst dbRisk   = incoming[\"Last Risk Score\"]          || incoming.db_risk_score    || '';\nconst dbNotes  = incoming[\"Notes\"]                    || incoming.db_notes         || '';\nconst dbRow    = incoming.db_row                      || null;\n\n// \u2500\u2500 Name similarity check \u2500\u2500\nlet nameMismatch = false;\nconst entityFromDoc = incoming[\"Entity Name (Doc)\"] || incoming.entity_name || '';\nif (exact && dbName && entityFromDoc) {\n  const clean   = s => s.toLowerCase().replace(/[^a-z0-9 ]/g, '').split(' ').filter(w => w.length > 2);\n  const overlap = clean(dbName).filter(w => clean(entityFromDoc).includes(w)).length;\n  nameMismatch  = overlap === 0;\n}\n\n// \u2500\u2500 Verification result \u2500\u2500\nconst formatValid = incoming[\"Format Valid\"] ?? incoming.format_valid ?? false;\nlet vr = 'UNVERIFIED';\nif (!formatValid)                                           vr = 'FORMAT_INVALID';\nelse if (!exact && !partial)                                vr = 'NOT_IN_DATABASE';\nelse if (exact && dbStat.toUpperCase().includes('REVOK'))   vr = 'REVOKED';\nelse if (exact && dbStat.toUpperCase().includes('SUSPEND')) vr = 'SUSPENDED';\nelse if (exact && nameMismatch)                             vr = 'ID_NAME_MISMATCH';\nelse if (partial && !exact)                                 vr = 'POSSIBLE_MATCH_REVIEW';\nelse if (exact)                                             vr = 'VERIFIED';\n\nreturn [{ json: {\n  // \u2500\u2500 Document fields \u2500\u2500\n  \"Request ID\":          incoming[\"Request ID\"]    || incoming.request_id    || '',\n  \"Submitted By\":        incoming[\"Submitted By\"]  || incoming.submitted_by  || '',\n  \"Email\":               incoming[\"Email\"]         || incoming.email         || '',\n  \"Organization\":        incoming[\"DB Entity Name\"]  || incoming.organization  || '',\n  \"File Name\":           incoming[\"File Name\"]     || incoming.file_name     || '',\n  \"Entity Name (Doc)\":   entityFromDoc,\n  \"Tax ID Raw\":          incoming[\"Tax ID Raw\"]    || incoming.tax_id_raw    || '',\n  \"Tax ID Normalized\":   submittedRaw,\n  \"Tax ID Type\":         dbType || incoming[\"Tax ID Type\"] || '',\n  \"Format Valid\":        formatValid,\n  \"Format Error\":        incoming[\"Format Error\"]  || incoming.format_error  || '',\n  \"Signature\":           incoming[\"Signature\"]     ?? incoming.signature     ?? false,\n\n  // \u2500\u2500 DB match results \u2500\u2500\n  \"DB Match Score\":      matchScore,\n  \"DB Entity Name\":      dbName,\n  \"DB Status\":           dbStat,\n  \"DB Active Since\":     dbActive,\n  \"DB Tax ID Type\":      dbType,\n  \"DB State\":            dbState,\n  \"DB Source\":           dbSource,\n  \"DB Last Verified\":    dbLastV,\n  \"DB Last Result\":      dbLastR,\n  \"DB Risk Score\":       dbRisk,\n  \"DB Notes\":            dbNotes,\n  \"Name Mismatch\":       nameMismatch,\n\n  // \u2500\u2500 Verdict \u2500\u2500\n  \"Final Status\":        vr,\n\n  // \u2500\u2500 AI / Groq fields \u2500\u2500\n  \"Risk Level\":          riskLevel,\n  \"Risk Score\":          riskScore,\n  \"AI Confidence\":       aiConfidence,\n  \"Compliance Flags\":    Array.isArray(complianceFlags) ? complianceFlags.join(', ') : complianceFlags,\n  \"AI Summary\":          aiSummary,\n  \"Recommended Action\":  recommendedAction,\n  \"Parse Confidence\":    parseConfidence,\n\n  // \u2500\u2500 Internal pipeline keys \u2500\u2500\n  request_id:            incoming[\"Request ID\"]   || incoming.request_id   || '',\n  submitted_by:          incoming[\"Submitted By\"] || incoming.submitted_by || '',\n  tax_id_normalized:     submittedRaw,\n  format_valid:          formatValid,\n  db_match_score:        matchScore,\n  db_exact_match:        exact,\n  db_partial_match:      partial,\n  db_entity_name:        dbName,\n  db_status:             dbStat,\n  db_active:             dbActive,\n  db_type:               dbType,\n  db_state:              dbState,\n  db_source:             dbSource,\n  db_last_verified:      dbLastV,\n  db_last_result:        dbLastR,\n  db_risk_score:         dbRisk,\n  db_notes:              dbNotes,\n  db_row:                dbRow,\n  name_mismatch:         nameMismatch,\n  verification_result:   vr,\n  is_verified:           vr === 'VERIFIED',\n  ai_summary:            aiSummary,\n  risk_level:            riskLevel,\n  risk_score:            riskScore,\n  ai_confidence:         aiConfidence,\n  compliance_flags:      complianceFlags,\n  recommended_action:    recommendedAction,\n  looked_up_at:          new Date().toISOString(),\n\n  // \u2500\u2500 Debug: show raw groq parse \u2500\u2500\n  _debug_groq_raw:       inputJson?.choices?.[0]?.message?.content || '',\n  _debug_groq_parsed:    groqVerdict,\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "e86bd649-3084-4487-a546-0a91949d1436",
      "name": "Sheets \u2014 Write Verification Log1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -720,
        -320
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $json.Email }}",
            "Doc Type": "=",
            "File Name": "={{ $json['File Name'] }}",
            "AI Summary": "={{ $json.ai_summary }}",
            "Request ID": "={{ $json.request_id }}",
            "Tax ID Raw": "={{ $json['Tax ID Raw'] }}",
            "Received At": "={{ $json['Request ID'] }}",
            "Completed At": "=",
            "Organization": "={{ $json['DB Entity Name'] }}",
            "Submitted By": "={{ $json.submitted_by }}",
            "verification_result": "={{ $json.verification_result }}"
          },
          "schema": [
            {
              "id": "Request ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Request ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Received At",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Received At",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Completed At",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Completed At",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submitted By",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submitted By",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Organization",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Organization",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "File Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "File Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entity Name (Doc)",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Entity Name (Doc)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Raw",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Raw",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Normalized",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Normalized",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Doc Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Doc Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax Year",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax Year",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Signature",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Signature",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Format Valid",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Format Valid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Format Error",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Format Error",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Match Score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Match Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Entity Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Entity Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name Mismatch",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Name Mismatch",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Final Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Final Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Risk Level",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Risk Level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Risk Score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Risk Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Confidence",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "AI Confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Compliance Flags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Compliance Flags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "AI Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommended Action",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Recommended Action",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Parse Confidence",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Parse Confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "request_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "request_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "submitted_by",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "submitted_by",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "submission_email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "submission_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "organization",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "organization",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "file_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "file_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "received_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "received_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tax_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_id_raw",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tax_id_raw",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_id_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tax_id_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "entity_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "entity_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "doc_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "doc_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_year",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tax_year",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "signature_present",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "signature_present",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "parse_confidence",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "parse_confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "parse_notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "parse_notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "normalized_tax_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "normalized_tax_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "format_valid",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "format_valid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "format_error",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "format_error",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_match_score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_match_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_exact_match",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_exact_match",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_partial_match",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_partial_match",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_entity_name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_entity_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_active",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_active",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_state",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_state",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_source",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_last_verified",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_last_verified",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_last_result",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_last_result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_risk_score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_risk_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "db_row",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "db_row",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "name_mismatch",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name_mismatch",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "verification_result",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "verification_result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "is_verified",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "is_verified",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "looked_up_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "looked_up_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "final_status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "final_status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "risk_level",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "risk_level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "risk_score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "risk_score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_confidence",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ai_confidence",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "compliance_flags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "compliance_flags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ai_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recommended_action",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "recommended_action",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "completed_at",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "completed_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Active Since",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Active Since",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Tax ID Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Tax ID Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB State",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB State",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Source",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Last Verified",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Last Verified",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Last Result",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Last Result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Risk Score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Risk Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DB Notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "DB Notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tax_id_normalized",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tax_id_normalized",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "_debug_groq_raw",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "_debug_groq_raw",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "_debug_groq_parsed",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "_debug_groq_parsed",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "\ud83d\udccb  VERIFICATION AUDIT LOG  \u2014  Auto-populated by AI Tax Verification System"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "locationDefine": {
            "values": {
              "headerRow": 3
            }
          }
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1692878098,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit#gid=1692878098",
          "cachedResultName": "Verification_Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit?usp=drivesdk",
          "cachedResultName": "TaxID verify&Logs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "3841af19-63cb-4bef-9286-54afdbd7ccce",
      "name": "Exact DB Match?1",
      "type": "n8n-nodes-base.if",
      "position": [
        -512,
        -320
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "cond-exact",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ $json.db_exact_match }}",
              "rightValue": true
            },
            {
              "id": "9c4fa0c7-5dba-491d-908f-34ff95e586f2",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.db_exact_match }}",
              "rightValue": {}
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7ee3f9b4-8fbc-492c-82f9-b1306b007a91",
      "name": "Sheets \u2014 Update DB Record1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -256,
        -480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $json['DB Status'] }}",
            "Tax ID": "={{ $json.db_row['Tax ID'] }}",
            "row_number": 0,
            "Last Verified": "={{ $now.toISO() }}",
            "Last Risk Score": "={{ $json['Risk Score'] }}",
            "Last Verification Result": "={{ $json['Final Status'] }}"
          },
          "schema": [
            {
              "id": "Tax ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entity Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Entity Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Registered State",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Registered State",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Active Since",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Active Since",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Verified",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Last Verified",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Source",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Source",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Verification Count",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Verification Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Verification Result",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Last Verification Result",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Risk Score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Last Risk Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Tax ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "locationDefine": {
            "values": {
              "headerRow": 3,
              "firstDataRow": 4
            }
          }
        },
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1971988441,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit#gid=1971988441",
          "cachedResultName": "TaxID_Database"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit?usp=drivesdk",
          "cachedResultName": "TaxID verify&Logs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "35242fc0-0515-426e-9aeb-a394f4999f12",
      "name": "Sheets \u2014 Log Unknown Tax ID1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -272,
        -192
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Request ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Request ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Normalized",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Normalized",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tax ID Type",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Tax ID Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Entity Name (Doc)",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Entity Name (Doc)",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Final Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Final Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Risk Score",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Risk Score",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Flagged At",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Flagged At",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submitted By",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submitted By",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Submission Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Submission Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Summary",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "AI Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Compliance Flags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Compliance Flags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "cellFormat": "USER_ENTERED",
          "locationDefine": {
            "values": {
              "headerRow": 3
            }
          }
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1145477867,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit#gid=1145477867",
          "cachedResultName": "Unknown_TaxIDs"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1tHpCHYxhAFaZrK3IYbT-a1TTIJQUKwFZKjrlB36CDuM/edit?usp=drivesdk",
          "cachedResultName": "TaxID verify&Logs"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2b1ccacb-24ed-47f8-a25e-1eee01f30ce3",
      "name": "Route by Final Status1",
      "type": "n8n-nodes-base.switch",
      "position": [
        -16,
        -320
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "VERIFIED",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sw-verified",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json['Last Verification Result'] }}",
                    "rightValue": "VERIFIED"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "REJECTED",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sw-rejected",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json['Last Verification Result'] }}",
                    "rightValue": "REJECTED"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "MANUAL_REVIEW"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "ede9ecfc-5b9e-4821-adf8-dbf0345a26ea",
      "name": "Webhook \u2014 Return JSON to Lovable1",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        672,
        -320
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, final_status: $('Parse Groq Verdict1').first().json.final_status || $('Parse Groq Verdict1').first().json['Final Status'], tax_id_normalized: $('Parse Groq Verdict1').first().json.tax_id_normalized || $('Parse Groq Verdict1').first().json['Tax ID Normalized'], entity_name: $('Parse Groq Verdict1').first().json.entity_name || $('Parse Groq Verdict1').first().json['Entity Name (Doc)'], is_duplicate: false, cache_hit: false, risk_level: $('Parse Groq Verdict1').first().json.risk_level || '', risk_score: $('Parse Groq Verdict1').first().json.risk_score || 0, ai_confidence: $('Parse Groq Verdict1').first().json.ai_confidence || 0, compliance_flags: $('Parse Groq Verdict1').first().json.compliance_flags || [], recommended_action: $('Parse Groq Verdict1').first().json.recommended_action || '', summary: $('Parse Groq Verdict1').first().json.ai_summary || '', completed_at: $('Parse Groq Verdict1').first().json.looked_up_at || new Date().toISOString() }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "8c735490-59ca-4322-988f-0b7e812985d2",
      "name": "Send a message3",
      "type": "n8n-nodes-base.gmail",
      "position": [
        272,
        -544
      ],
      "parameters": {
        "sendTo": "={{ $('Exact DB Match?1').item.json.Email }}",
        "message": "=<h2>\u2705 Tax ID Verification Complete</h2>  <p>Dear {{ $('Exact DB Match?1').item.json['Submitted By'] }},</p>  <p>Your submitted tax document has been successfully verified. Below is a summary:</p>  <table border=\"1\" cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse:collapse; width:100%;\">   <tr><td><strong>Request ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Request ID'] }}</td></tr>   <tr><td><strong>Entity Name</strong></td><td>{{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}</td></tr>   <tr><td><strong>Tax ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Normalized'] }}</td></tr>   <tr><td><strong>Tax ID Type</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Type'] }}</td></tr>   <tr><td><strong>Final Status</strong></td><td>\u2705 VERIFIED</td></tr>   <tr><td><strong>DB Status</strong></td><td>{{ $('Exact DB Match?1').item.json['DB Status'] }}</td></tr>   <tr><td><strong>Risk Level</strong></td><td>{{ $('Exact DB Match?1').item.json['Risk Level'] }}</td></tr>   <tr><td><strong>AI Summary</strong></td><td>{{ $('Exact DB Match?1').item.json['AI Summary'] }}</td></tr>   <tr><td><strong>Recommended Action</strong></td><td>{{ $('Exact DB Match?1').item.json['Recommended Action'] }}</td></tr>   <tr><td><strong>Verified At</strong></td><td>{{ $('Exact DB Match?1').item.json.looked_up_at }}</td></tr> </table>  <p>No further action is required.</p> <p><em>This is an automated message from your Tax ID Verification System.</em></p>",
        "options": {},
        "subject": "=\u2705 Tax ID Verification Successful \u2014 {{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f4bd5b43-de45-4a71-b601-20f7abf1058b",
      "name": "Send a message4",
      "type": "n8n-nodes-base.gmail",
      "position": [
        256,
        -304
      ],
      "parameters": {
        "sendTo": "={{ $('Exact DB Match?1').item.json.Email }}",
        "message": "=<h2>\u2705 Tax ID Verification Complete</h2>  <p>Dear {{ $('Exact DB Match?1').item.json['Submitted By'] }},</p>  <p>Your submitted tax document has been successfully verified. Below is a summary:</p>  <table border=\"1\" cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse:collapse; width:100%;\">   <tr><td><strong>Request ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Request ID'] }}</td></tr>   <tr><td><strong>Entity Name</strong></td><td>{{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}</td></tr>   <tr><td><strong>Tax ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Normalized'] }}</td></tr>   <tr><td><strong>Tax ID Type</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Type'] }}</td></tr>   <tr><td><strong>Final Status</strong></td><td>\u2705 VERIFIED</td></tr>   <tr><td><strong>DB Status</strong></td><td>{{ $('Exact DB Match?1').item.json['DB Status'] }}</td></tr>   <tr><td><strong>Risk Level</strong></td><td>{{ $('Exact DB Match?1').item.json['Risk Level'] }}</td></tr>   <tr><td><strong>AI Summary</strong></td><td>{{ $('Exact DB Match?1').item.json['AI Summary'] }}</td></tr>   <tr><td><strong>Recommended Action</strong></td><td>{{ $('Exact DB Match?1').item.json['Recommended Action'] }}</td></tr>   <tr><td><strong>Verified At</strong></td><td>{{ $('Exact DB Match?1').item.json.looked_up_at }}</td></tr> </table>  <p>No further action is required.</p> <p><em>This is an automated message from your Tax ID Verification System.</em></p>",
        "options": {},
        "subject": "=\u2705 Tax ID Verification Successful \u2014 {{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fca4534a-9041-4d16-a221-1dfd38ce2581",
      "name": "Send a message5",
      "type": "n8n-nodes-base.gmail",
      "position": [
        272,
        -48
      ],
      "parameters": {
        "sendTo": "={{ $('Exact DB Match?1').item.json.Email }}",
        "message": "=<h2>\u2705 Tax ID Verification Complete</h2>  <p>Dear {{ $('Exact DB Match?1').item.json['Submitted By'] }},</p>  <p>Your submitted tax document has been successfully verified. Below is a summary:</p>  <table border=\"1\" cellpadding=\"8\" cellspacing=\"0\" style=\"border-collapse:collapse; width:100%;\">   <tr><td><strong>Request ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Request ID'] }}</td></tr>   <tr><td><strong>Entity Name</strong></td><td>{{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}</td></tr>   <tr><td><strong>Tax ID</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Normalized'] }}</td></tr>   <tr><td><strong>Tax ID Type</strong></td><td>{{ $('Exact DB Match?1').item.json['Tax ID Type'] }}</td></tr>   <tr><td><strong>Final Status</strong></td><td>\u2705 VERIFIED</td></tr>   <tr><td><strong>DB Status</strong></td><td>{{ $('Exact DB Match?1').item.json['DB Status'] }}</td></tr>   <tr><td><strong>Risk Level</strong></td><td>{{ $('Exact DB Match?1').item.json['Risk Level'] }}</td></tr>   <tr><td><strong>AI Summary</strong></td><td>{{ $('Exact DB Match?1').item.json['AI Summary'] }}</td></tr>   <tr><td><strong>Recommended Action</strong></td><td>{{ $('Exact DB Match?1').item.json['Recommended Action'] }}</td></tr>   <tr><td><strong>Verified At</strong></td><td>{{ $('Exact DB Match?1').item.json.looked_up_at }}</td></tr> </table>  <p>No further action is required.</p> <p><em>This is an automated message from your Tax ID Verification System.</em></p>",
        "options": {},
        "subject": "=\u2705 Tax ID Verification Successful \u2014 {{ $('Exact DB Match?1').item.json['Entity Name (Doc)'] }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9605253a-2f09-44e2-ab97-36073d10c6d8",
      "name": "Respond \u2014 No Tax ID Found",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1840,
        32
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: false, error: \"NO_TAX_ID_FOUND\", request_id: $json.request_id, message: \"No Tax ID could be extracted. Please upload a valid tax form (W-9, W-8, 1099, W-2 or 1040).\", parse_notes: $json.parse_notes, parse_confidence: $json.parse_confidence }) }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "c8f9df11-6b8f-478b-824f-1b4fdc4d8490",
      "name": "Duplicate found",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -2448,
        -480
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify($('Return Cached Result').first().json) }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "9a83da43-3c1b-481f-ae8a-efb29f54f2e6",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3952,
        -960
      ],
      "parameters": {
        "color": 5,
        "width": 208,
        "height": 112,
        "content": "Youtube Demo video\n\n[\u25b6\ufe0f Watch Demo Video](https://youtu.be/4A-jqox14R8)"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "9a430c22-65b4-427d-8e79-29ce00ba42ee",
  "nodeGroups": [],
  "connections": {
    "Send a message3": {
      "main": [
        [
          {
            "node": "Webhook \u2014 Return JSON to Lovable1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message4": {
      "main": [
        [
          {
            "node": "Webhook \u2014 Return JSON to Lovable1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message5": {
      "main": [
        [
          {
            "node": "Webhook \u2014 Return JSON to Lovable1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exact DB Match?1": {
      "main": [
        [
          {
            "node": "Sheets \u2014 Update DB Record1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Sheets \u2014 Log Unknown Tax ID1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Duplicate Decision": {
      "main": [
        [
          {
            "node": "Switch \u2014 Duplicate Route",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Validation1": {
      "main": [
        [
          {
            "node": "Google Sheets \u2014 Read TaxID Database1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tax ID Extracted?1": {
      "main": [
        [
          {
            "node": "Format Validation1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond \u2014 No Tax ID Found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Groq Verdict1": {
      "main": [
        [
          {
            "node": "Sheets \u2014 Write Verification Log1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Return Cached Result": {
      "main": [
        [
          {
            "node": "Duplicate found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Final Status1": {
      "main": [
        [
          {
            "node": "Send a message3",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send a message4",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send a message5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract PDF Text Layer1": {
      "main": [
        [
          {
            "node": "Groq \u2014 Parse PDF Tax Document1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filename Duplicate Check": {
      "main": [
        [
          {
            "node": "Sheets \u2014 Lookup Verification Log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Lovable Payload1": {
      "main": [
        [
          {
            "node": "Filename Duplicate Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch \u2014 Duplicate Route": {
      "main": [
        [
          {
            "node": "Return Cached Result",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Extract PDF Text Layer1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Groq Extract Response1": {
      "main": [
        [
          {
            "node": "Tax ID Extracted?1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets \u2014 Update DB Record1": {
      "main": [
        [
          {
            "node": "Route by Final Status1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Database Lookup + Match Logic1": {
      "main": [
        [
          {
            "node": "Groq \u2014 Final Compliance Verdict1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets \u2014 Log Unknown Tax ID1": {
      "main": [
        [
          {
            "node": "Route by Final Status1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook \u2014 Lovable Form POST1": {
      "main": [
        [
          {
            "node": "Normalize Lovable Payload1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq \u2014 Parse PDF Tax Document1": {
      "main": [
        [
          {
            "node": "Parse Groq Extract Response1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Groq \u2014 Final Compliance Verdict1": {
      "main": [
        [
          {
            "node": "Parse Groq Verdict1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets \u2014 Lookup Verification Log": {
      "main": [
        [
          {
            "node": "Duplicate Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sheets \u2014 Write Verification Log1": {
      "main": [
        [
          {
            "node": "Exact DB Match?1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets \u2014 Read TaxID Database1": {
      "main": [
        [
          {
            "node": "Database Lookup + Match Logic1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}