CV DeepMatch position config
Every CV DeepMatch submission carries a config object whose
requirements block tells the matching engine what a good candidate
looks like for this position. The endpoint reference
(CvDeepMatchRequirements)
lists every field and its type. This guide explains the conventions —
the things that aren't obvious from the schema alone and that, if you get
them wrong, produce a config that validates but scores badly.
If you only read one thing: every importance is an integer 1–5, and
each kind of requirement has exactly one correct home. The rest is
detail.
The 1–5 importance scale
importance appears throughout the config — on the work-experience
dimension, on each skill, on each industry, on education, and more. It is
always an integer from 1 to 5:
| Value | Meaning |
|---|---|
1 | Barely matters / nice-to-have |
3 | Moderately important |
5 | Critical to the role |
Internally the engine divides the value by 5 to get a 0–1 weight, so 5 → 1.0, 3 → 0.6, 1 → 0.2. That has consequences:
0is not "off". A0produces a zero weight — the dimension silently contributes nothing. To switch education off, useis_enabled: false(below), notimportance: 0.- Values above 5 overweight.
importance: 7yields a weight of1.4, which can push scores out of the expected range. - Fractions are not the contract.
4.5happens to arithmetic-work but is not accepted — send whole integers 1–5.
The submit endpoint rejects out-of-range or non-integer importance
values with INVALID_INPUT, so you'll catch most mistakes at submit time
rather than in a silently-wrong score. Still, choose deliberately: making
everything 5 is the same as making everything 1 — nothing is
prioritised relative to anything else.
Field routing — what goes where
Each requirement you extract from a job description has exactly one correct place. Putting it elsewhere doesn't error, but it asks the engine the wrong question.
| Requirement | Goes in | Never in |
|---|---|---|
| A language (e.g. "English B2") | skills.language_skills_config | hard_skills, soft_skills, qualifications |
| Years / months of experience | workExperience.from / .to | qualifications |
| Degree or field of study | education.academic | skills or qualifications |
| A tool / system / method visible on a CV | skills_config.hard_skills | qualifications |
| A behavioural / interpersonal trait | skills_config.soft_skills | qualifications |
| A related job title | workExperience.relevant_roles | skills |
| A relevant industry | workExperience.relevant_industries (+ industries_config) | skills |
| An essential broad competency not reducible to a skill | minimal_qualifications | hard/soft skills (if it is a skill) |
| A nice-to-have broad competency | preferable_qualifications | same |
| Employment conditions (contract, onsite/hybrid, shift, location, availability) | Not scored — keep it out of the config | anywhere scored |
Languages are never skills
This is the single most common routing mistake. A language requirement
goes only in skills.language_skills_config, and the language names
must be plain — no proficiency suffix:
| ✗ Wrong | ✓ Correct |
|---|---|
"English (B2+)" | "English" |
"English - C1" | "English" |
"Spanish (native)" | "Spanish" |
A proficiency suffix is matched literally against the CV and almost never
hits, so language scoring collapses to zero. The submit endpoint rejects
language strings containing (), [], or /. Capture the required level
in your own explanations block instead.
Two more language gotchas worth knowing:
- The preferred-languages field is spelled
prefered_languages— oner. It's a historical spelling the engine reads exactly; the natural-lookingpreferred_languagesis silently ignored. target_countriesare countries where the language is spoken (proof of real-world use), not the job's location. For English you'd list"United States","United Kingdom", etc. Leave it empty if the JD doesn't value it.
Minimal vs preferable qualifications
minimal_qualifications (essential) and preferable_qualifications
(advantageous) are for broad competencies that can't be reduced to a
single hard/soft skill label and that describe capability depth. They
must be realistically inferable from a CV.
Good: "Demonstrated experience managing high-volume customer interactions with measurable performance outcomes." — describes measurable capability depth.
Bad: "Ability to consistently deliver customer support over the phone
while identifying opportunities to recommend products." — that's a task
description; express it as soft skills (Customer-Centric Communication,
Sales Orientation) plus relevant_roles.
Keep out of qualifications:
- Employment conditions (contract length, onsite/hybrid, shift, schedule).
- Willingness / availability statements ("willing to travel", "open to relocation").
- Time-based requirements — those belong in
workExperience.from/.to. - Long JD task sentences rewritten as "Ability to…".
If a requirement can reasonably be a hard or soft skill, put it there
instead. Use qualifications sparingly — 0 is fine when skills cover the
role. Whether qualifications are scored at all is controlled by the
required skills_config.requirements toggle block (both
minimal_qualifications and preferable_qualifications booleans must be
present).
Education ON vs OFF
education is optional at submit — omit it and we auto-fill a safe,
disabled default. But if you send the block, send all of it, and
disable education by toggling, not by deleting:
- To disable education scoring: send the full
educationblock withis_enabled: false. The engine reads the block's structure either way; a partial or missing block when education is otherwise expected causes a failure downstream. - To enable it: set
is_enabled: trueand fill inacademic/non_academic.
Inside academic, study_status is case-sensitive and must be one of
Both, Undergraduate, Graduate. A value like "Graduated" is rejected
and, if it slipped through, would short-circuit academic scoring.
Convention for weighting: when a degree isn't genuinely critical to the
role (e.g. degree_level: "High School" with no specific field), keep
education.importance and academic.importance at 1–2. Reserve 4–5 for
roles where the degree truly matters.
Cardinality limits
The engine doesn't crash if you exceed these, but match scores degrade —
over-long lists force every candidate to match an impossibly long
specification, and scores collapse across the board. The submit endpoint
enforces the caps, so over-long lists return INVALID_INPUT:
| List | Max items | Why |
|---|---|---|
hard_skills | 5 | Forces prioritising technical/tool requirements |
soft_skills | 5 | Forces prioritising behavioural requirements |
hard_skills + soft_skills combined | 10 | Beyond this the reasoning gets noisy |
minimal_qualifications | 3 | Only the few real non-skill competencies |
preferable_qualifications | 3 | Only the most meaningful nice-to-haves |
relevant_industries | 3 (and ≥ 1) | More dilutes industry-correlation scoring |
industries_config | 3 | Must mirror relevant_industries one-for-one |
relevant_industries and industries_config must each contain 1–3
entries and mirror each other — industries_config carries the
per-industry weight, relevant_industries is the plain list the reasoning
step reads. An empty relevant_industries is rejected.
Minimal valid config
This is the smallest config the submit endpoint accepts — education and
language_skills_config are omitted and auto-filled:
{
"name": "Senior Backend Engineer",
"requirements": {
"workExperience": {
"from": 5,
"to": 10,
"importance": 5,
"time_importance": 3,
"transferable_skills": true,
"minimum_job_experience_duration": 4,
"threshold_for_one_exp_relevance": 84,
"relevant_roles": ["Backend Engineer"],
"relevant_companies": [],
"relevant_industries": ["SaaS", "Fintech"],
"industries_config": [
{ "name": "SaaS", "importance": 5 },
{ "name": "Fintech", "importance": 4 }
]
},
"skills": {
"importance": 5,
"skills_config": {
"hard_skills": [
{ "name": "Node.js", "importance": 5 },
{ "name": "TypeScript", "importance": 4 },
{ "name": "PostgreSQL", "importance": 4 }
],
"soft_skills": [
{ "name": "Communication", "importance": 4 }
],
"minimal_qualifications": [],
"preferable_qualifications": [],
"requirements": {
"minimal_qualifications": true,
"preferable_qualifications": true
}
}
}
}
}
Pre-flight checklist
Before submitting, verify:
name(orposition_name) — non-empty string.workExperience.from ≤ workExperience.to— integer years.workExperience.relevant_industries— 1–3 items, non-empty.workExperience.industries_config— same count, mirrors the above.skills.skills_config.requirements— present, both booleans.- Every
importance— integer 1–5 (no zeros, fractions, or out-of-range). - No language inside
hard_skills/soft_skills/ qualifications. - No proficiency suffix in language names.
- Cardinality caps respected (industries ≤ 3, hard ≤ 5, soft ≤ 5, hard+soft ≤ 10, qualifications ≤ 3 each).
- If you send
education, send the full block (useis_enabled: falseto disable, not omission).
See also
- CV DeepMatch integration — submit, poll, and webhook walkthrough.
CvDeepMatchRequirements— field-by-field schema reference.CvDeepMatchSkillItem— the shape of each skill / qualification entry.