{
  "id": "Vc7e9iEDsCjoXsdM",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "KYC-RISK-FORM",
  "tags": [],
  "nodes": [
    {
      "id": "5406944c-aa51-4edf-8345-c34de0359e00",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -336
      ],
      "parameters": {
        "width": 688,
        "height": 608,
        "content": "## KYC Risk Profiling Workflow\n\nCaptures KYC form data, validates required fields, sends it to AI for risk analysis, formats the response and routes records based on risk level.\n\n## Flow:\n\nKYC Form Submission \u2192 Validate KYC Input \u2192 AI Risk Analysis \u2192 Process AI Response \u2192 Format Final Data \u2192 IF Risk Check\n\n\n## Setup Steps\n\nCreate a KYC form with exact field names for all required inputs. Configure the validation node to reject missing or invalid data. Ensure the AI node returns structured JSON. Map final fields correctly in Google Sheets and connect Slack so alerts trigger only when the processed riskCategory is High Risk.\n\n\n## How It Works\n\nWhen a user submits the KYC form, the workflow validates the input and sends clean data to AI for risk scoring and profiling. The AI response is parsed, formatted and checked for risk level. High-risk cases are logged and alerted in Slack, while low and medium-risk cases are only saved."
      },
      "typeVersion": 1
    },
    {
      "id": "af556160-67c5-409f-a81b-68c51e0c923d",
      "name": "KYC Form Submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        576,
        768
      ],
      "parameters": {
        "options": {},
        "formTitle": "KYC_FORM",
        "formFields": {
          "values": [
            {
              "fieldName": "Income",
              "fieldType": "number",
              "fieldLabel": "e.g.5000",
              "requiredField": true
            },
            {
              "fieldName": "Geography",
              "fieldLabel": "e.g.india,usa",
              "requiredField": true
            },
            {
              "fieldName": "Occupation",
              "fieldLabel": "e.eg.software engineer",
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "32b37622-fd04-49f3-aecc-4441bc120ce1",
      "name": "Process AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1376,
        768
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  try {\n    // Correct path for your AI response\n    let rawText = item.json.output?.[0]?.content?.[0]?.text || '{}';\n\n    // Remove markdown fences if present\n    rawText = rawText\n      .replace(/```json/g, '')\n      .replace(/```/g, '')\n      .trim();\n\n    const parsed = JSON.parse(rawText);\n\n    results.push({\n      json: {\n        riskCategory: parsed.riskCategory || 'Unknown',\n        redFlags: parsed.redFlags || [],\n        redFlagText: (parsed.redFlags && parsed.redFlags.length > 0)\n          ? parsed.redFlags.join(', ')\n          : 'None',\n        income: parsed.income || '',\n        geography: parsed.geography || '',\n        occupation: parsed.occupation || ''\n      }\n    });\n\n  } catch (error) {\n    results.push({\n      json: {\n        riskCategory: 'Unknown',\n        redFlags: [],\n        redFlagText: 'None',\n        income: '',\n        geography: '',\n        occupation: '',\n        error: error.message\n      }\n    });\n  }\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "e591b2ac-d634-42b4-9ac9-b738ec0ba1f0",
      "name": "Format Final Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1600,
        768
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c10e471b-3900-49da-a84a-ba498d1e6249",
              "name": "riskCategory",
              "type": "string",
              "value": "={{ $json.riskCategory }}"
            },
            {
              "id": "0fa31d67-d34a-4cb7-b467-376d4f2ba100",
              "name": "redFlags",
              "type": "string",
              "value": "={{ $json.redFlags }}"
            },
            {
              "id": "c0f4121f-3c2e-44c6-adbc-be6063178ce8",
              "name": "income",
              "type": "string",
              "value": "={{ $json.income }}"
            },
            {
              "id": "b516a79a-474c-4870-acad-3de36a937ff4",
              "name": "geography",
              "type": "string",
              "value": "={{ $json.geography }}"
            },
            {
              "id": "4fb86d75-e107-4db9-b486-675e710823b7",
              "name": "occupation",
              "type": "string",
              "value": "={{ $json.occupation }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f95c9c9f-8a6a-403e-9c44-80cf8f140880",
      "name": "Check High Risk",
      "type": "n8n-nodes-base.if",
      "position": [
        1824,
        768
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f3403896-dee4-4855-8b75-43ef4deb4233",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.riskCategory }}",
              "rightValue": "High"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "11bb277c-141f-4885-846a-03d68cf4af36",
      "name": "Save High Risk Record",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2272,
        672
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "8867854e-40fa-4224-b42d-7d851013ce25",
      "name": "Send High Risk Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        2496,
        672
      ],
      "parameters": {
        "text": "= *HIGH RISK KYC Alert!*  \n*Income:* {{ $json.income }} \n*Geography:* {{ $json.geography }} \n*Occupation:* {{ $json.occupation }}  \n*Risk Category:* {{ $json.riskCategory }} \n*Red Flags:* - {{ $json.redFlagText }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        },
        "otherOptions": {}
      },
      "typeVersion": 2.4
    },
    {
      "id": "d17c8d0d-11e5-4d25-9e39-a1d5eef7f1f1",
      "name": "Save Normal Risk Record",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2080,
        864
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "9ae34016-ba2e-41af-942f-3787befeecf9",
      "name": "Validate KYC Input",
      "type": "n8n-nodes-base.code",
      "position": [
        800,
        768
      ],
      "parameters": {
        "jsCode": "const income = Number($json.Income || 0);\nconst geography = String($json.Geography || '').trim();\nconst occupation = String($json.Occupation || '').trim();\n\nconst errors = [];\n\nif (!income || income <= 0) {\n  errors.push('Income must be greater than 0');\n}\n\nif (!geography) {\n  errors.push('Geography is required');\n}\n\nif (!occupation) {\n  errors.push('Occupation is required');\n}\n\nreturn [\n  {\n    json: {\n      Income: income,\n      Geography: geography.toUpperCase(),\n      Occupation: occupation,\n      isValid: errors.length === 0,\n      validationErrors: errors.length ? errors.join(', ') : '',\n      createdAt: new Date().toISOString()\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "fca703bd-9b1f-4558-82d5-fe6aeae3ba3c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        448
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 576,
        "content": "## KYC Form Submission\n\nTriggers the workflow when a customer submits KYC details and passes the entered information into the risk profiling process."
      },
      "typeVersion": 1
    },
    {
      "id": "8f26c1c0-ef85-4435-8b42-ec6997cca255",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1344,
        448
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 576,
        "content": "## AI Response Formatting\n\nProcesses the AI-generated risk analysis, extracts the important customer risk fields, formats the output into a clean structure and prepares the data for the final decision step where the workflow checks whether the customer should be treated as high risk."
      },
      "typeVersion": 1
    },
    {
      "id": "c24f8b7d-2722-4736-b20e-c38fb033e0ea",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2032,
        448
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 576,
        "content": "## AI Response Formatting\n\nProcesses the AI risk assessment, extracts key risk fields, formats the customer data into a clean final structure and prepares the record for the decision step that determines whether the customer should be routed through the high-risk review path."
      },
      "typeVersion": 1
    },
    {
      "id": "5f6aee12-41c1-4d8f-9c6a-b14108723f1a",
      "name": "Format the Data For Sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        2080,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c686274f-926b-4abe-9289-827f2e55f86f",
              "name": "riskCategory",
              "type": "string",
              "value": "={{ $json.riskCategory }}"
            },
            {
              "id": "78e829d0-a59e-4ae6-9f35-ed26139501e2",
              "name": "income",
              "type": "string",
              "value": "={{ $json.income }}"
            },
            {
              "id": "7d55e5b9-0b22-4ea0-b6bb-dc694dcc9681",
              "name": "geography",
              "type": "string",
              "value": "={{ $json.geography }}"
            },
            {
              "id": "8052eefb-9fb4-4251-92d9-bd0148e4a303",
              "name": "redFlags",
              "type": "string",
              "value": "={{ $json.redFlags }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bf2f25cd-52ad-4f70-be1d-c4d92d36b218",
      "name": "Ai Assign The Risk Category",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1008,
        768
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are a KYC Risk Analyst.\n\nAnalyze the applicant details below and do ALL of the following:\n1. Assign a risk category: Low / Medium / High\n2. List any red flags found\n3. Return the original applicant details exactly as received\n\nApplicant Details:\nIncome: {{ $json.Income }}\nGeography: {{ $json.Geography }}\nOccupation: {{ $json.Occupation }}\n\nRisk Rules:\n- High risk if the geography is a sanctioned country, FATF blacklisted country or high-risk jurisdiction\n- High risk if the occupation is in a high-risk sector such as cryptocurrency, gambling, arms trade, shell companies or politically exposed roles\n- Medium risk if one moderate concern exists\n- Low risk if no major red flags exist\n\nReturn ONLY valid JSON in this exact format:\n{\n  \"riskCategory\": \"High\",\n  \"redFlags\": [\"flag1\", \"flag2\"],\n  \"income\": \"{{ $json.Income }}\",\n  \"geography\": \"{{ $json.Geography }}\",\n  \"occupation\": \"{{ $json.Occupation }}\"\n}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "c8041ceb-3ab5-48e6-8344-ddea3edb7b87",
  "connections": {
    "Check High Risk": {
      "main": [
        [
          {
            "node": "Format the Data For Sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Save Normal Risk Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Final Data": {
      "main": [
        [
          {
            "node": "Check High Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate KYC Input": {
      "main": [
        [
          {
            "node": "Ai Assign The Risk Category",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "KYC Form Submission": {
      "main": [
        [
          {
            "node": "Validate KYC Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process AI Response": {
      "main": [
        [
          {
            "node": "Format Final Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save High Risk Record": {
      "main": [
        [
          {
            "node": "Send High Risk Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format the Data For Sheet": {
      "main": [
        [
          {
            "node": "Save High Risk Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ai Assign The Risk Category": {
      "main": [
        [
          {
            "node": "Process AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}