AutomationFlowsEmail & Gmail › Screen and Route Ai-scored Job Applications with Airtable, Google Drive and…

Screen and Route Ai-scored Job Applications with Airtable, Google Drive and…

Original n8n title: Screen and Route Ai-scored Job Applications with Airtable, Google Drive and Openrouter

BySalman Mehboob @salmanmehboob on n8n.io

This workflow collects job applications via an n8n Form, checks duplicates in Airtable, stores CV files in Google Drive, and uses OpenRouter to score and summarize each CV for an n8n Automation Expert role, updating Airtable status and emailing shortlisted candidates via Gmail.…

Event trigger★★★★☆ complexityAI-powered27 nodesForm TriggerAirtableFormGoogle DriveOpenRouter ChatOutput Parser StructuredChain LlmGmail
Email & Gmail Trigger: Event Nodes: 27 Complexity: ★★★★☆ AI nodes: yes Added:
Screen and Route Ai-scored Job Applications with Airtable, Google Drive and… — n8n workflow card showing Form Trigger, Airtable, Form integration

This workflow corresponds to n8n.io template #17303 — we link there as the canonical source.

This workflow follows the Airtable → Chainllm recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "wvG7MGSDF9IcnEVJ",
  "meta": {
    "builderVariant": "mcp",
    "aiBuilderAssisted": true
  },
  "name": "CV Screening - Intake & Store",
  "tags": [],
  "nodes": [
    {
      "id": "b2ddbf35-a5cc-4858-aaaa-f4d35ca37ef8",
      "name": "Receive Application",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -208,
        96
      ],
      "parameters": {
        "options": {
          "path": "cv-application",
          "buttonLabel": "Submit Application",
          "appendAttribution": false
        },
        "formTitle": "Job Application",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Full Name",
              "placeholder": "Your full name",
              "requiredField": true
            },
            {
              "fieldLabel": "WhatsApp Number",
              "placeholder": "e.g. +1234567890",
              "requiredField": true
            },
            {
              "fieldType": "email",
              "fieldLabel": "Email",
              "placeholder": "you@example.com",
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "CV",
              "multipleFiles": false,
              "requiredField": true,
              "acceptFileTypes": ".pdf"
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Cover Letter",
              "placeholder": "Optional"
            }
          ]
        },
        "responseMode": "lastNode",
        "formDescription": "Apply for the role. Upload your CV as a PDF or Word document."
      },
      "typeVersion": 2.6
    },
    {
      "id": "658f0804-04bb-4d98-bc73-a689d4a5774b",
      "name": "Normalize Phone",
      "type": "n8n-nodes-base.set",
      "position": [
        16,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "phone-e164",
              "name": "phoneE164",
              "type": "string",
              "value": "={{ (() => { let p = ($json[\"WhatsApp Number\"] || \"\").toString().replace(/[^0-9+]/g, \"\"); if (p.startsWith(\"+\")) return p; if (p.startsWith(\"0092\")) return \"+\" + p.slice(2); if (p.startsWith(\"92\")) return \"+\" + p; if (p.startsWith(\"0\")) return \"+92\" + p.slice(1); return \"+\" + p; })() }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "6f02c6ea-8ea9-43ff-97e0-3cfefc9636ac",
      "name": "Check Existing Applicant",
      "type": "n8n-nodes-base.airtable",
      "position": [
        272,
        96
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "app8QJ6WwaggOL44B",
          "cachedResultName": "CV Screening System"
        },
        "limit": 1,
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "tbljWFgYiC96NNEnk",
          "cachedResultName": "Applications"
        },
        "options": {},
        "operation": "search",
        "returnAll": false,
        "filterByFormula": "=OR(LOWER({Email}) = LOWER(\"{{ $json.Email }}\"), {WhatsApp Number} = \"{{ $json.phoneE164 }}\")"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2,
      "alwaysOutputData": true
    },
    {
      "id": "e6cd776d-bd2a-4267-be80-ddf75dfab080",
      "name": "Is Duplicate?",
      "type": "n8n-nodes-base.if",
      "position": [
        496,
        96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4b2a69ff-0f13-452a-a87b-dc425aa68595",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "7845a2a7-a0b2-4b48-b2c9-f598398109b1",
      "name": "Already Applied",
      "type": "n8n-nodes-base.form",
      "position": [
        976,
        -64
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "Application already received",
        "completionMessage": "=Hi {{ $(\"Receive Application\").item.json[\"Full Name\"] }}, we already have an application from you on file. There is no need to apply again."
      },
      "typeVersion": 2.5
    },
    {
      "id": "5ebccd88-1560-4b23-ba7a-0fdd90b656cf",
      "name": "Attach CV File",
      "type": "n8n-nodes-base.set",
      "position": [
        848,
        192
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cv-binary",
              "name": "data",
              "type": "binary",
              "value": "={{ $(\"Receive Application\").item.binary.CV }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "94e6204e-25f4-4735-8081-c8b3924628b6",
      "name": "Upload CV to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1072,
        192
      ],
      "parameters": {
        "name": "={{ $(\"Receive Application\").item.json[\"Full Name\"] }} - CV",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultName": "My Drive"
        },
        "options": {
          "simplifyOutput": false
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultName": "/ (Root folder)"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "c7d3a99c-4e6d-4705-98b6-85774ab8fb40",
      "name": "Make CV Link Viewable",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1280,
        96
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {},
        "operation": "share",
        "permissionsUi": {
          "permissionsValues": {
            "role": "reader",
            "type": "anyone"
          }
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "0603ca28-d8f7-486a-8cac-e19ec71c5792",
      "name": "Log Application",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1488,
        0
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "app8QJ6WwaggOL44B",
          "cachedResultName": "CV Screening System"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "tbljWFgYiC96NNEnk",
          "cachedResultName": "Applications"
        },
        "columns": {
          "value": {
            "CV": "={{ $(\"Upload CV to Drive\").item.json.webViewLink }}",
            "Email": "={{ $(\"Receive Application\").item.json.Email }}",
            "Full Name": "={{ $(\"Receive Application\").item.json[\"Full Name\"] }}",
            "Received At": "={{ $now.toISO() }}",
            "Cover Letter": "={{ $(\"Receive Application\").item.json[\"Cover Letter\"] }}",
            "WhatsApp Number": "={{ $(\"Normalize Phone\").item.json.phoneE164 }}",
            "Screening Status": "Pending"
          },
          "schema": [
            {
              "id": "Full Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Full Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "WhatsApp Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "WhatsApp Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CV",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CV",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Cover Letter",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Cover Letter",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Received At",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Received At",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Screening Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Screening Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {
          "typecast": true
        },
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "89017aef-710b-4409-a386-036399d18e80",
      "name": "Application Received",
      "type": "n8n-nodes-base.form",
      "position": [
        1680,
        0
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "Application received",
        "completionMessage": "=Thanks {{ $(\"Receive Application\").item.json[\"Full Name\"] }}! We have received your application and CV. Our team will review it and reach out via WhatsApp or email."
      },
      "typeVersion": 2.5
    },
    {
      "id": "eafff1c7-e6f0-4abd-af88-1536491179b2",
      "name": "Attach CV for Screening",
      "type": "n8n-nodes-base.set",
      "position": [
        1920,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cv-bin-2",
              "name": "data",
              "type": "binary",
              "value": "={{ $(\"Receive Application\").item.binary.CV }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c3e0eff0-a4d3-4aa6-aed7-b1b1663009a3",
      "name": "Extract CV Text",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        2160,
        0
      ],
      "parameters": {
        "options": {
          "joinPages": true
        },
        "operation": "pdf"
      },
      "typeVersion": 1.1
    },
    {
      "id": "388ad07a-bff1-490e-b9fc-61acaaeadd1b",
      "name": "OpenRouter Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2368,
        176
      ],
      "parameters": {
        "model": "openrouter/free",
        "options": {
          "temperature": 0.2
        }
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a9bddc31-ab6a-4cf6-b84e-1f6a229ed2f4",
      "name": "Screening Fixer Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2608,
        336
      ],
      "parameters": {
        "model": "openrouter/free",
        "options": {
          "temperature": 0
        }
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "017d0787-2082-4044-adeb-68ea84e3d4db",
      "name": "CV Score Schema",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2624,
        176
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"aiMatchScore\": { \"type\": \"integer\", \"minimum\": 0, \"maximum\": 100, \"description\": \"Overall fit score 0-100 based strictly on the rubric\" },\n    \"aiSummary\": { \"type\": \"string\", \"description\": \"2-3 sentence summary of the candidate's fit, strengths and gaps for this role\" },\n    \"extractedSkills\": { \"type\": \"array\", \"items\": { \"type\": \"string\" }, \"description\": \"Concrete skills and tools found in the CV\" }\n  },\n  \"required\": [\"aiMatchScore\", \"aiSummary\", \"extractedSkills\"],\n  \"additionalProperties\": false\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d6ae79c3-4406-48d6-afe8-db1446f391f6",
      "name": "Screen CV",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2432,
        0
      ],
      "parameters": {
        "text": "=You are a strict technical recruiter screening CVs for ONE role: an n8n Automation Expert.\n\nROLE REQUIREMENTS:\n- 2+ years hands-on automation / integration experience\n- Strong, demonstrable n8n skills: building real workflows with triggers, IF/Switch, Merge, error handling, Code nodes, sub-workflows, HTTP/API nodes\n\nSCORING RUBRIC (total 100):\n- n8n hands-on depth \u2014 35 pts (deep hands-on 30-35, mentions but shallow 10-20, none 0)\n- Relevant experience / years \u2014 20 pts (2+ yrs 15-20, ~1-2 yrs 8-14, under 1 yr 0-7)\n- Automation & integration breadth \u2014 20 pts (APIs, webhooks, auth/OAuth, data transformation; Make/Zapier count as a plus, not a substitute for n8n)\n- Supporting technical skills \u2014 15 pts (JS/Python for Code nodes, databases/Airtable/Sheets, AI/LLM integration)\n- Proof / signal \u2014 10 pts (portfolio, GitHub, named projects, quantified impact)\n\nGATES:\n- If there is NO genuine evidence of n8n, cap the total at 40 even if everything else is strong.\n- Score ONLY from evidence present in the CV. Do not infer skills that are not stated. Missing info = low band, not benefit of the doubt.\n\nReturn aiMatchScore (0-100 integer), aiSummary (2-3 sentences on fit, strengths, gaps), and extractedSkills (concrete skills/tools found).\n\nCANDIDATE CV:\n{{ $json.text }}",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.9
    },
    {
      "id": "c07f010f-fb9b-49b7-a1e7-8923de4e4bc7",
      "name": "Route by Score",
      "type": "n8n-nodes-base.switch",
      "position": [
        2992,
        -16
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Shortlisted",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "44a230a6-d16e-43b2-836a-05e6ab283781",
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    },
                    "leftValue": "={{ $json.output.aiMatchScore }}",
                    "rightValue": 70
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Review",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "5e2efa24-3697-4718-a321-6cad97d7f022",
                    "operator": {
                      "type": "number",
                      "operation": "gte"
                    },
                    "leftValue": "={{ $json.output.aiMatchScore }}",
                    "rightValue": 50
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Rejected",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "73620cd6-150b-4f4e-a7f3-ffb4daf7395c",
                    "operator": {
                      "type": "number",
                      "operation": "lt"
                    },
                    "leftValue": "={{ $json.output.aiMatchScore }}",
                    "rightValue": 50
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cc7f54b8-4466-4289-9e37-6fc52c4a0ed3",
      "name": "Update - Shortlisted",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3264,
        -64
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "app8QJ6WwaggOL44B",
          "cachedResultName": "CV Screening System"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "tbljWFgYiC96NNEnk",
          "cachedResultName": "Applications"
        },
        "columns": {
          "value": {
            "id": "={{ $(\"Log Application\").item.json.id }}",
            "AI Summary": "={{ $(\"Screen CV\").item.json.output.aiSummary }}",
            "AI Match Score": "={{ $(\"Screen CV\").item.json.output.aiMatchScore }}",
            "Extracted Skills": "={{ $(\"Screen CV\").item.json.output.extractedSkills.join(\", \") }}",
            "Screening Status": "Shortlisted"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Match Score",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "AI Match Score",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "AI Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "AI Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Extracted Skills",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Extracted Skills",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Screening Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Screening Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ]
        },
        "options": {
          "typecast": true
        },
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "29d4b729-c722-4a80-bac6-a576f45d608e",
      "name": "Update - Review",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3264,
        96
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "app8QJ6WwaggOL44B",
          "cachedResultName": "CV Screening System"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "tbljWFgYiC96NNEnk",
          "cachedResultName": "Applications"
        },
        "columns": {
          "value": {
            "id": "={{ $(\"Log Application\").item.json.id }}",
            "AI Summary": "={{ $(\"Screen CV\").item.json.output.aiSummary }}",
            "AI Match Score": "={{ $(\"Screen CV\").item.json.output.aiMatchScore }}",
            "Extracted Skills": "={{ $(\"Screen CV\").item.json.output.extractedSkills.join(\", \") }}",
            "Screening Status": "Review"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Match Score",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "AI Match Score",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "AI Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "AI Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Extracted Skills",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Extracted Skills",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Screening Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Screening Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ]
        },
        "options": {
          "typecast": true
        },
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "03d0bb93-794c-4a45-be46-830545a8fbb6",
      "name": "Update - Rejected",
      "type": "n8n-nodes-base.airtable",
      "position": [
        3264,
        256
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "app8QJ6WwaggOL44B",
          "cachedResultName": "CV Screening System"
        },
        "table": {
          "__rl": true,
          "mode": "id",
          "value": "tbljWFgYiC96NNEnk",
          "cachedResultName": "Applications"
        },
        "columns": {
          "value": {
            "id": "={{ $(\"Log Application\").item.json.id }}",
            "AI Summary": "={{ $(\"Screen CV\").item.json.output.aiSummary }}",
            "AI Match Score": "={{ $(\"Screen CV\").item.json.output.aiMatchScore }}",
            "Extracted Skills": "={{ $(\"Screen CV\").item.json.output.extractedSkills.join(\", \") }}",
            "Screening Status": "Rejected"
          },
          "schema": [
            {
              "id": "id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Match Score",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "AI Match Score",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "AI Summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "AI Summary",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Extracted Skills",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Extracted Skills",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Screening Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Screening Status",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ]
        },
        "options": {
          "typecast": true
        },
        "operation": "update"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "59d0c791-c827-45e0-932c-ee8c5bb3146d",
      "name": "Send Shortlist Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3488,
        -48
      ],
      "parameters": {
        "sendTo": "={{ $(\"Receive Application\").item.json.Email }}",
        "message": "=<p>Hi {{ $(\"Receive Application\").item.json[\"Full Name\"] }},</p><p>Great news - after reviewing your CV for the n8n Automation Expert role, we'd like to move you forward to an interview.</p><p>Please pick a slot that suits you here:</p><p><a href=\"https://calendly.com/your-team/interview\">https://calendly.com/your-team/interview</a></p><p>Looking forward to speaking with you.</p>",
        "options": {
          "appendAttribution": false
        },
        "subject": "You have been shortlisted - book your interview"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "65ae9946-4674-4d2a-b86b-ad7c3c00dd98",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        -352
      ],
      "parameters": {
        "width": 592,
        "height": 1056,
        "content": "## CV Screening - Intake & Store\n\n### How it works\n\n1. A candidate submits the application form: name, WhatsApp number, email, CV (PDF) and an optional cover letter.\n2. The phone number is normalised and Airtable is checked for an existing applicant by email or phone.\n3. Duplicates are shown an \"already applied\" page; new applicants have their CV uploaded to Google Drive and logged in Airtable, then see a confirmation page.\n4. Each new CV is parsed to text and scored 0-100 against the n8n Automation Expert rubric by an LLM.\n5. The score routes the applicant: 70+ is shortlisted and emailed a Calendly link, 50-69 is marked for review, below 50 is rejected.\n\n### Airtable columns\n\n- **Full Name** \u2014 applicant's name\n- **WhatsApp Number** \u2014 normalised to E.164\n- **Email** \u2014 applicant's email\n- **CV** \u2014 shareable Google Drive link\n- **Cover Letter** \u2014 optional text\n- **Received At** \u2014 when the application was logged\n- **AI Match Score** \u2014 screening score 0-100\n- **AI Summary** \u2014 short fit summary\n- **Extracted Skills** \u2014 skills found in the CV\n- **Screening Status** \u2014 Pending \u00b7 Shortlisted \u00b7 Review \u00b7 Rejected\n\n### Setup steps\n\n- [ ] Connect Airtable, Google Drive, Gmail and OpenRouter credentials on the relevant nodes.\n- [ ] Point the Airtable nodes at your CV Screening base and Applications table.\n- [ ] Set a working model on both OpenRouter nodes.\n- [ ] Replace the Calendly link in the shortlist email with your own.\n- [ ] Publish the workflow and share the form URL from the Receive Application node.\n\n### Customization\n\nAdjust the score thresholds in the Route by Score node, or edit the scoring rubric inside the Screen CV prompt."
      },
      "typeVersion": 1
    },
    {
      "id": "6e756d06-6ae7-48ac-b110-975fd412a4d5",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -272,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 448,
        "content": "## Intake & normalize\n\nApplicant submits the form; the phone number is normalised to E.164 so the duplicate check is reliable."
      },
      "typeVersion": 1
    },
    {
      "id": "d4dbfe6f-2406-48ea-864f-ef0ade3f246a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 448,
        "content": "## Duplicate guard\n\nAirtable is searched by email or phone to decide whether this applicant already exists."
      },
      "typeVersion": 1
    },
    {
      "id": "b0545855-1450-4825-9993-c3eb198ec1d3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 752,
        "content": "## Store applicant & respond\n\nDuplicates see an \"already applied\" page. New applicants have their CV stored on Google Drive, are logged in Airtable as Pending, and see a confirmation page."
      },
      "typeVersion": 1
    },
    {
      "id": "75c8b60a-0243-4516-9055-a85c670b7b9c",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1856,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 1040,
        "height": 752,
        "content": "## AI screening\n\nThe CV is parsed to text and scored 0-100 against the role rubric, returning a summary and extracted skills."
      },
      "typeVersion": 1
    },
    {
      "id": "0afa076e-582c-4d97-9894-3c31339716b6",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2928,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 832,
        "height": 752,
        "content": "## Route & outcomes\n\nThe score decides the outcome: 70+ shortlist + Calendly email, 50-69 review, below 50 reject - each written back to Airtable."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": true,
    "executionOrder": "v1"
  },
  "versionId": "bfa99ef7-dbd9-42c7-a1ed-77b8749ef865",
  "nodeGroups": [],
  "connections": {
    "Screen CV": {
      "main": [
        [
          {
            "node": "Route by Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Duplicate?": {
      "main": [
        [
          {
            "node": "Already Applied",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Attach CV File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Attach CV File": {
      "main": [
        [
          {
            "node": "Upload CV to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Score": {
      "main": [
        [
          {
            "node": "Update - Shortlisted",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update - Review",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Update - Rejected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CV Score Schema": {
      "ai_outputParser": [
        [
          {
            "node": "Screen CV",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Extract CV Text": {
      "main": [
        [
          {
            "node": "Screen CV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Application": {
      "main": [
        [
          {
            "node": "Application Received",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Phone": {
      "main": [
        [
          {
            "node": "Check Existing Applicant",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Model": {
      "ai_languageModel": [
        [
          {
            "node": "Screen CV",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Upload CV to Drive": {
      "main": [
        [
          {
            "node": "Make CV Link Viewable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Application": {
      "main": [
        [
          {
            "node": "Normalize Phone",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Application Received": {
      "main": [
        [
          {
            "node": "Attach CV for Screening",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update - Shortlisted": {
      "main": [
        [
          {
            "node": "Send Shortlist Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Make CV Link Viewable": {
      "main": [
        [
          {
            "node": "Log Application",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Screening Fixer Model": {
      "ai_languageModel": [
        [
          {
            "node": "CV Score Schema",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Attach CV for Screening": {
      "main": [
        [
          {
            "node": "Extract CV Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Existing Applicant": {
      "main": [
        [
          {
            "node": "Is Duplicate?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

This workflow collects job applications via an n8n Form, checks duplicates in Airtable, stores CV files in Google Drive, and uses OpenRouter to score and summarize each CV for an n8n Automation Expert role, updating Airtable status and emailing shortlisted candidates via Gmail.…

Source: https://n8n.io/workflows/17303/ — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

This template automates the complete hiring pipeline for digital agencies managing applications across multiple job roles. When a candidate submits a Google Form with their CV, the system scores it wi

OpenRouter Chat, Output Parser Structured, Google Sheets +6
Email & Gmail

n8n Graphic Design Team. Uses googleSheets, googleDrive, httpRequest, outputParserStructured. Event-driven trigger; 37 nodes.

Google Sheets, Google Drive, HTTP Request +5
Email & Gmail

Qualifying Appointment Requests With Ai & N8N Forms. Uses formTrigger, form, lmChatOpenAi, gmail. Event-driven trigger; 25 nodes.

Form Trigger, Form, OpenAI Chat +5
Email & Gmail

Googlecalendar Form. Uses formTrigger, form, lmChatOpenAi, gmail. Event-driven trigger; 25 nodes.

Form Trigger, Form, OpenAI Chat +5
Email & Gmail

The automation loads rows from a Google Sheet of leads that you want to contact. It makes a Google search via Apify for LinkedIn links based on the First name / Last name / Company. Another Apify acto

HTTP Request, Google Sheets, Chain Llm +3