Skip to content

Products

HireLayer Job Criteria Extractor

HireLayer job description parsing API: send a job ad as text or a file and get its typed, weighted criteria back as JSON, for free.

The HireLayer Job Criteria Extractor reads a job description and returns its criteria in one POST /api/v4/jobs/extract-criteria call: usually 4 to 10, each with a type, a requirement, a weight and, when the ad sets one, a threshold such as 3 years minimum or B2. Send the job as text or as a PDF, DOCX, TXT or HTML file. It is free, except when a new text is sent under the job_id of a job already scored: its stored scores are evaluated again on the new criteria, 1 credit each. The job is stored under a job_id, and the Resume Scorer, Talent Pool Search and Job Recommendations reuse its criteria.

FieldValues
typeskill, experience, education, language, certification, location, soft_skill, other
requirementrequired, preferred, bonus. required: a resume that clearly lacks it loses 25 % of its score, never eliminated outright. preferred and bonus count only through their weight.
weightImportance. 3 essential, 2 important, 1 nice to have, 0 off: kept on the job, left out of every score, of the required-criterion penalty, of required_missing and of to_verify. Texts already written (summary, explanation) stay as they are.
thresholdThe minimum level the ad asks for, or null.

Criteria are written in the job’s language, French or English, unless language says otherwise. Correct one with PATCH /jobs/{job_id}/criteria/{criterion_id}: a weight, requirement or type change re-ranks the stored scores for free. A job text identical to the stored job returns the job as stored: title, location and language sent with it are ignored; change them with PUT /jobs/{job_id}.

Endpoint
POST /api/v4/jobs/extract-criteria
Input
JSON text (50,000 characters) or a job file
Output
The criteria and the job_id
Price
Free; 1 credit per stored score evaluated again when a new text replaces a stored job
POST/api/v4/jobs/extract-criteria

Reads a job description and returns its typed criteria (usually 4 to 10, at most 12), the job stored under a job_id.

  • The same text sent again under the same id (or without an id) returns the stored job and its current criteria (200), without a new extraction; the call's title, location and language are then ignored: change them with PUT /jobs/{job_id}. A different text under an existing job_id replaces it and extracts the criteria again, as PUT /jobs/{job_id} with recompute_criteria: true would; its title, location and status stay as stored unless the call sends them. To extract again from the same text, use that PUT.
Authentication
X-API-Key header
Billing
Free; 1 credit per stored score evaluated again when a new text replaces a stored job
Client timeout
Client timeout ≥ 150 s

Headers

  • HireLayer-Workspacestring

    Your customer's workspace id. Case-insensitive, created on first use. Absent, calls use default.

Request body

Content type application/json, or multipart/form-data with files

  • textstringrequired

    The full job description, as published.

    1–50,000 characters

  • titlestring | null

    ≤ 300 characters

  • locationstring | null

    Where the job is based. Read by the extraction.

    ≤ 300 characters

  • languagestring
    "fr""en"
  • job_idstring

    Letters, digits and . _ : ~ -, up to 200 characters.

  • do_not_store_databoolean

    Enterprise plan only, else 403 enterprise_plan_required: process without storing anything. See Storage.

    default false

Response

200A job was already stored under this id. The same text returns its current criteria; another text replaces it and its criteria are extracted again.

  • request_idstring

    The call's id, also in the HireLayer-Request-Id header. Quote it when contacting support.

  • job_idstring | null

    null without storage.

  • storedboolean
  • titlestring | null
  • locationstring | null
  • languagestring
    "fr""en"
  • criteriaobject[]

    Usually 4 to 10, at most 12, numbered crit_1, crit_2… in order.

    1–12 items

    ›Show 7 child fields
    • criterion_idstring

      Stable id in the job, such as crit_2. Never reused.

    • labelstring
    • typestring
      "skill""experience""education""language""certification""location""soft_skill""other"
    • requirementstring

      required: a resume that clearly lacks it loses 25 % of its score, never eliminated outright. preferred and bonus count only through their weight.

      "required""preferred""bonus"
    • weightinteger

      Importance. 3 essential, 2 important, 1 nice to have, 0 off: kept on the job, left out of every score, of the required-criterion penalty, of required_missing and of to_verify. Texts already written (summary, explanation) stay as they are.

      0–3

    • thresholdstring | null
    • sourcestring

      extracted by HireLayer, or custom: sent or edited by you.

      "extracted""custom"
  • credits_usedinteger

    Credits this call cost.

    ≥ 0

