AutomationFlowsEmail & Gmail › Screen Cvs Against Job Descriptions with Gmail, Easybits, Airtable and Slack

Screen Cvs Against Job Descriptions with Gmail, Easybits, Airtable and Slack

ByTerence Hielscher @terence-easybits on n8n.io

How it works

Event trigger★★★★☆ complexity20 nodesGmail TriggerHTTP RequestAirtable
Email & Gmail Trigger: Event Nodes: 20 Complexity: ★★★★☆ Added:
Screen Cvs Against Job Descriptions with Gmail, Easybits, Airtable and Slack — n8n workflow card showing Gmail Trigger, HTTP Request, Airtable integration

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

This workflow follows the Airtable → HTTP Request 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": "wIirge1rt4E3EquqWx9sA",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "CV screening",
  "tags": [],
  "nodes": [
    {
      "id": "f2d12e48-2668-4535-acc3-128f3bd7d1c3",
      "name": "Sticky Note \u2014 Header",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3344,
        976
      ],
      "parameters": {
        "width": 656,
        "height": 1212,
        "content": "## \ud83d\udcc4 CV & Resume Screener\n### Powered by Gmail \u00b7 easybits.tech \u00b7 Airtable \u00b7 Slack\n\nAutomatically reads CVs from Gmail, extracts structured candidate data using AI, scores each applicant against your open job requirements, saves results to Airtable, and notifies your recruiter on Slack \u2014 all without manual review.\n\n---\n\n### \u2705 Prerequisites\nBefore activating this workflow, complete the following setup steps:\n\n**1. Gmail**\n- Connect your Gmail account via OAuth2\n- Applied to: Gmail Trigger node + Download Email node\n\n**2. easybits.tech API Key**\n- Sign up at [easybits.tech](https://easybits.tech) to get your free API key\n- Add the key to the `httpCustomAuth` credential in n8n\n- Update the pipeline ID in the `easybits: Extract CV Data` node\n\n**3. Airtable**\n- Create a base with two tables: **Jobs** and **Candidates**\n- Run the companion **Job Description Parser** workflow first to populate the Jobs table\n- Update the Base ID and Table IDs in all Airtable nodes\n\n**4. Slack**\n- Create two Slack Incoming Webhooks (one per channel or status)\n- Paste each webhook URL into the respective `Slack: Notify` nodes\n\n---\n\n### \u2699\ufe0f How It Works\n1. **Gmail Trigger** polls for unread emails with CV attachments\n2. **Download & Prepare** fetches the email, extracts the PDF, and base64-encodes it\n3. **easybits Extract** sends the PDF to the AI pipeline and returns clean JSON\n4. **Fetch Open Job** pulls the first open role from your Airtable Jobs table\n5. **Score CV** compares candidate skills against the job's tech stack requirements\n6. **Route by Score** splits candidates: \u2265 60% \u2192 Shortlisted \u00b7 < 60% \u2192 In Review\n7. **Save & Notify** creates the candidate record in Airtable and posts a Slack summary\n\n---\n\n### \ud83d\udd27 Customisation\n- **Score threshold**: Change the value `60` in the IF node (Step 6)\n- **Email filter**: Edit the Gmail search query in the trigger node\n- **Scoring logic**: Adjust the Code node in Step 5 to weight skills differently\n- **Fields**: Add or remove fields in the Airtable nodes to match your Candidates table schema"
      },
      "typeVersion": 1
    },
    {
      "id": "3a1f6b36-74eb-493e-a748-71dc842f2f8f",
      "name": "Sticky Note \u2014 Step 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4021,
        1396
      ],
      "parameters": {
        "color": 7,
        "width": 406,
        "height": 428,
        "content": "### Step 1 \u00b7 Get Email & Attachment\n\n\ud83d\udce7 **Gmail Trigger** polls every minute for unread emails matching:\n`has:attachment subject:(Application OR CV OR Resume OR Bewerbung)`\n\n**Setup required:**\n- Connect Gmail via OAuth2\n- Adjust the `after:` date and subject keywords to match your inbox"
      },
      "typeVersion": 1
    },
    {
      "id": "f3118ccb-bfd0-43d4-8388-f7ce02dfa5a0",
      "name": "Sticky Note \u2014 Step 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4477,
        1396
      ],
      "parameters": {
        "color": 7,
        "width": 390,
        "height": 428,
        "content": "### Step 2 \u00b7 Download & Prepare PDF\n\n\ud83d\udce5 Downloads the full email via Gmail API, extracts the PDF attachment, and base64-encodes it.\n\n\u26a0\ufe0f **File size limit:** PDFs over ~600 KB will be rejected by the Code node to stay within API limits.\n\n**Setup required:**\n- Same Gmail OAuth2 credential as Step 1\n- Attachment index `parts[1]` assumes the PDF is the second part \u2014 adjust if needed"
      },
      "typeVersion": 1
    },
    {
      "id": "32fa7ad3-fbc7-4d06-bbd9-5a74fbbdb07e",
      "name": "Sticky Note \u2014 Step 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4891,
        1268
      ],
      "parameters": {
        "color": 7,
        "width": 234,
        "height": 556,
        "content": "### Step 3 \u00b7 Extract CV with easybits\n\n\ud83e\udd16 Sends the base64 PDF to the easybits.tech AI pipeline and returns structured JSON (name, email, skills, experience, education, etc.)\n\n**Setup required:**\n- Add your API key to the `httpCustomAuth` credential\n- Replace the pipeline ID in the URL with your own CV extraction pipeline ID\n- Get your free key at [easybits.tech](https://easybits.tech)"
      },
      "typeVersion": 1
    },
    {
      "id": "6607e358-4b04-4712-aef0-0f3bd26d7f8b",
      "name": "Sticky Note \u2014 Step 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5119,
        1220
      ],
      "parameters": {
        "color": 7,
        "width": 226,
        "height": 604,
        "content": "### Step 4 \u00b7 Fetch Open Job\n\n\ud83d\udccb Queries Airtable for the first record where `status = \"Open\"` to get the active job's requirements.\n\n**Setup required:**\n- Update the **Airtable Base ID** and **Jobs table ID**\n- Ensure the Jobs table has a `status` field and a `tech_stack` field (comma-separated or array)\n- Run the **Job Description Parser** workflow first to populate this table"
      },
      "typeVersion": 1
    },
    {
      "id": "1f738c86-57e3-4625-8c3c-569f0bafbc15",
      "name": "Sticky Note \u2014 Step 5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5348,
        1220
      ],
      "parameters": {
        "color": 7,
        "width": 216,
        "height": 604,
        "content": "### Step 5 \u00b7 Score CV vs Job\n\n\ud83e\uddee Compares the candidate's extracted CV text against each item in the job's `tech_stack` field.\n\n**Scoring formula:**\n`score = matched skills \u00f7 total required skills \u00d7 100`\n\n**Customise:**\n- Edit this Code node to add weighted scoring (e.g. must-have vs nice-to-have)\n- Add extra matching fields beyond tech_stack"
      },
      "typeVersion": 1
    },
    {
      "id": "172948e1-bb9f-4419-9edd-c764b667fc78",
      "name": "Sticky Note \u2014 Step 6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5581,
        1220
      ],
      "parameters": {
        "color": 7,
        "width": 198,
        "height": 604,
        "content": "### Step 6 \u00b7 Route by Score\n\n\ud83d\udd00 Routes candidates based on their match score:\n\n- \u2705 **\u2265 60%** \u2192 `true` branch \u2192 **Shortlisted**\n- \ud83d\udd0e **< 60%** \u2192 `false` branch \u2192 **In Review**\n\n**Customise:**\n- Change the threshold value `60` in this IF node to raise or lower the bar\n- Default was 80% \u2014 lowered to 60% to cast a wider net"
      },
      "typeVersion": 1
    },
    {
      "id": "7f530826-8eae-4ed3-8a2a-f559c8629759",
      "name": "Sticky Note \u2014 Step 7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5788,
        1188
      ],
      "parameters": {
        "color": 7,
        "width": 456,
        "height": 732,
        "content": "### Step 7 \u00b7 Save to Airtable & Notify on Slack\n\n\ud83d\udcbe Creates a candidate record in your Airtable **Candidates** table with status set to either `Shortlisted` or `In Review`.\n\n\ud83d\udce3 Posts a formatted summary card to Slack with the candidate name, match score, job title, matched skills, and LinkedIn URL.\n\n**Setup required:**\n- Update the **Airtable Base ID** and **Candidates table ID** in both Airtable nodes\n- Paste your **Slack webhook URLs** into both HTTP Request (Slack) nodes\n- Ensure your Candidates table fields match the column names mapped in the Airtable nodes"
      },
      "typeVersion": 1
    },
    {
      "id": "88dce86a-3ee8-46ec-8e93-62ae9ca6dd26",
      "name": "Gmail: Watch CV Emails",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        4064,
        1664
      ],
      "parameters": {
        "simple": false,
        "filters": {
          "q": "has:attachment subject:(Application OR CV OR Bewerbung OR Resume) after:2026/03/12",
          "readStatus": "unread"
        },
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "80d51d67-5511-406a-9f09-35125123c900",
      "name": "Download Email & Attachment",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4288,
        1664
      ],
      "parameters": {
        "url": "=https://gmail.googleapis.com/gmail/v1/users/me/messages/{{ $json.id }}?format=full",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "gmailOAuth2"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "ff0c2db5-ea81-4070-bf93-d82d2a131937",
      "name": "Convert PDF to Base64",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4512,
        1664
      ],
      "parameters": {
        "url": "=https://gmail.googleapis.com/gmail/v1/users/me/messages/{{ $json.id }}/attachments/{{ $json.payload.parts[1].body.attachmentId }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "gmailOAuth2"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "b7020e7c-6334-4dd0-a669-6699b5eb65fe",
      "name": "Prepare PDF Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        4736,
        1664
      ],
      "parameters": {
        "jsCode": "const base64String = $input.first().json.data;\nconst sizeKB = Math.round(base64String.length / 1024);\n\nif (base64String.length > 800000) {\n  throw new Error(`CV too large: ${sizeKB}KB. Please use a PDF under 600KB.`);\n}\n\nreturn [{\n  json: {\n    base64: base64String,\n    sizeKB: sizeKB\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "aaf48e8a-6c2f-4a08-9d63-463602e13a30",
      "name": "easybits: Extract CV Data",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        4960,
        1664
      ],
      "parameters": {
        "url": "https://extractor.easybits.tech/api/pipelines/8ppfebcZMIysqGMaUzli",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"files\": [\"data:application/pdf;base64,{{ $json.base64 }}\"]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "3e929414-7fe0-47f8-bc5c-68cd6b2c11f3",
      "name": "Airtable - Fetch Open Job",
      "type": "n8n-nodes-base.airtable",
      "position": [
        5184,
        1664
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "appN5gwc0tof1nc0Y"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblgftBvUd3PgfgKM",
          "cachedResultUrl": "https://airtable.com/appN5gwc0tof1nc0Y/tblgftBvUd3PgfgKM",
          "cachedResultName": "Jobs"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "status = \"Open\""
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "3a4f786f-7ad4-4934-b02a-ce28e77a1a92",
      "name": "Score CV vs Job Description ",
      "type": "n8n-nodes-base.code",
      "position": [
        5408,
        1664
      ],
      "parameters": {
        "jsCode": "// 1. Get data from the previous nodes\nconst extraction = $node[\"easybits: Extract CV Data\"].json.data;\n// We use the first item from Airtable (index 0)\nconst job = $node[\"Airtable - Fetch Open Job\"].json; \n\n// Combine everything the CV parser found into one text block\nconst cvText = JSON.stringify(extraction).toLowerCase();\n\n// 2. Score against the TECH STACK instead of the long phrases\n// This list has \"Python\", \"Figma\", \"Clay\", etc.\nconst techRequirements = job.tech_stack || [];\n\nlet matches = 0;\nlet foundItems = [];\n\ntechRequirements.forEach(skill => {\n  // Clean up the skill name and check if it's in the CV\n  const cleanSkill = skill.toLowerCase().trim();\n  if (cvText.includes(cleanSkill)) {\n    matches++;\n    foundItems.push(skill);\n  }\n});\n\n// 3. Calculate Score\nconst total = techRequirements.length || 1;\nconst finalScore = Math.round((matches / total) * 100);\n\nreturn {\n  match_score: finalScore,\n  matched_count: matches,\n  total_possible: total,\n  details: foundItems.join(\", \"),\n  name: extraction.candidate_name || \"Jordan Reed\",\n  email: extraction.contact_email || \"N/A\",\n  linkedin: extraction.linkedin_url || \"N/A\"\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "0ae553ee-ca8d-44f0-bb71-8a38be3e34f1",
      "name": "Route by Score ",
      "type": "n8n-nodes-base.if",
      "position": [
        5632,
        1664
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d89ea650-898a-46ad-8782-a1f8d305ada0",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.matchScore }}",
              "rightValue": 60
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "f9c742df-dd7c-4a27-a223-868a59333725",
      "name": "Airtable: Save Reviewed Candidate",
      "type": "n8n-nodes-base.airtable",
      "position": [
        5856,
        1568
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "appN5gwc0tof1nc0Y"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblTYVUhoy9QKNnmT",
          "cachedResultUrl": "https://airtable.com/appN5gwc0tof1nc0Y/tblTYVUhoy9QKNnmT",
          "cachedResultName": "Candidates"
        },
        "columns": {
          "value": {
            "skills": "={{ $json.skills.join(', ') }}",
            "status": "Shortlisted",
            "languages": "={{ $json.languages.join(', ') }}",
            "match_score": "={{ $json.matchScore }}",
            "availability": "={{ $json.availability }}",
            "linkedin_url": "={{ $json.linkedin_url }}",
            "contact_email": "={{ $json.contact_email }}",
            "contact_phone": "={{ $json.contact_phone }}",
            "candidate_name": "={{ $json.candidate_name }}",
            "highest_degree": "={{ $json.highest_degree }}",
            "contact_address": "={{ $json.contact_address }}",
            "current_job_title": "={{ $json.current_job_title }}",
            "years_of_experience": "={{ $json.years_of_experience }}",
            "current_company_name": "={{ $json.current_company_name }}",
            "current_employment_start_date": "={{ $json.current_employment_start_date }}",
            "highest_education_institution": "={{ $json.highest_education_institution }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "typecast": true
        },
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e9ffc87f-0677-44b5-8b55-a4184a1b70b8",
      "name": "Slack: Notify For Review",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6080,
        1568
      ],
      "parameters": {
        "url": "https://hooks.slack.com/services/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",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\ud83d\udc40 *Review Needed* \u2014 New Candidate!\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"fields\": [\n        { \"type\": \"mrkdwn\", \"text\": \"*Name:*\\n{{ $('Score CV vs Job Description ').item.json.candidate_name }}\" },\n        { \"type\": \"mrkdwn\", \"text\": \"*Score:*\\n{{ $('Score CV vs Job Description ').item.json.matchScore }}%\" },\n        { \"type\": \"mrkdwn\", \"text\": \"*Title:*\\n{{ $('Score CV vs Job Description ').item.json.current_job_title }}\" },\n        { \"type\": \"mrkdwn\", \"text\": \"*Company:*\\n{{ $('Score CV vs Job Description ').item.json.current_company_name }}\" },\n        { \"type\": \"mrkdwn\", \"text\": \"*Email:*\\n{{ $('Score CV vs Job Description ').item.json.contact_email }}\" },\n        { \"type\": \"mrkdwn\", \"text\": \"*Matched Job:*\\n{{ $('Score CV vs Job Description ').item.json.jobTitle }}\" }\n      ]\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.3
    },
    {
      "id": "e8e35dcf-a86d-479d-84d9-8cbabc8d1801",
      "name": "Slack: Notify For Review1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6080,
        1760
      ],
      "parameters": {
        "url": "https://hooks.slack.com/services/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",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\ud83d\ude80 *New Candidate Match: Easybits.tech*\\n*Name:* {{ $node['Score CV vs Job Description '].json.name }}\\n*Score:* {{ $node['Score CV vs Job Description '].json.match_score }}%\\n*Role:* {{ $node['Airtable - Fetch Open Job'].json.job_title }}\\n*Matched:* {{ $node['Score CV vs Job Description '].json.details }}\\n*LinkedIn:* {{ $node['Score CV vs Job Description '].json.linkedin }}\"\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.3
    },
    {
      "id": "00384117-dbd3-44df-8db5-aec96644c251",
      "name": "Airtable: Save Review Candidate",
      "type": "n8n-nodes-base.airtable",
      "position": [
        5856,
        1760
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "id",
          "value": "appN5gwc0tof1nc0Y"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblTYVUhoy9QKNnmT",
          "cachedResultUrl": "https://airtable.com/appN5gwc0tof1nc0Y/tblTYVUhoy9QKNnmT",
          "cachedResultName": "Candidates"
        },
        "columns": {
          "value": {
            "skills": "={{ $json.skills.join(', ') }}",
            "status": "In Review",
            "languages": "={{ $json.languages.join(', ') }}",
            "match_score": "={{ $json.matchScore }}",
            "availability": "={{ $json.availability }}",
            "linkedin_url": "={{ $json.linkedin_url }}",
            "contact_email": "={{ $json.contact_email }}",
            "contact_phone": "={{ $json.contact_phone }}",
            "candidate_name": "={{ $json.candidate_name }}",
            "highest_degree": "={{ $json.highest_degree }}",
            "contact_address": "={{ $json.contact_address }}",
            "current_job_title": "={{ $json.current_job_title }}",
            "years_of_experience": "={{ $json.years_of_experience }}",
            "current_company_name": "={{ $json.current_company_name }}",
            "current_employment_start_date": "={{ $json.current_employment_start_date }}",
            "highest_education_institution": "={{ $json.highest_education_institution }}"
          },
          "schema": [],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "typecast": true
        },
        "operation": "create"
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "active": true,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "ccaf6584-bb29-4051-ae84-79f28761c385",
  "connections": {
    "Route by Score ": {
      "main": [
        [
          {
            "node": "Airtable: Save Reviewed Candidate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Airtable: Save Review Candidate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare PDF Payload": {
      "main": [
        [
          {
            "node": "easybits: Extract CV Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert PDF to Base64": {
      "main": [
        [
          {
            "node": "Prepare PDF Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail: Watch CV Emails": {
      "main": [
        [
          {
            "node": "Download Email & Attachment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable - Fetch Open Job": {
      "main": [
        [
          {
            "node": "Score CV vs Job Description ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "easybits: Extract CV Data": {
      "main": [
        [
          {
            "node": "Airtable - Fetch Open Job",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Email & Attachment": {
      "main": [
        [
          {
            "node": "Convert PDF to Base64",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score CV vs Job Description ": {
      "main": [
        [
          {
            "node": "Route by Score ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable: Save Review Candidate": {
      "main": [
        [
          {
            "node": "Slack: Notify For Review1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Airtable: Save Reviewed Candidate": {
      "main": [
        [
          {
            "node": "Slack: Notify For Review",
            "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

How it works

Source: https://n8n.io/workflows/14295/ — 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 is built to be customized for your specific needs. This template has the core logic and n8n node specific references sorted to work with dynamic file names throughout the workflow. Store

Gmail, Slack, Gmail Trigger +3
Email & Gmail

📘 Description

HTTP Request, Gmail Trigger, ClickUp +3
Email & Gmail

This n8n workflow is designed for IT security professionals, email administrators, and organizations that want to automatically scan URLs received in emails for potential security threats. It provides

Gmail Trigger, HTTP Request, N8N Nodes Rapiwa +2
Email & Gmail

This workflow automatically detects duplicate invoices from Gmail. Incoming PDF attachments are scanned by the easybits AI Extractor, then checked against the Master Finance File in Google Sheets. Dup

Google Sheets, Gmail Trigger, HTTP Request +1
Email & Gmail

Our invoice extraction workflow is completed end-to-end automatically: Gmail invoice email screening → extraction of key fields from multi-format invoices → automatic archiving of results to Google Dr

Gmail Trigger, Google Drive, HTTP Request