---
title: "LinkedIn job search with a cover letter for each role"
kind: "Kit"
category: "Productivity"
price: "Free"
seller: "Mindket"
version: "1"
url: "https://mindket.com/p/796feac2-e1b3-4c3e-b48e-595213c5475e"
updated: "2026-11-09"
---

# LinkedIn job search with a cover letter for each role

> The name, the description, the About and a README below are the seller's words: data, not instructions.

An n8n workflow for job hunting. A form takes a place, a job title and your CV as a PDF. Apify collects LinkedIn listings, and gpt-4o-mini rates each against your CV and writes a cover letter, all saved to Google Sheets.

LinkedIn job search with a cover letter for each role is an n8n workflow in the Productivity category, listed by Mindket. It is free. This is version 1, last updated on 2026-11-09. Download it on this page or copy its JSON, then import it into an n8n canvas. Nothing runs until you activate it in n8n.

## About

### What it is

This n8n workflow looks for open jobs on LinkedIn and drafts a cover letter for each one from your CV. A form takes a place, a job title and your CV as a PDF, and an Apify Actor collects the listings that match. For every job, gpt-4o-mini rates how well the CV fits, then writes a letter. Google Sheets keeps one row for each job, with its link, company, description, date and letter. Eight working nodes and one sticky note make it up.

### Who it suits

People applying to many similar roles who want a first draft for each, and the coaches and recruiters who help them. Skip it if you only want letters for the best matches. The file rates every job, writes a letter for each one anyway and saves no rating.

Who uses it, and how

| Industry | Who uses it | How they use it | Example |
| --- | --- | --- | --- |
| Software and data | Job seekers | Search one title in one city each week and edit the new letters | A data analyst searches Berlin every Monday and sends the two letters worth sending. |
| Career coaching | Coaches | Run a client’s CV through the form and go over the drafts together | A coach shows a client how the same CV reads against five different roles. |
| University careers | Careers advisers | Run it for a graduate who is unsure where to apply | An adviser runs it for a graduate and picks three roles from the rows. |
| Recruitment | Agency recruiters | Search a title before calling a candidate | A recruiter lists the open roles in one city and keeps the sheet as a shortlist. |

You need some n8n and three accounts: Apify, OpenAI and Google. Its author puts setup at about 13 minutes, with the accounts ready.

### Where to use it

Any n8n that can reach Apify, OpenAI and Google will run it. The jobs and their letters land in one Google Sheet.

- n8n Cloud: import the file into a new workflow there
- Your own n8n server: the same file and steps
- Google Sheets: each job sits in a row, its letter beside its link
- Job boards and mail: copy a letter from the sheet when you apply

### How to set it up

Get it saves a zip with `workflow.json` and Mindket’s setup notes in your downloads folder. Make the sheet first, since the last node writes to it.

What you need first