201Job created and criteria extracted.

  • request_idstring

    The call's id, also in the HireLayer-Request-Id header. Quote it when contacting support.

  • job_idstring | null

    null without storage.

  • storedboolean
  • titlestring | null
  • locationstring | null
  • languagestring
    "fr""en"
  • criteriaobject[]

    Usually 4 to 10, at most 12, numbered crit_1, crit_2… in order.

    1–12 items

    ›Show 7 child fields
    • criterion_idstring

      Stable id in the job, such as crit_2. Never reused.

    • labelstring
    • typestring
      "skill""experience""education""language""certification""location""soft_skill""other"
    • requirementstring

      required: a resume that clearly lacks it loses 25 % of its score, never eliminated outright. preferred and bonus count only through their weight.

      "required""preferred""bonus"
    • weightinteger

      Importance. 3 essential, 2 important, 1 nice to have, 0 off: kept on the job, left out of every score, of the required-criterion penalty, of required_missing and of to_verify. Texts already written (summary, explanation) stay as they are.

      0–3

    • thresholdstring | null
    • sourcestring

      extracted by HireLayer, or custom: sent or edited by you.

      "extracted""custom"
  • credits_usedinteger

    Credits this call cost.

    ≥ 0

Errors

  • 400
    invalid_requesttext or file is required.

    param: text. Neither text nor a file.

    Fix, then retry

  • 400
    invalid_requesttitle must be a string.

    param: title. text, title, location, language or job_id is not a string.

    Fix, then retry

  • 400
    invalid_requestlanguage must be fr or en.

    param: language. language is not fr or en.

    Fix, then retry

  • 400
    invalid_requesttitle must be 300 characters or less.

    param: title. title or location over 300 characters.

    Fix, then retry

  • 400
    invalid_requestjob_id cannot be search: that name is reserved for POST /api/v4/jobs/search.

    param: job_id. job_id is not a valid id, or is a name the paths reserve (extract-criteria, search).

    Fix, then retry

  • 400
    invalid_requestUnknown field lang.

    param: lang. A field the call does not take.

    Fix, then retry

  • 400
    invalid_requestThe request body is not valid JSON.

    The body is not valid JSON, not an object, or not sent as application/json.

    Fix, then retry

  • 400
    invalid_requestHireLayer-Workspace must contain letters, digits and . _ : ~ -, up to 200 characters.

    param: HireLayer-Workspace. HireLayer-Workspace is not a valid id.

    Fix, then retry

  • 401
    missing_api_keyThe X-API-Key header is missing.

    No X-API-Key header.

    Fix, then retry

  • 401
    missing_api_keyAuthorization: Bearer is not accepted: send the key in the X-API-Key header.

    The key sent as Authorization: Bearer: it goes in X-API-Key.

    Fix, then retry

  • 401
    missing_api_keyThe key goes in the X-API-Key header, not in the URL.

    The key sent in the URL: it goes in X-API-Key.

    Fix, then retry

  • 401
    invalid_api_keyInvalid API key: it is unknown, malformed or revoked.

    The key is unknown, malformed or revoked.

    Fix, then retry

  • 403
    insufficient_creditsThis call evaluates 12 scores, 1 credit each: 12 credits, and 3 are left. Nothing was processed or billed.

    A new text replaces a stored job already scored, and the credits left do not cover its scores evaluated again.

    Fix, then retry

  • 403
    enterprise_plan_requireddo_not_store_data is available on the Enterprise plan only. Nothing was processed or billed.

    param: do_not_store_data. do_not_store_data: true below the Enterprise plan.

    Do not retry

  • 413
    payload_too_largetext must be 50,000 characters or less.

    param: text. The text is over 50,000 characters.

    Fix, then retry

  • 413
    payload_too_largefile must be 4.5 MB or less.

    param: file. The file is over 4.5 MB.

    Fix, then retry

  • 413
    payload_too_largeThe text of file must be 50,000 characters or less.

    param: file. The text read in the file is over 50,000 characters.

    Fix, then retry

  • 422
    job_unreadablefile has no text layer: it is probably a scan. Send its text instead.

    param: file. The file cannot be read: a scan, a protected or damaged PDF, a PDF of more than 50 pages, an old .doc, or another type.

    Do not retry

  • 500
    internal_errorInternal error: retry later. If it persists, contact support with the request_id.

    An unexpected error.

    Retry with backoff

  • 502
    model_unavailableThe analysis did not complete after several attempts. Nothing was stored or billed: retry with backoff.

    The analysis did not complete.

    Retry with backoff

  • 502
    internal_errorThe service could not be reached: retry later.

    The service could not be reached.

    Retry with backoff

  • 503
    internal_errorThe credit service is briefly unavailable: retry in a second.

    The credit service is briefly unavailable. Header Retry-After: <seconds>.

    Retry with backoff

  • 504
    internal_errorThe service did not answer in time. The change may still be applied: read it before sending it again.

    No answer in time.

    Retry with backoff

Behavior

