Postuler à des emplois depuis Excel et suivre le statut des candidatures

Avancé

Ceci est unPersonal Productivity, Multimodal AIworkflow d'automatisation du domainecontenant 24 nœuds.Utilise principalement des nœuds comme If, Set, Cron, Gmail, Filter. Demandes d'emploi et suivi de statut automatisés basés sur LinkedIn, Indeed et Google Sheets

Prérequis
  • Compte Google et informations d'identification Gmail API
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
  • Informations d'identification Google Sheets API
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "name": "Apply to Jobs from Excel and Track Application Status",
  "tags": [
    {
      "id": "job-automation",
      "name": "Job Automation",
      "createdAt": "2025-01-15T00:00:00.000Z",
      "updatedAt": "2025-01-15T00:00:00.000Z"
    }
  ],
  "nodes": [
    {
      "id": "template-overview",
      "name": "📋 Aperçu du modèle",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        380,
        160
      ],
      "parameters": {
        "color": 4,
        "width": 389,
        "height": 464,
        "content": "## 🎯 Job Application Automation System\n\n**What it does:**\n- Reads job listings from Google Sheets\n- Automatically applies to jobs with personalized cover letters\n- Tracks application status every 2 days\n- Sends email notifications for updates\n- Maintains complete application history\n\n**Who's it for:**\n- Job seekers wanting to automate repetitive applications\n- Recruiters managing bulk applications\n- Career coaches tracking client progress\n\n**Requirements:**\n- Google Sheets with job data\n- Gmail account for notifications\n- Resume stored online (Google Drive recommended)\n- Job platform API access (LinkedIn, Indeed)\n\n**Setup Instructions:**\n1. Create Google Sheet with required columns\n2. Configure your spreadsheet ID in 'Configuration' node\n3. Set up Google Sheets and Gmail credentials\n4. Update email addresses in notification nodes\n5. Test with 1-2 jobs before full automation\n\n**⚠️ Important:** Replace mock HTTP requests with actual job platform APIs. Current implementation is for demonstration purposes."
      },
      "typeVersion": 1
    },
    {
      "id": "sheet-structure",
      "name": "📊 Structure de la feuille",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        820,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 295,
        "height": 284,
        "content": "## 📊 Excel Sheet Structure\n\nRequired columns:\n- Job_ID: Unique identifier\n- Company: Company name\n- Position: Job title\n- Status: Not Applied, Applied, etc.\n- Applied_Date: Application date\n- Last_Checked: Last status check\n- Application_ID: Platform reference\n- Notes: Additional info\n- Job_URL: Direct job link\n- Priority: High, Medium, Low"
      },
      "typeVersion": 1
    },
    {
      "id": "setup-notes",
      "name": "⚙️ Notes de configuration",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1180,
        160
      ],
      "parameters": {
        "color": 6,
        "width": 295,
        "height": 224,
        "content": "## 🔧 Configuration Setup\n\n1. Replace 'YOUR_GOOGLE_SHEET_ID' with actual ID\n2. Add your resume URL (Google Drive link)\n3. Customize cover letter template\n4. Update email addresses\n\n**Security Note:** Never hardcode API keys!\nUse n8n's credential store for all auth."
      },
      "typeVersion": 1
    },
    {
      "id": "daily-trigger",
      "name": "🕘 Déclencheur de candidature quotidien",
      "type": "n8n-nodes-base.cron",
      "position": [
        240,
        480
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1-5"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "configuration",
      "name": "⚙️ Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        460,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "spreadsheet-id",
              "name": "spreadsheetId",
              "type": "string",
              "value": "REPLACE_WITH_YOUR_GOOGLE_SHEET_ID"
            },
            {
              "id": "resume-url",
              "name": "resumeUrl",
              "type": "string",
              "value": "https://drive.google.com/file/d/YOUR_RESUME_ID/view"
            },
            {
              "id": "cover-letter",
              "name": "coverLetterTemplate",
              "type": "string",
              "value": "Dear Hiring Manager,\n\nI am excited to apply for the {{position}} role at {{company}}. With my experience in software development and {{skills}}, I believe I would be a valuable addition to your team.\n\nI am particularly drawn to {{company}} because of your innovation in the tech industry. I would love to contribute to your continued success.\n\nBest regards,\nYour Name"
            },
            {
              "id": "user-email",
              "name": "userEmail",
              "type": "string",
              "value": "your-email@example.com"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "read-jobs",
      "name": "📖 Lire la feuille des offres",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        680,
        480
      ],
      "parameters": {
        "range": "A:J",
        "keyRow": 1,
        "dataMode": "autoMapInputData",
        "sheetName": "Jobs",
        "documentId": "={{ $json.spreadsheetId }}",
        "requestMethod": "GET",
        "authentication": "oAuth2"
      },
      "typeVersion": 4
    },
    {
      "id": "filter-pending",
      "name": "🎯 Filtrer les candidatures en attente",
      "type": "n8n-nodes-base.filter",
      "position": [
        900,
        480
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "not-applied",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Not Applied"
            },
            {
              "id": "has-url",
              "operator": {
                "type": "string",
                "operation": "isNotEmpty"
              },
              "leftValue": "={{ $json.Job_URL }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "split-jobs",
      "name": "🔄 Traiter les offres une par une",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1120,
        480
      ],
      "parameters": {
        "options": {
          "reset": false
        },
        "batchSize": 1
      },
      "typeVersion": 3
    },
    {
      "id": "prepare-data",
      "name": "📝 Préparer les données de candidature",
      "type": "n8n-nodes-base.set",
      "position": [
        1340,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "job-platform",
              "name": "platform",
              "type": "string",
              "value": "={{ $json.Job_URL.includes('linkedin.com') ? 'linkedin' : $json.Job_URL.includes('indeed.com') ? 'indeed' : 'generic' }}"
            },
            {
              "id": "personalized-cover",
              "name": "personalizedCoverLetter",
              "type": "string",
              "value": "={{ $('Configuration').first().json.coverLetterTemplate.replace('{{position}}', $json.Position).replace('{{company}}', $json.Company).replace('{{skills}}', 'relevant technical skills') }}"
            },
            {
              "id": "application-date",
              "name": "applicationDate",
              "type": "string",
              "value": "={{ $now.format('yyyy-MM-dd') }}"
            },
            {
              "id": "resume-url",
              "name": "resumeUrl",
              "type": "string",
              "value": "={{ $('Configuration').first().json.resumeUrl }}"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "platform-router",
      "name": "🔀 Router par plateforme",
      "type": "n8n-nodes-base.switch",
      "position": [
        1560,
        480
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "linkedin-check",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.platform }}",
              "rightValue": "linkedin"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "linkedin-apply",
      "name": "💼 Postuler via LinkedIn",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1780,
        380
      ],
      "parameters": {
        "url": "https://api.linkedin.com/v2/jobs/applications",
        "options": {
          "retry": {
            "enabled": true,
            "maxTries": 3
          },
          "timeout": 30000
        },
        "sendBody": true,
        "sendHeaders": true,
        "requestMethod": "POST",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "jobId",
              "value": "={{ $json.Job_ID }}"
            },
            {
              "name": "coverLetter",
              "value": "={{ $json.personalizedCoverLetter }}"
            },
            {
              "name": "resumeUrl",
              "value": "={{ $json.resumeUrl }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "linkedInOAuth2Api"
      },
      "typeVersion": 4
    },
    {
      "id": "indeed-apply",
      "name": "🔍 Postuler via Indeed",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1780,
        580
      ],
      "parameters": {
        "url": "https://api.indeed.com/ads/applications",
        "options": {
          "retry": {
            "enabled": true,
            "maxTries": 3
          },
          "timeout": 30000
        },
        "sendBody": true,
        "sendHeaders": true,
        "requestMethod": "POST",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "jobkey",
              "value": "={{ $json.Job_ID }}"
            },
            {
              "name": "message",
              "value": "={{ $json.personalizedCoverLetter }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "indeedApi"
      },
      "typeVersion": 4
    },
    {
      "id": "process-result",
      "name": "📊 Traiter le résultat de la candidature",
      "type": "n8n-nodes-base.set",
      "position": [
        2000,
        480
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "application-status",
              "name": "applicationStatus",
              "type": "string",
              "value": "={{ $json.statusCode >= 200 && $json.statusCode < 300 ? 'Applied' : 'Failed' }}"
            },
            {
              "id": "app-id",
              "name": "applicationId",
              "type": "string",
              "value": "={{ $json.body?.applicationId || $json.body?.id || 'AUTO_' + $now.format('yyyyMMddHHmmss') }}"
            },
            {
              "id": "status-notes",
              "name": "statusNotes",
              "type": "string",
              "value": "={{ $json.statusCode >= 200 && $json.statusCode < 300 ? 'Application submitted successfully via ' + $('Prepare Application Data').first().json.platform : 'Application failed: ' + $json.statusCode }}"
            },
            {
              "id": "job-data",
              "name": "originalJobData",
              "type": "object",
              "value": "={{ $('Prepare Application Data').first().json }}"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "update-status",
      "name": "📝 Mettre à jour le statut de l'offre",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2220,
        480
      ],
      "parameters": {
        "range": "D{{ $json.originalJobData.row_index }}:H{{ $json.originalJobData.row_index }}",
        "keyRow": 1,
        "values": {
          "values": [
            [
              "={{ $json.applicationStatus }}",
              "={{ $json.originalJobData.applicationDate }}",
              "={{ $json.originalJobData.applicationDate }}",
              "={{ $json.applicationId }}",
              "={{ $json.statusNotes }}"
            ]
          ]
        },
        "dataMode": "autoMapInputData",
        "sheetName": "Jobs",
        "documentId": "={{ $('Configuration').first().json.spreadsheetId }}",
        "requestMethod": "UPDATE",
        "authentication": "oAuth2",
        "valueInputMode": "raw"
      },
      "typeVersion": 4
    },
    {
      "id": "send-notification",
      "name": "📧 Envoyer une notification de candidature",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2440,
        480
      ],
      "parameters": {
        "email": "={{ $('Configuration').first().json.userEmail }}",
        "message": "<h3>Application Status Update</h3>\n<p><strong>Company:</strong> {{ $json.originalJobData.Company }}</p>\n<p><strong>Position:</strong> {{ $json.originalJobData.Position }}</p>\n<p><strong>Status:</strong> {{ $json.applicationStatus }}</p>\n<p><strong>Date:</strong> {{ $json.originalJobData.applicationDate }}</p>\n<p><strong>Platform:</strong> {{ $json.originalJobData.platform }}</p>\n<p><strong>Notes:</strong> {{ $json.statusNotes }}</p>\n<p><strong>Application ID:</strong> {{ $json.applicationId }}</p>",
        "subject": "Job Application: {{ $json.originalJobData.Company }} - {{ $json.originalJobData.Position }}",
        "operation": "sendEmail",
        "emailFormat": "html"
      },
      "typeVersion": 2
    },
    {
      "id": "status-tracking-info",
      "name": "📊 Informations de suivi de statut",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        380,
        740
      ],
      "parameters": {
        "color": 7,
        "width": 329,
        "height": 204,
        "content": "## 📈 Status Tracking Workflow\n\nThis section runs every 2 days to:\n- Check status of applied jobs\n- Update the spreadsheet\n- Send notifications for changes\n\n**Note:** Replace mock status checks with actual API calls to job platforms for real status updates."
      },
      "typeVersion": 1
    },
    {
      "id": "status-trigger",
      "name": "🕐 Déclencheur de vérification de statut",
      "type": "n8n-nodes-base.cron",
      "position": [
        240,
        980
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 10 */2 * *"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "read-applied",
      "name": "📖 Lire les offres postulées",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        460,
        980
      ],
      "parameters": {
        "range": "A:J",
        "keyRow": 1,
        "dataMode": "autoMapInputData",
        "sheetName": "Jobs",
        "documentId": "={{ $('Configuration').first().json.spreadsheetId }}",
        "requestMethod": "GET",
        "authentication": "oAuth2"
      },
      "typeVersion": 4
    },
    {
      "id": "filter-applied",
      "name": "🎯 Filtrer les offres postulées",
      "type": "n8n-nodes-base.filter",
      "position": [
        680,
        980
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "applied-filter",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "Applied"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "split-status",
      "name": "🔄 Vérifier le statut une par une",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        900,
        980
      ],
      "parameters": {
        "options": {
          "reset": false
        },
        "batchSize": 1
      },
      "typeVersion": 3
    },
    {
      "id": "mock-status-check",
      "name": "🔍 Vérification de statut simulée",
      "type": "n8n-nodes-base.set",
      "position": [
        1120,
        980
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "mock-status",
              "name": "newStatus",
              "type": "string",
              "value": "={{ ['Applied', 'Under Review', 'Interview Scheduled', 'Rejected'][Math.floor(Math.random() * 4)] }}"
            },
            {
              "id": "check-date",
              "name": "checkDate",
              "type": "string",
              "value": "={{ $now.format('yyyy-MM-dd') }}"
            },
            {
              "id": "status-notes",
              "name": "statusNotes",
              "type": "string",
              "value": "Status checked automatically via API"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "status-changed",
      "name": "🔄 Vérifier si le statut a changé",
      "type": "n8n-nodes-base.if",
      "position": [
        1340,
        980
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "status-changed",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.Status }}",
              "rightValue": "={{ $json.newStatus }}"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "update-changed",
      "name": "📝 Mettre à jour le statut modifié",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1560,
        980
      ],
      "parameters": {
        "range": "D{{ $json.row_index }}:F{{ $json.row_index }}",
        "keyRow": 1,
        "values": {
          "values": [
            [
              "={{ $json.newStatus }}",
              "={{ $json.Applied_Date }}",
              "={{ $json.checkDate }}"
            ]
          ]
        },
        "dataMode": "autoMapInputData",
        "sheetName": "Jobs",
        "documentId": "={{ $('Configuration').first().json.spreadsheetId }}",
        "requestMethod": "UPDATE",
        "authentication": "oAuth2",
        "valueInputMode": "raw"
      },
      "typeVersion": 4
    },
    {
      "id": "send-status-update",
      "name": "📧 Envoyer une mise à jour de statut",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1780,
        980
      ],
      "parameters": {
        "email": "={{ $('Configuration').first().json.userEmail }}",
        "message": "<h3>Application Status Changed</h3>\n<p><strong>Company:</strong> {{ $json.Company }}</p>\n<p><strong>Position:</strong> {{ $json.Position }}</p>\n<p><strong>Previous Status:</strong> {{ $json.Status }}</p>\n<p><strong>New Status:</strong> {{ $json.newStatus }}</p>\n<p><strong>Last Checked:</strong> {{ $json.checkDate }}</p>\n<p><strong>Notes:</strong> {{ $json.statusNotes }}</p>",
        "subject": "Status Update: {{ $json.Company }} - {{ $json.Position }}",
        "operation": "sendEmail",
        "emailFormat": "html"
      },
      "typeVersion": 2
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "updatedAt": "2025-01-15T00:00:00.000Z",
  "versionId": "1",
  "staticData": null,
  "connections": {
    "configuration": {
      "main": [
        [
          {
            "node": "read-jobs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "read-jobs": {
      "main": [
        [
          {
            "node": "filter-pending",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "indeed-apply": {
      "main": [
        [
          {
            "node": "process-result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "read-applied": {
      "main": [
        [
          {
            "node": "filter-applied",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "update-status": {
      "main": [
        [
          {
            "node": "send-notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "platform-router": {
      "main": [
        [
          {
            "node": "linkedin-apply",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "indeed-apply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "mock-status-check": {
      "main": [
        [
          {
            "node": "status-changed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "linkedin-apply": {
      "main": [
        [
          {
            "node": "process-result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "filter-applied": {
      "main": [
        [
          {
            "node": "split-status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "status-trigger": {
      "main": [
        [
          {
            "node": "read-applied",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "update-changed": {
      "main": [
        [
          {
            "node": "send-status-update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "split-status": {
      "main": [
        [
          {
            "node": "mock-status-check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "status-changed": {
      "main": [
        [
          {
            "node": "update-changed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "split-jobs": {
      "main": [
        [
          {
            "node": "prepare-data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "prepare-data": {
      "main": [
        [
          {
            "node": "platform-router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "daily-trigger": {
      "main": [
        [
          {
            "node": "configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "process-result": {
      "main": [
        [
          {
            "node": "update-status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "filter-pending": {
      "main": [
        [
          {
            "node": "split-jobs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 2
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - Productivité personnelle, IA Multimodale

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds24
Catégorie2
Types de nœuds10
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34