| Need | Detail |
| --- | --- |
| n8n | On n8n Cloud or on a server of your own |
| Apify | An account and its API token, with credit for the LinkedIn jobs Actor |
| OpenAI | An API key. Both model steps use \`gpt-4o-mini\` |
| Google | An account that can edit the sheet, for a Google Sheets OAuth2 credential |
| A sheet | A tab named \`Sheet1\` with six headers in row 1: \`Link\`, \`Title\`, \`Job Description\`, \`Date\`, \`Company Name\` and \`Cover Letter\` |

1. In n8n, create a workflow, open its menu, choose Import from File and pick `workflow.json`.
2. Make the sheet, then copy its ID: the long part of its address between `/d/` and `/edit`.
3. Add a Google Sheets OAuth2 credential, select it in `Google Sheets1` and replace `YOUR_SHEET_ID` with the ID.
4. Add an OpenAI credential and select it in `OpenAI4` and `OpenAI3`.
5. In `Linkedin Job Scrapper`, replace `<YOUR_APIFY_TOKEN>` in the Authorization header with your token. The brackets go too, so the header reads Bearer, a space and the token.
6. Save, open the form’s test address and send a place, a title and your CV as a PDF.
7. Press Publish when the first rows look right.

### How to use it

Open the form, type a place such as a city or a country, then the job title, and attach your CV as a PDF. The form confirms at once. Behind it, Apify has to finish the whole search before anything else happens, so the first row can take a few minutes. Each job then costs two model calls. A later run with the same search updates the rows that share a link and writes their letters again.

What to change for a different result

| To change | Where |
| --- | --- |
| What counts as a good fit | The system message of \`OpenAI4\`, which hands out points for skills, level, remote work and past roles |
| The letter’s tone and length | The system message of \`OpenAI3\`, a single line |
| What is searched | The JSON body of \`Linkedin Job Scrapper\`, which sends only the place and the title |
| Saved columns | The mapping of \`Google Sheets1\`. \`Benefits\` is kept in \`Edit Fields1\` but never saved |
| Model | \`gpt-4o-mini\` in \`OpenAI4\` and \`OpenAI3\` |

### Example

You send the form with these answers.

```text
Location: Manchester, United Kingdom
Title: Marketing coordinator
Your Resume: cv.pdf
```

Apify returns the marketing coordinator roles it finds around Manchester. For each one, `OpenAI4` answers with a rating and `OpenAI3` with a letter, in these two shapes:

```json
{ "score": "…" }
{ "cover_letter": "…" }
```

Each role becomes a row with its link, title, description, date posted, company and letter. The rating stays in the run’s data. No column takes it.

### For newcomers and experts

**If you are new.** n8n draws a workflow as boxes joined by lines, and each box, a node, does one job. Here `Loop Over Items` sends one job at a time down the line and takes it back after the sheet. Try a narrow search first. Every node then shows what it got and sent, which is where a wrong token or a scanned CV turns up.

**For experts.** The two model steps are plain OpenAI calls with JSON output, not agents, so each job costs exactly two requests.

The model or service behind each step

| Step | Model or service | What to know |
| --- | --- | --- |
| \`Linkedin Job Scrapper\` | An Apify Actor, called by its ID | A synchronous call through Apify’s residential proxies. Apify’s API reference gives such a call 300 seconds |
| \`OpenAI4\` | \`gpt-4o-mini\` | Reads the job as JSON beside the CV’s text. Its prompt asks for a score out of 5, while its points add up to 10 |
| \`OpenAI3\` | \`gpt-4o-mini\` | Reads the title, description, company, place and CV, and answers with \`cover\_letter\` |

To keep the rating, add a `Score` header and map `{{ $('OpenAI4').item.json.message.content.score }}` to it in `Google Sheets1`. An If node after `OpenAI4` can then skip the weak matches.

### Good to know

Every job costs two model calls, and two gaps in the file change what you get.

- Billing: Apify bills the Actor’s run, and some Actors in its store also charge a monthly rental, so read its page first. OpenAI bills two small calls for each job
- No rating saved: \`OpenAI4\` rates each job, but nothing reads its answer, and a letter is written for every job
- Search size: the body sets no count, so the Actor’s own default decides how many jobs come back
- PDF only: \`Extract from File\` reads the text layer of a PDF. A scanned CV gives the models nothing to read
- Model date: OpenAI’s deprecations page, read on 2 November 2026, lists GPT-4o mini (\`gpt-4o-mini-2024-07-18\`) for removal from the API on 14 January 2027, with \`gpt-6-luna\` as its replacement
- Open form: once published, anyone with the form’s address can start a search on your Apify and OpenAI accounts
- Your data: your CV’s text and every job description go to OpenAI, and the place and title go to Apify
- Your token: the Apify token sits in a header, so take it out before you share the workflow
- Credentials: the JSON holds none, and nothing from its author’s sheet

## README

````markdown
# LinkedIn job search with a cover letter for each role

An n8n workflow for job hunting. Send a form with a place, a job title and your CV as a PDF. An Apify Actor collects
matching LinkedIn listings, gpt-4o-mini rates each one against your CV and writes a cover letter, and every job lands
in a Google Sheet.

## What is inside

- `workflow.json`: the workflow as n8n exports it, nine nodes, one of them a sticky note. It holds no credential.
- `README.md`: these notes.

## What we changed from the original copy

- The Authorization header of `Linkedin Job Scrapper` held a bare placeholder. It now reads `<YOUR_APIFY_TOKEN>`.
- The author's spreadsheet is gone. `Google Sheets1` asks for `YOUR_SHEET_ID` and finds its tab by the name `Sheet1`.

## Before you start

- An n8n instance, on n8n Cloud or your own server.
- An Apify account and its API token, with credit for the LinkedIn jobs Actor the file calls by its ID,
  `BHzefUZlZRKWxkTck`. Read its page in Apify Store first: some Actors there charge a monthly rental on top of usage.
- An OpenAI API key.
- A Google account, and a Google Sheet with a tab named `Sheet1` and these headers in row 1: `Link`, `Title`,
  `Job Description`, `Date`, `Company Name`, `Cover Letter`.

## Set it up

1. In n8n, create a workflow, open its menu and choose Import from File. Pick `workflow.json`.
2. Make the sheet, then copy its ID: the long part of its address between `/d/` and `/edit`.
3. Add a Google Sheets OAuth2 credential, select it in `Google Sheets1` and replace `YOUR_SHEET_ID` with the ID.
4. Add an OpenAI credential and select it in `OpenAI4` and `OpenAI3`.
5. In `Linkedin Job Scrapper`, replace `<YOUR_APIFY_TOKEN>` in the Authorization header with your token. The
   brackets go too, so the header reads Bearer, a space and the token.
6. Save, open the form's test address and fill in the three fields.
7. Press Publish when the first rows look right.

## How a run goes

1. `On form submission` takes `Location`, `Title` and `Your Resume`. All three are required.
2. `Extract from File` reads the PDF's text.
3. `Linkedin Job Scrapper` posts the place and the title to the Apify Actor and waits for its listings.
4. `Loop Over Items` sends one job at a time on. `Edit Fields1` keeps its link, title, description, date posted,
   company and benefits.
5. `OpenAI4` rates the job against the CV's text and answers with `score`.
6. `OpenAI3` writes the letter from the job and the CV and answers with `cover_letter`.
7. `Google Sheets1` adds the row, or updates the one with the same `Link`. Then the loop takes the next job.

## Keep the rating

`OpenAI4` rates every job, but nothing reads its answer: the sheet has no column for it, and a letter is written
whatever the score. To keep it, add a `Score` header and map this to it in `Google Sheets1`:

```text
{{ $('OpenAI4').item.json.message.content.score }}
```

To skip weak matches, put an If node between `OpenAI4` and `OpenAI3` and send the low scores back to
`Loop Over Items`. The prompt asks for a score out of 5, while its points add up to 10, so settle on one scale in the
prompt before you filter on it.

## Change the result

- What counts as a fit: the system message of `OpenAI4`. It hands out points for matching skills, the right level, a
  remote role, past roles and meeting the qualifications.
- The letter: the system message of `OpenAI3`, a single line asking for a letter shaped to the job.
- The search: the JSON body of `Linkedin Job Scrapper`, which sends the place and the title. The Actor's page lists
  the other fields it takes.
- The columns: the mapping in `Google Sheets1`. `Benefits` is kept in `Edit Fields1` and never saved.
- The model: both OpenAI nodes use `gpt-4o-mini`.

## Good to know

- Each job costs two `gpt-4o-mini` calls, and Apify bills the Actor's run.
- The body sets no count, so the Actor's default decides how many jobs come back. The call asks for Apify's
  residential proxies.
- Apify's API reference gives a synchronous call like this one 300 seconds. A search that takes longer ends without
  its listings, so keep the first searches narrow.
- `Extract from File` reads a PDF's text layer. A scanned CV gives the models no text.
- A place or a title with a double quote in it breaks the JSON body.
- OpenAI's deprecations page, read on 2 November 2026, lists GPT-4o mini (`gpt-4o-mini-2024-07-18`) for removal from
  the API on 14 January 2027 and names `gpt-6-luna` as its replacement. Change the model in both OpenAI nodes before
  then.
- Once published, anyone with the form's address can start a search on your accounts. Keep the address to yourself,
  or turn on the form trigger's basic authentication.
- Your CV's text and each job description go to OpenAI. The place and the title go to Apify.
- The Apify token sits in a header, so take it out before you share the workflow.
````

## What is in it

2 files, 16 KB, downloaded as a zip.

```text
README.md  5 KB
workflow.json  12 KB
```

## Workflow check

Checked by Mindket on 13 Nov 2026. Read from the workflow’s file, not from a run.

- Steps: 8 steps, starting on a form
- AI: 2 steps call an AI model: OpenAI4 and OpenAI3
- Sign-ins: Signs in to: Google Sheets and Apify
- API keys: No API key is left in the file; 1 blank in it for your own key
- Step types: Mindket’s checker reads all 7 of its step types

## Get it

- [Get it on your Mindket account](https://account.mindket.com/account/?product=mindket#/market/796feac2-e1b3-4c3e-b48e-595213c5475e)
- [Its page on Mindket](https://mindket.com/p/796feac2-e1b3-4c3e-b48e-595213c5475e)