Credits
0. Except when a different text replaces a stored job that has scores and the extraction brings new criteria: as with PUT /jobs/{job_id}, its stored scores are evaluated again in the background, 1 credit each, and the call is refused (403) when the credits left do not cover them. credits_used counts this call's extraction only.
Without storage
job_id is null. Keep the criteria and send them back with the job to POST /resumes/score, so that scores stay comparable from one call to the next.
curl -X POST https://hirelayer.co/api/v4/jobs/extract-criteria \
  -H "X-API-Key: $HIRELAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Ingénieur IA / Développeur backend Node.js (H/F)",
    "text": "Ingénieur IA / Développeur backend Node.js (H/F)\nLumio · Paris 9e · CDI · Hybride (2 jours de télétravail par semaine)\n- 3 ans minimum d'\''expérience en développement backend Node.js / TypeScript\n- Expérience indispensable de l'\''intégration de LLM en production\n- Vous maîtrisez AWS (Lambda, S3, DynamoDB) ; une certification AWS est un plus\n- Anglais courant (B2 minimum) obligatoire"
  }'
{
  "request_id": "0c4a7b1e-5d2f-4e8a-b3c6-9f1d2e7a4b58",
  "job_id": "job_30cfa454c97663f3e1801e5a61b87d74",
  "stored": true,
  "title": "Ingénieur IA / Développeur backend Node.js (H/F)",
  "location": null,
  "language": "fr",
  "criteria": [
    {
      "criterion_id": "crit_1",
      "label": "Développement backend Node.js / TypeScript",
      "type": "skill",
      "requirement": "preferred",
      "weight": 3,
      "threshold": "3 ans minimum",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_2",
      "label": "Intégration de LLM en production",
      "type": "skill",
      "requirement": "required",
      "weight": 3,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_3",
      "label": "AWS (Lambda, S3, DynamoDB)",
      "type": "skill",
      "requirement": "preferred",
      "weight": 2,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_4",
      "label": "Diplôme d'ingénieur ou Bac+5 en informatique",
      "type": "education",
      "requirement": "preferred",
      "weight": 2,
      "threshold": "Bac+5",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_5",
      "label": "Anglais",
      "type": "language",
      "requirement": "required",
      "weight": 2,
      "threshold": "B2 minimum",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_6",
      "label": "Encadrement technique",
      "type": "experience",
      "requirement": "bonus",
      "weight": 1,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_7",
      "label": "Certification AWS",
      "type": "certification",
      "requirement": "bonus",
      "weight": 1,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_8",
      "label": "Astreinte",
      "type": "other",
      "requirement": "required",
      "weight": 1,
      "threshold": "1 semaine sur 6",
      "source": "extracted"
    }
  ],
  "credits_used": 0
}

From a file. Send the job description as a PDF, DOCX, TXT or HTML file in the multipart field file.

curl -X POST https://hirelayer.co/api/v4/jobs/extract-criteria \
  -H "X-API-Key: $HIRELAYER_API_KEY" \
  -F "file=@job.pdf;type=application/pdf"
{
  "request_id": "0c4a7b1e-5d2f-4e8a-b3c6-9f1d2e7a4b58",
  "job_id": "job_30cfa454c97663f3e1801e5a61b87d74",
  "stored": true,
  "title": "Ingénieur IA / Développeur backend Node.js (H/F)",
  "location": null,
  "language": "fr",
  "criteria": [
    {
      "criterion_id": "crit_1",
      "label": "Développement backend Node.js / TypeScript",
      "type": "skill",
      "requirement": "preferred",
      "weight": 3,
      "threshold": "3 ans minimum",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_2",
      "label": "Intégration de LLM en production",
      "type": "skill",
      "requirement": "required",
      "weight": 3,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_3",
      "label": "AWS (Lambda, S3, DynamoDB)",
      "type": "skill",
      "requirement": "preferred",
      "weight": 2,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_4",
      "label": "Diplôme d'ingénieur ou Bac+5 en informatique",
      "type": "education",
      "requirement": "preferred",
      "weight": 2,
      "threshold": "Bac+5",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_5",
      "label": "Anglais",
      "type": "language",
      "requirement": "required",
      "weight": 2,
      "threshold": "B2 minimum",
      "source": "extracted"
    },
    {
      "criterion_id": "crit_6",
      "label": "Encadrement technique",
      "type": "experience",
      "requirement": "bonus",
      "weight": 1,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_7",
      "label": "Certification AWS",
      "type": "certification",
      "requirement": "bonus",
      "weight": 1,
      "threshold": null,
      "source": "extracted"
    },
    {
      "criterion_id": "crit_8",
      "label": "Astreinte",
      "type": "other",
      "requirement": "required",
      "weight": 1,
      "threshold": "1 semaine sur 6",
      "source": "extracted"
    }
  ],
  "credits_used": 0
}