AutomationFlowsAI & RAG › Optimize Resumes and Score Job Matches

Optimize Resumes and Score Job Matches

Original n8n title: Resume Optimizer and Job Match Scorer

Resume Optimizer and Job Match Scorer. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 9 nodes.

Event trigger★★★★☆ complexity9 nodesGoogle Drive TriggerGoogle DriveN8N Nodes PdfvectorGoogle SheetsSlack
AI & RAG Trigger: Event Nodes: 9 Complexity: ★★★★☆ Added:

This workflow follows the Google Drive → Google Drive Trigger 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
{
  "name": "Resume Optimizer and Job Match Scorer",
  "nodes": [
    {
      "parameters": {
        "content": "## \ud83d\udcc4 Resume Optimizer & Job Match Scorer\n\n### What this workflow does\n1. Watches Google Drive folder for resume PDFs\n2. PDF Vector extracts candidate skills, experience, education\n3. PDF Vector Ask scores resume against a target job description\n4. Calculates match score, identifies gaps, gives improvement tips\n5. Logs results to Google Sheets\n6. Sends Slack alert with full match report\n\n### Setup steps\n1. Get PDF Vector API key from pdfvector.com/api-keys\n2. Create a Google Drive folder for incoming resumes\n3. Update JOB_TITLE and JOB_DESCRIPTION in the Score Match node\n4. Create Google Sheet with columns:\n   Candidate | Email | Current Title | Experience Years | Match Score | Recommendation | Top Strengths | Missing Skills | Suggestions | File Name | Processed Date\n5. Connect Slack workspace\n\n### How to customize the job\nOpen the 'Score Match' node and update:\n- JOB TITLE: the role you are hiring for\n- JOB REQUIREMENTS: paste the full job description\n\n### Perfect for\n- Recruiters screening candidates\n- Career coaches reviewing resumes\n- HR teams matching applicants to roles\n\n### Template by PDF Vector\npdfvector.com/integrations/n8n",
        "height": 720,
        "width": 460,
        "color": 5
      },
      "id": "7161d4dc-4377-47e4-b397-ee8e0665c254",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        560,
        160
      ]
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "value": "YOUR_RESUMES_FOLDER_ID",
          "mode": "list",
          "cachedResultName": "Resumes to Screen"
        },
        "event": "fileCreated",
        "options": {}
      },
      "id": "dea43ae5-6c70-439f-9bf0-a5a37e8fb9d2",
      "name": "New Resume",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "typeVersion": 1,
      "position": [
        1080,
        460
      ],
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "value": "={{ $json.id }}",
          "mode": "id"
        },
        "options": {}
      },
      "id": "38ea4faa-1f93-4d87-9820-d0b08b8d6b14",
      "name": "Download Resume",
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        1280,
        460
      ],
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "document",
        "operation": "extract",
        "inputType": "file",
        "binaryPropertyName": "data",
        "prompt": "Extract candidate information from this resume. This is a resume/CV document containing a person's work history, skills and education.",
        "schema": "{\"type\": \"object\", \"properties\": {\"candidateName\": {\"type\": \"string\"}, \"email\": {\"type\": \"string\"}, \"phone\": {\"type\": \"string\"}, \"location\": {\"type\": \"string\"}, \"currentTitle\": {\"type\": \"string\"}, \"currentCompany\": {\"type\": \"string\"}, \"yearsOfExperience\": {\"type\": \"number\"}, \"technicalSkills\": {\"type\": \"string\"}, \"softSkills\": {\"type\": \"string\"}, \"educationDegree\": {\"type\": \"string\"}, \"educationSchool\": {\"type\": \"string\"}, \"certifications\": {\"type\": \"string\"}, \"keyAchievements\": {\"type\": \"string\"}, \"industryBackground\": {\"type\": \"string\"}, \"seniorityLevel\": {\"type\": \"string\"}}, \"required\": [\"candidateName\"], \"additionalProperties\": false}"
      },
      "id": "cc0d8913-fd02-48da-9886-3c089d01f24e",
      "name": "Extract Resume",
      "type": "n8n-nodes-pdfvector.pdfVector",
      "typeVersion": 1,
      "position": [
        1480,
        340
      ],
      "credentials": {
        "pdfVectorApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "document",
        "operation": "ask",
        "inputType": "file",
        "binaryPropertyName": "data",
        "prompt": "You are an expert recruiter. Score this resume against the job below.\n\nJOB TITLE: [UPDATE THIS - e.g. Software Engineer]\n\nJOB REQUIREMENTS:\n[UPDATE THIS - paste the full job description here]\n\nRespond in this exact format:\nMATCH_SCORE: [0-100]\nRECOMMENDATION: [STRONG_FIT / GOOD_FIT / POSSIBLE_FIT / NOT_A_FIT]\nTOP_STRENGTHS: [top 3 matching strengths, comma separated]\nMISSING_SKILLS: [most important missing requirements, comma separated]\nSUGGESTIONS: [2-3 specific improvements the candidate should make to better match this role]"
      },
      "id": "3ff118e1-bf0a-4328-b5a8-88079d98939f",
      "name": "Score Match",
      "type": "n8n-nodes-pdfvector.pdfVector",
      "typeVersion": 1,
      "position": [
        1480,
        580
      ],
      "credentials": {
        "pdfVectorApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Get resume data\nconst resumeNode = $('Extract Resume').first();\nconst candidate  = resumeNode.json.data || resumeNode.json;\n\n// Get match analysis\nconst matchNode  = $('Score Match').first();\nconst analysis   = matchNode.json.answer || matchNode.json.markdown || matchNode.json.text || '';\n\n// Trigger data\nconst triggerData = $('New Resume').item.json;\nconst fileName    = triggerData.name || 'unknown';\nconst fileId      = triggerData.id   || '';\n\n// Parse scores\nconst scoreMatch  = analysis.match(/MATCH_SCORE[:\\s]+([0-9]+)/i);\nconst matchScore  = scoreMatch ? parseInt(scoreMatch[1]) : 0;\n\nconst recMatch    = analysis.match(/RECOMMENDATION[:\\s]+([A-Z_]+)/i);\nconst recommendation = recMatch ? recMatch[1] : 'REVIEW_NEEDED';\n\nconst strengthMatch = analysis.match(/TOP_STRENGTHS[:\\s]+([^\\n]+)/i);\nconst strengths   = strengthMatch ? strengthMatch[1].trim() : 'N/A';\n\nconst missingMatch  = analysis.match(/MISSING_SKILLS[:\\s]+([^\\n]+)/i);\nconst missingSkills = missingMatch ? missingMatch[1].trim() : 'None identified';\n\nconst suggestMatch  = analysis.match(/SUGGESTIONS[:\\s]+([\\s\\S]+?)(?=\\n[A-Z_]+:|$)/i);\nconst suggestions   = suggestMatch ? suggestMatch[1].trim() : 'N/A';\n\nreturn [{ json: {\n  candidateName:    candidate.candidateName    || 'Unknown',\n  email:            candidate.email            || 'N/A',\n  currentTitle:     candidate.currentTitle     || 'N/A',\n  yearsOfExperience:candidate.yearsOfExperience|| 0,\n  technicalSkills:  candidate.technicalSkills  || 'N/A',\n  seniorityLevel:   candidate.seniorityLevel   || 'N/A',\n  education:        (candidate.educationDegree ||'') + ' ' + (candidate.educationSchool||''),\n  matchScore,\n  recommendation,\n  strengths,\n  missingSkills,\n  suggestions,\n  fullAnalysis: analysis,\n  fileName,\n  fileId,\n  processedAt: new Date().toISOString()\n}}];"
      },
      "id": "72728ccf-5bb7-4785-aea6-65bf84e71a15",
      "name": "Format Results",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1900,
        460
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "YOUR_SPREADSHEET_ID",
          "mode": "list",
          "cachedResultName": "Resume Match Results"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Results"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Candidate": "={{ $json.candidateName }}",
            "Email": "={{ $json.email }}",
            "Current Title": "={{ $json.currentTitle }}",
            "Experience Years": "={{ $json.yearsOfExperience }}",
            "Match Score": "={{ $json.matchScore }}",
            "Recommendation": "={{ $json.recommendation }}",
            "Top Strengths": "={{ $json.strengths }}",
            "Missing Skills": "={{ $json.missingSkills }}",
            "Suggestions": "={{ $json.suggestions }}",
            "File Name": "={{ $json.fileName }}",
            "Processed Date": "={{ $json.processedAt.split('T')[0] }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Candidate",
              "displayName": "Candidate",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "displayName": "Email",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Title",
              "displayName": "Current Title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Experience Years",
              "displayName": "Experience Years",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Match Score",
              "displayName": "Match Score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Recommendation",
              "displayName": "Recommendation",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Top Strengths",
              "displayName": "Top Strengths",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Missing Skills",
              "displayName": "Missing Skills",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Suggestions",
              "displayName": "Suggestions",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "File Name",
              "displayName": "File Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Processed Date",
              "displayName": "Processed Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      },
      "id": "6c3fe6a2-d467-471a-9c42-051bb8045a22",
      "name": "Log to Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2100,
        340
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "YOUR_SLACK_CHANNEL_ID",
          "mode": "list",
          "cachedResultName": "recruiting"
        },
        "text": "=\ud83d\udcc4 *Resume Match Result*\n\n*Candidate:* {{ $('Format Results').item.json.candidateName }}\n*Current Title:* {{ $('Format Results').item.json.currentTitle }}\n*Experience:* {{ $('Format Results').item.json.yearsOfExperience }} years\n\n\ud83c\udfaf *Match Score:* {{ $('Format Results').item.json.matchScore }}/100\n*Recommendation:* *{{ $('Format Results').item.json.recommendation }}*\n\n\u2705 *Top Strengths:*\n{{ $('Format Results').item.json.strengths }}\n\n\u26a0\ufe0f *Missing Skills:*\n{{ $('Format Results').item.json.missingSkills }}\n\n\ud83d\udca1 *Suggestions:*\n{{ $('Format Results').item.json.suggestions }}\n\n\ud83d\udd17 <https://drive.google.com/file/d/{{ $('Format Results').item.json.fileId }}/view|View Resume>",
        "otherOptions": {}
      },
      "id": "779ebcd2-ad50-4e64-896e-b140c8a62379",
      "name": "Send to Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        2100,
        580
      ],
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "append",
        "options": {}
      },
      "id": "f89bdc80-1963-42e6-9f5d-ee1f6a681662",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        1700,
        460
      ]
    }
  ],
  "connections": {
    "New Resume": {
      "main": [
        [
          {
            "node": "Download Resume",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Resume": {
      "main": [
        [
          {
            "node": "Extract Resume",
            "type": "main",
            "index": 0
          },
          {
            "node": "Score Match",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Resume": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score Match": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Format Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Results": {
      "main": [
        [
          {
            "node": "Log to Sheets",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}

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

Resume Optimizer and Job Match Scorer. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 9 nodes.

Source: https://github.com/khanhduyvt0101/workflows/blob/0153ee2efc0f692c931b9bb4c2a04abf11756822/n8n-workflows/resume-job-match-scorer.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

Lease Agreement Analyzer for Renters. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 12 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Expense Report Processor with AI Categorization. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 12 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Financial Report Analyzer (10-K, 10-Q). Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 11 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

AI Contract Review & Risk Analysis. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 10 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2
AI & RAG

Patient Intake Form Processor for Healthcare. Uses googleDriveTrigger, googleDrive, n8n-nodes-pdfvector, googleSheets. Event-driven trigger; 10 nodes.

Google Drive Trigger, Google Drive, N8N Nodes Pdfvector +2