Automate your job search and reach the hiring contact with n8n
Search LinkedIn, RemoteOK, and We Work Remotely daily, score every job with AI, draft an application note, find the recruiter or hiring manager on LinkedIn, and send them a connection request.
Run a daily job search across LinkedIn, RemoteOK, and We Work Remotely, score every opening against your profile with AI, draft an application note for strong fits, find the right person at each company on LinkedIn, and send them a personalized connection request under your name. Every job lands in Google Sheets with its score, notes, and outreach status.
Why being early matters in a job search, and how to run the same flow from MCP or REST: see the playbook Automate your LinkedIn job search.
Import the template: Search and outreach to top-fit jobs with LinkedIn, RemoteOK, WWR, Claude and Sheets
What you need
- A Periodix Actions account with a connected LinkedIn profile (3-day free trial)
- The Periodix Actions node installed (listed in n8n as Periodix LinkedIn), see Installation
- An AI provider API key: Claude by default, OpenAI or Gemini also work
- A Google Sheet with a Leads tab and these column headers: source, job_title, company_name, company_id, company_match, job_url, job_location, fit_score, work_mode, fit_reason, application_note, recipient_name, recipient_headline, recipient_id, recipient_match, connection_note, connection_sent
Workflow at a glance
Run Daily → Search Config → Search LinkedIn Jobs (Periodix Actions) + Fetch RemoteOK + Fetch We Work Remotely → Normalize each source → Merge → Deduplicate → Resolve LinkedIn company (Periodix Actions) → Score Fit with AI → Keep Strong Fits → Draft Application with AI → Find Recipient at Company (Periodix Actions) → Draft Connection Note → Send Connection Request (Periodix Actions) → Save Leads
Step by step
1. Run Daily (Schedule Trigger)
Runs once a day at 8:00. Good roles collect applicants fast, so a daily run keeps you early.
2. Search Config (Set node)
The top 3 results are compared to the job's company by normalized name, not just the first result. The outcome is written to company_match:
| company_match | Meaning |
|---|---|
| has_id | The job came from LinkedIn with a company ID |
| verified | A company page name matched |
| unverified_fallback | No name matched, the top result was used |
| not_found | No company results |
7. Score Fit with AI and Keep Strong Fits (HTTP Request + Code + Filter)
AI scores each job 1 to 10 against your profile and preferences, and classifies work_mode as REMOTE_OK, HYBRID_OK, HYBRID_TOO_FAR, or UNCLEAR. Only jobs with fit_score of 5 or higher that are not HYBRID_TOO_FAR move on.
8. Draft Application with AI (HTTP Request + Code)
Writes a short application note under 600 characters, specific to the role and your background. Saved as application_note.
9. Find Recipient at Company (Periodix Actions: Search + Code)
For every job with a company ID, a people search runs inside that company:
{{ "https://www.linkedin.com/search/results/people/?keywords=" + encodeURIComponent($('Search Config').first().json.recipient_titles) + "¤tCompany=%5B%22" + $json.company_id + "%22%5D" }}
From up to 10 results, the workflow picks the first person whose headline contains one of your recipient_titles. The outcome is written to recipient_match: verified, unverified_fallback, not_found, or skipped (no company resolved).
10. Draft Connection Note and Send Connection Request (HTTP Request + Periodix Actions: Connection)
AI writes a connection note under 300 characters that mentions the specific role. Then Periodix Actions sends it:
- Resource: Connection
- Operation: Send Request
- Recipient:
{{ $json.recipient_id }} - Note:
{{ $json.connection_note }}
11. Save Leads (Google Sheets)
Every strong-fit job is appended to the Leads tab, whether a request was sent or not, with connection_sent set to true or false.
Example output (Leads tab row)
{
"source": "remoteok",
"job_title": "Growth Marketing Manager",
"company_name": "Example Labs",
"company_id": "12345678",
"company_match": "verified",
"job_url": "https://remoteok.com/remote-jobs/example",
"job_location": "Remote",
"fit_score": 8,
"work_mode": "REMOTE_OK",
"fit_reason": "Matches wanted growth role, fully remote, B2B SaaS.",
"application_note": "Hi, I am applying for the Growth Marketing Manager role at Example Labs...",
"recipient_name": "Sam Lee",
"recipient_headline": "Talent Acquisition Lead at Example Labs",
"recipient_id": "ACoAAExample789",
"recipient_match": "verified",
"connection_note": "Hi Sam, I just applied for the Growth Marketing Manager role at Example Labs and would love to connect.",
"connection_sent": true
}Customization
- Who to reach: set
recipient_titlesto Recruiter for a warm intro, CEO or CTO to go straight to the top, or list several. - Confirmed matches only: filter the Sheet on
company_matchandrecipient_matchto skipunverified_fallbackrows, or add an If node before Send Connection Request that only allowsverified. - Review before sending: remove Send Connection Request and send manually from the Sheet.
- More job boards: copy the RemoteOK or We Work Remotely branch and normalize to the same fields.
Troubleshooting
- No LinkedIn jobs: check
linkedin_geo_id, widenfreshness_hours, or simplifyjob_keywords. - No RemoteOK or We Work Remotely jobs: your
keyword_listis too narrow for their titles and tags. - recipient_match is not_found for most jobs: list fewer titles in
recipient_titles. LinkedIn keyword search works best with one or two terms. - Outreach columns are empty in the Sheet: add the column headers listed in What you need. The Sheets node maps fields by header name.
- Scores of 0 with reason "parse error": the AI reply was not valid JSON. Check the model name and API key.
- The same job appears on different days: the workflow dedupes within one run only. Read the Leads tab first and filter by
job_url, or use Append or Update matched onjob_url.
Related
Updated 5 days ago