AI Resume Job Matcher: Ranked Shortlist + Fit Scores
Pricing
$20.00 / 1,000 retained job fit results
AI Resume Job Matcher: Ranked Shortlist + Fit Scores
Search 10 public developer-job sources or score up to 200 supplied jobs for one candidate. Get a ranked shortlist with fit scores, hard-requirement checks, evidence, gaps, and posting links. Returned shortlist results cost $0.02 each; no model key is needed.
Pricing
$20.00 / 1,000 retained job fit results
Rating
0.0
(0)
Developer
Job Atlas
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
AI Job Search & Fit Scorer — 10 Sources + AI Matching
Example provenance: All observed run IDs, immutable build IDs and historical build examples in this README come from nomad-agent/ai-job-fit-scorer. They demonstrate the primary Actor; none is evidence of a Job Atlas run. Calls below use the Job Atlas Actor’s latest selector.
Start with one input and output
An Apify account is required. Use your Apify API token when calling the API; Console runs do not need that token pasted into the input. No AI-provider key is required: the Actor owner pays for scoring. Supply exactly one candidate profile or résumé; sourceApifyToken is optional for reading your own source dataset.
Free-tier event rates checked 2026-10-04: job-fit-result $0.02.
Cost: Total = Actor event charges + platform usage if separately billed + any BYO-provider charges. See “Current costs” for your event rates, plan tiers and a calculation. A sample does not promise future billable volume.
Input and output below were read from the same successful run ZMoMBfLEl0cPGIHcc (2026-10-04, immutable build 93Chil9Dg8n0C4QGd). This controlled example scored a fictional candidate against one supplied fictional job, using the owner’s AI provider. It did not search source sites. Apify added the unused search default to retained INPUT; mode: score-jobs selects only the supplied jobs. This is an observed example, not a guarantee that repeating it returns this row. It used the Nomad Agent source Actor build at capture time.
Input JSON
{"mode": "score-jobs","jobs": [{"schemaVersion": "nomad-agent-job-v1","identity": {"source": "example","externalId": "readme-fixture-20261004","url": "https://example.com/jobs/platform-engineer"},"data": {"title": "Platform Engineer","company": {"name": "Example Labs","sourceId": null,"department": null,"url": null,"logoUrl": null},"classification": {"industries": null,"jobFunctions": null},"domains": null,"domainsRaw": null,"locations": [{"raw": "Madrid, Spain","countryName": "Spain","countryCode": "ES","city": "Madrid","region": null,"postalCode": null,"streetAddress": null,"facilityName": null,"positionsAvailable": null,"latitude": null,"longitude": null}],"employment": {"workArrangements": ["hybrid"],"applicantLocationRequirements": null,"workSchedules": null,"contractTypes": ["full-time"],"durationMonths": null,"hoursPerWeek": null,"hoursPerWeekRaw": null,"startDate": null,"startDateRaw": null},"application": {"postedAt": null,"deadline": null,"referenceNumber": null,"referenceNumberIssuer": null,"applicantSnapshot": null,"url": null,"email": null,"directApply": null,"applyMethodRaw": null,"availability": null,"hiringContacts": null,"eligibilityCriteria": null,"selectionProcess": null},"seniority": {"raw": null,"levels": ["mid"]},"requirements": {"education": null,"experience": null,"languages": null,"requiredSkills": [{"name": "Python","yearsRequired": null},{"name": "PostgreSQL","yearsRequired": null}],"preferredSkills": null,"certifications": null,"skillsQualifications": null,"specificRequirements": null},"benefits": null,"funding": {"programme": null},"compensation": {"currency": null,"exact": null,"minimum": null,"maximum": null,"period": null,"raw": null},"constraints": {"visaSponsorship": null,"workAuthorization": null,"securityClearance": null,"locationPreference": null}},"custom": null,"llm": {"status": "not_requested","requestedFields": [],"filledFields": [],"provider": null,"model": null,"promptVersion": null,"completedAt": null},"raw": {"description": "Build reliable Python services and PostgreSQL data pipelines. Five years of backend experience preferred. Hybrid in Madrid, Spain.","descriptionHtml": null}}],"candidateProfile": {"primaryRole": "Platform Engineer","targetTerms": ["Platform Engineer","Backend Engineer"],"skills": ["Python","PostgreSQL","Docker"],"seniorityLevels": ["mid"],"yearsExperience": 5,"workableLanguages": [{"language": "English","level": "C1","evidence": "CV: English C1"}],"workableLanguagesComplete": false,"acceptedWorkArrangements": ["hybrid"],"remoteLocations": [],"hybridLocations": ["Madrid, Spain"],"onsiteLocations": [],"workArrangementPreferencesComplete": true,"acceptedCountryCodes": ["ES"],"acceptedContractTypes": ["permanent"],"acceptedContractTypesComplete": true,"freeText": "Fictional example candidate: individual-contributor product engineering roles."},"maxItems": 1,"resultMode": "audit","minDeliveryScore": 2,"minRankToForward": 30,"recoverHolds": true,"aiConcurrency": 1,"maxAiItems": 1,"search": {"sources": ["linkedin","remote_boards","builtin","justjoinit","nofluffjobs","hackernews","ycombinator_was","wttj","infojobs","tecnoempleo"],"keywords": ["software engineer"],"location": "Madrid","remoteOnly": false,"titleExclude": ["intern","junior"],"postedWithinDays": 7,"maxItemsPerSource": 10,"cacheTtlSeconds": 1800,"concurrency": 3,"sourceTimeoutSecs": 120}}
Matching output excerpt
Selected fields from the captured output row are shown below. Long strings and arrays are shortened for display; this is not the complete output contract.
{"schemaVersion": "nomad-ai-job-fit-v1","jobKey": "example:readme-fixture-20261004","title": "Platform Engineer","company": "Example Labs","location": "Madrid, Spain","fitScore": 90,"deliveryScore": 5,"recommendation": "exceptional","evaluationStatus": "scored","blockingGates": [],"why": "Excellent match for a mid-level Platform Engineer role: Python, PostgreSQL, five years of backend experience, and hybrid work in Madrid align closely with the posting and preferences.","gapSummary": "Permanent employment and work authorization are not explicitly confirmed; the posting only states full-time and provides no eligibility details.","url": "https://example.com/jobs/platform-engineer"}
Give it one résumé or a short candidate profile. It searches available postings from up to 10 public developer-job sources, removes duplicates, uses their complete original descriptions, and returns a ranked shortlist with two scores per job: a raw 0–100 fit and a 0–5 delivery score that drops whenever a hard requirement is contradicted. Already have a job list? Skip the search and score your own jobs instead.
No model key is required. Each returned match costs $0.02. In default shortlist mode, jobs that miss the threshold, hard drops, holds, AI failures, and clean empty searches have no result charge. Audit mode charges retained non-failure rows.
Independent, unofficial integration. Not affiliated with or endorsed by LinkedIn or any source-site operator. Review source terms, privacy rules, and applicable law for your use case.
What a result looks like
One real row from a run on 2026-09-05 that scored the built-in example candidate, a generalist senior software engineer:
{"schemaVersion": "nomad-ai-job-fit-v1","jobKey": "linkedin:4436371317","title": "Senior Software Engineer, Java","company": "CLEAR","location": "New York, NY","postedAt": "2026-09-05","fitScore": 78,"deliveryScore": 4,"recommendation": "strong","evaluationStatus": "scored","blockingGates": [],"why": "Strong match for a senior full-stack software engineering role: eight years of backend/full-stack experience, React, TypeScript, AWS, Docker, Kubernetes, APIs, and CI/CD align well with the posting.","gapSummary": "The posting highlights Java, which is not listed in the candidate’s skills. Work arrangement, New York logistics, and work authorization are not specified.","url": "https://www.linkedin.com/jobs/view/senior-software-engineer-java-at-clear-4436371317"}
How to read it:
- fitScore (0–100) says how well the posting matches the candidate's skills and target roles.
- deliveryScore (0–5) is the number to act on. Hard gates such as work mode, location, language, work authorization, seniority, or role family lower it, so a great skills match with an impossible location never reaches the top.
- blockingGates lists any hard gate that failed. Empty means none did.
- why and gapSummary are the model's short evidence for and against the match.
The full row also carries the normalized job, every gate verdict, the deterministic pre-screen decision, the model and provider that produced the verdict, source provenance, and stable hashes. The complete example is public: fit-row.example.json.
Run it in one minute
Apify Console. Press Start. The form is prefilled with a bounded search:
all ten sources, software-engineer roles posted in the last seven days around
Madrid with intern and junior titles excluded, at most three jobs, the example
candidate, and a result-charge cap of $0.06. The log, the run status
message, and candidate.usedExampleProfile in the run summary all say the
results describe that example candidate, not you. Then replace the profile
with your own facts, or clear it and upload a résumé. Exactly one candidate
source may be set; a run that keeps the profile and adds a résumé is rejected
before any paid work starts.
API. This call selects latest, searches one source, and returns at most one
match for $0.02:
curl --request POST \--header "Authorization: Bearer $APIFY_TOKEN" \--header "Content-Type: application/json" \--data '{"mode": "search","search": {"sources": ["linkedin"],"keywords": ["platform engineer"],"location": "Madrid","postedWithinDays": 7,"maxItemsPerSource": 1},"candidateProfile": {"primaryRole": "Platform Engineer","targetTerms": ["Platform Engineer", "Backend Engineer"],"skills": ["Python", "PostgreSQL", "Docker"],"seniorityLevels": ["mid"],"remoteLocations": ["Spain", "European Union"],"hybridLocations": ["Madrid, Spain"],"onsiteLocations": [],"workArrangementPreferencesComplete": true},"maxItems": 1,"resultMode": "shortlist","minDeliveryScore": 2,"aiConcurrency": 1}' \"https://api.apify.com/v2/actors/jobatlas~ai-job-fit-scorer/runs?build=latest&waitForFinish=120&maxItems=1&maxTotalChargeUsd=0.02"
Build 0.1.22 produced the real example above. New calls use latest; record the numeric build number and immutable build ID returned by Apify. Keep the returned run ID, wait for that
run to reach SUCCEEDED with exit code 0, then read its default dataset and
its RUN-SUMMARY record. Storage counts can settle a moment after the run
finishes, so re-read the same run when they have not reconciled yet. A
ten-source version of this input is public:
search-input.json.
Two ways to use it
Search + score (default)
Set mode to search, give at least one search term, and pick sources. The
Actor never invents a query from a résumé, so search.keywords is required.
Only the search object narrows what is fetched: put the city or country in
search.location, or use ISO country codes in search.countryCodes when no
location is set, and remote-only work in search.remoteOnly. A location
written in preferences or the candidate profile affects scoring only.
Score jobs you already have
Selecting sourceDatasetId grants this run read-only access to that dataset. For sourceActorRunId outside the Actor's limited access, supply sourceApifyToken with read access to the run and its dataset. The token is an encrypted input; it is never included in results or run summaries. Using the dataset ID avoids needing a separate token.
Set mode to score-jobs, provide one candidate source, and exactly one job
source:
jobs: inlinenomad-agent-job-v1records (up to 200);sourceDatasetId: an existing Apify dataset, read only;sourceActorRunId: one exact successful upstream Actor run. AddexpectedSourceBuildwhen the upstream build must match.
{"mode": "score-jobs","sourceDatasetId": "YOUR_DATASET_ID","candidateProfile": {"primaryRole": "Data Engineer","targetTerms": ["Data Engineer", "Analytics Engineer"],"skills": ["Python", "SQL", "dbt"],"remoteLocations": ["European Union"],"hybridLocations": [],"onsiteLocations": [],"workArrangementPreferencesComplete": true},"maxItems": 25,"resultMode": "shortlist","minDeliveryScore": 2}
A complete inline job record is public: inline-input.json.
Candidate input: choose exactly one
candidateProfile: structured facts and preferences. Fill only what the candidate actually stated and leave unknowns empty; the scorer treats an empty field as unknown, never as a contradiction.resume: a text-based PDF or TXT uploaded in the Apify Console.resumeText: plain text for API clients.
For a conditional profile, set candidateProfile.schemaVersion to 8 and
include both matchingPolicy (profile-matching-policy-v1) and tenureBounds
(profile-tenure-bounds-v1). Each alternative is one complete acceptable
combination; every rule within it must hold. A missing job fact leaves a hard
condition unresolved and holds the job from AI scoring. Omit these fields for
the existing flat candidate profile format. Year-only experience dates should
remain a range in tenureBounds, not an invented exact year count.
preferences can add explicit role, location, work-mode, language, or contract
constraints for scoring. It does not change which jobs are fetched.
Sources
| Key | Source |
|---|---|
linkedin | LinkedIn public job pages |
remote_boards | Remote job boards |
builtin | Built In |
justjoinit | Just Join IT |
nofluffjobs | No Fluff Jobs |
hackernews | Hacker News “Who is Hiring?” |
ycombinator_was | Y Combinator Work at a Startup |
wttj | Welcome to the Jungle |
infojobs | InfoJobs |
tecnoempleo | Tecnoempleo |
The default selects all ten listed sources. Results are merged fairly across sources and deduplicated before scoring, and every job needs its full description before it can be scored.
Search matches available job postings. Each keyword query matches the title or description
when every word in that query matches; any query may match. Location and
country filters use locations. These filters apply before the job data
limit. titleExclude is checked afterward on the bounded fetched records.
A strict remoteOnly search keeps only postings explicitly marked fully remote,
excluding hybrid and unknown arrangements. Experience preferences affect
scoring. RUN-SUMMARY records fetched jobs, applied filters and unavailable
sources for each selected source.
How scoring works
- A deterministic pre-screen reads each posting and sorts it into a hard
contradiction (dropped), uncertain evidence (held), or a plausible match
(forwarded to AI).
minRankToForwardsets the forwarding floor andrecoverHoldscan send holds to AI as well. - Each forwarded job gets one AI verdict: the raw
fitScore, a short rationale, gaps, and a pass/fail with evidence for every hard gate. - Any failed hard gate clamps the
deliveryScore. - Rows are ordered by delivery score first, then raw fit.
If the model call fails, the row is reported as ai_failed. It is never
silently turned into a zero.
Shortlist or audit
resultMode decides what reaches the dataset and what is charged:
shortlist(default) returns only rows withevaluationStatus: "scored"anddeliveryScore >= minDeliveryScore. The default threshold is2and equality counts. Everything else is neither returned nor charged.auditkeeps the complete evaluation trail: scored rows, static drops, holds, forward-cap holds, andai_failedrows. Every retained row exceptai_failedis charged.minDeliveryScoreis recorded but does not filter.
Output
Dataset rows follow nomad-ai-job-fit-v1
(schema).
Three keys matter for automation:
matchKeyidentifies one candidate plus one job. Use it as the upsert key.evaluationKeychanges with the exact candidate snapshot, job content, scoring contract, or evaluation time. Keep it as the receipt.jobKeyidentifies the posting only. Keying a destination on it alone lets one candidate's result overwrite another's.
RUN-SUMMARY in the default key-value store follows
nomad-ai-job-fit-run-summary-v4
(schema,
real example).
It records per-source outcomes, the result policy, warnings, candidate hashes
(never résumé text), provider and model usage, billing receipts, and the
terminal reason. Its counts block always includes staticDropped,
staticHeld, aiScored, aiFailed, resultFilteredOut, and outputRows,
so an empty shortlist is distinguishable from a run that did no work.
Reconcile the summary with the run and its dataset before writing results
anywhere.
Limits
| Limit | Value |
|---|---|
| Unique jobs evaluated per run | 200 |
| AI verdict concurrency | 1–8 |
| Source concurrency | 1–10 |
| Résumé upload | 5 MB, 50 pages, 8,000 readable characters |
| Job description text and HTML | No length limit; never truncated or rejected for size |
| Default run timeout | 15 minutes |
Pricing
| Result mode | job-fit-result is charged when | Price |
|---|---|---|
shortlist (default) | A scored row meets minDeliveryScore and is returned | $0.02 per returned match ($20 per 1,000) |
audit | A complete evaluation row is retained; ai_failed is never charged | $0.02 per retained non-failure row ($20 per 1,000) |
One charged row is $0.02, 25 are $0.50, 100 are $2.00. There is no search, résumé, run-start, or model-key fee, and no paid child Actor runs: search reads available postings with verified complete descriptions, and never scrapes job websites during your run. Results depend on available coverage for each source (LinkedIn currently holds US software-engineering postings), so a search can return jobs from fewer sources than it names.
The model calls are paid by the Actor owner. That route is capped at $0.20/M
prompt tokens and $1.20/M completion tokens, with at most two provider attempts
per AI call and a fixed $0.25 circuit breaker per run. When the breaker trips,
later AI-dependent evaluations become unbilled ai_failed rows in audit
mode. Shortlist mode filters those failed rows out.
maxTotalChargeUsd on the run limits how many jobs can be evaluated before
their scores are known. A low cap can therefore stop evaluation early even
when some later jobs would have been filtered out and left uncharged.
Integrations and agents
The credential-free starters below select latest. The accompanying
skill, guide, schemas, and examples describe that contract:
- Integration guide with the exact-run consumption contract
- Agent skill for Codex and Claude Code, with validators for rows and run summaries
- Hosted Apify MCP descriptor
- REST run-and-fetch client
- n8n → Google Sheets workflow
- Make → Google Sheets blueprint
- Zapier editor specification
- Example inputs and real outputs
Maintained paths are API, MCP, n8n, Make, Zapier, Python, and the Agent Skill. No Airtable asset is claimed. An Actor run proves neither hosted client exposure nor a named-destination write; verify those layers separately.
The starters are inactive and contain no credentials. Local artifact validation checks the starter configuration. A successful Actor run proves the Actor path; it does not prove your n8n, Make, Zapier, or Google Sheets destination. Test a disposable destination before enabling a schedule.
Caveats
- Public sites change, rate-limit, block, or omit fields. One source can be partial while the others still return usable rows.
- A source teaser is not accepted as a full job description. Supplied and
searched descriptions are never truncated or rejected for length, and returned
job records carry the complete text and HTML. A posting whose AI prompt exceeds
the owner-cost safety limit is returned as
ai_failedand is not charged. - A source that returns zero rows after a verified request is a clean empty result. Unverified empties, all-source failure, or only invalid records fail the run rather than pretending the search was clean.
- Search responses are cached for
cacheTtlSeconds. Set it to0when a check must hit the source fresh. - Duplicate source identities with conflicting supplied content fail closed.
- The Actor evaluates one candidate per run and does not learn from clicks or previous runs.
- Scores are decision support, not facts about a person, and never a substitute for reading the posting.
Privacy and responsible use
- Only public job pages are in scope. The Actor does not use cookies, borrowed accounts, login or paywall bypasses, or CAPTCHA evasion.
- Résumés are processed in memory. They are not written as a separate dataset or copied into every fit prompt. The original Actor input or upload remains subject to Apify retention controls.
- Extracted candidate evidence and fit prompts go through the configured OpenRouter/OpenAI route with provider data collection denied. No zero-data-retention claim is made.
- File URLs are restricted to Apify upload hosts; arbitrary URL fetching is rejected.
- Dataset and upstream-run inputs are read only. The Actor never applies to a job, changes source data, or makes an automated hiring decision.
Verify the source posting and keep a human responsible for application and hiring decisions.
Fast setup and source code
Public repository · Agent setup skill.
Use the Actor’s current input form for filters, or start with its documented API example. Select latest for ai-job-fit-scorer and record the immutable build ID and number returned by your run. Inspect the dataset and any run summary the Actor documents together; a successful status alone does not establish complete source coverage.
Restrictive filters or repeat-delivery suppression can produce zero results. Diagnostics and demo records are not source records. Optional AI or translation stays explicit where supported.
Observed output example
Selected fields from a real source record inspected on 2026-10-03; consult the output schema for the full contract. Values change with the source.
{"schemaVersion": "nomad-ai-job-fit-v1","matchKey": "85fa5ac9acc99d4a8984212277adac384a841d92d96edf026a596bee17ceb615","evaluationKey": "24e88ceb74ce5aed864c51a76b9dd8337ef9140f8ee2bf257aaace3410f0b04b","jobKey": "wttj:f7509d9d-4946-411d-8dde-3903d7f74f82","candidateHash": "10435c5062dfa2ca106667416d98c01b9c9c9870a5363bb431eaf64744c41e81","candidateSnapshotHash": "aaa8f9a66057aca500a9e5d45b2d9cc73ec05a03518059812fd5f9f247c4df3b","evaluatedAt": "2026-10-03T08:06:54Z","source": "wttj","externalId": "f7509d9d-4946-411d-8dde-3903d7f74f82","url": "https://www.welcometothejungle.com/en/companies/galadrim/jobs/software-engineer-freelance-madrid_madrid","title": "Software Engineer - Freelance - Madrid","company": "Galadrim","location": "Madrid, Spain","postedAt": "2026-09-27","fitScore": 72,"deliveryScore": 4,"recommendation": "strong","evaluationStatus": "scored","why": "Strong Software Engineer match with eight years of backend/full-stack experience and React, TypeScript, Python, AWS, Docker, Kubernetes, and SQL. Spanish fluency and Madrid work logistics are unverified.","gapSummary": "The posting requires native Spanish and fluent English; the candidate only documents English at B2. Work arrangement, authorization, and freelance compatibility are not specified.","blockingGates": [],"scoreAdjustedForGates": false}
Product guides and related tools
- Product overview and public links
- Public setup guide
- Job Atlas job-data tools
- Oink personal job alerts
Current costs
Current Actor event rates, checked 2026-10-04. USD; use the Pricing tab for your plan and later changes.
| Event | Free | Bronze | Silver | Gold | Platinum | Diamond |
|---|---|---|---|---|---|---|
Retained job fit result (job-fit-result) | $0.02 | $0.02 | $0.02 | $0.02 | $0.02 | $0.02 |
For example, 100 × job-fit-result totals $2 in Actor event charges on Free. This is an arithmetic example, before any waiver; actual charged events depend on the run and selected options. It is not a promise of output or a charge for simply setting an item cap.
Your total is the charged Actor events, plus platform usage only if this Actor’s Pricing tab bills it separately, plus any external provider you use with your own key. Do not add platform usage twice when it is included. Apify credits and plan discounts affect your invoice. Set a run cost limit in Console before starting.
Job Atlas
Explore the Job Atlas job-data and matching Actors. Use latest and retain the immutable build ID returned by each run.
Product guide | Source and client examples | Setup skill | Setup guide