Skip to content

For sourcing and talent search products

One skill vocabulary for every profile your users source

Profiles reach your product from job boards, referrals, CV databases and uploads, each worded differently. HireLayer parses attached CVs, resolves skills and recruiter queries to one taxonomy, and ranks the longlist a recruiter is about to read.

A sourcing search screen. The recruiter's query 'react dev, k8s, postgres' is resolved to the taxonomy skills React, Kubernetes and PostgreSQL. Below, a longlist of three candidates from different sources is ranked with scores and short rationales.

The problem

Why sourced profiles are hard to search

Your product is good at finding people. The trouble starts when a recruiter tries to compare what was found.

  1. 01

    Every source words skills differently

    “K8s”, “Kubernetes admin” and “container orchestration” overlap. Keyword search treats them as unrelated.

  2. 02

    Recruiter queries are free text too

    A query typed between two calls rarely matches the labels stored on profiles.

  3. 03

    Attached CVs stay unread

    The most detailed information sits in PDFs that nobody opens until a candidate is already shortlisted.

  4. 04

    Longlists have no reading order

    A search returns dozens of plausible profiles; the recruiter needs to know where to start.

Query normalization

What a recruiter types, and what your search runs

The query goes through /skills/resolve as one text and comes back as taxonomy skills in the order typed, each with the words it came from. Parts that match no skill are listed in unresolved, never guessed. Values below come from real responses.

Recruiter types

Your backend sends

POST /api/v1/skills/resolve
{ "text": "react js", "language": "en" }

skills[], in the order typed

  1. 1React

    react

    software · from “react js”

    Frontend development

unresolved: []

Your search filters on

react

No scores to tune: each part of the query is resolved or listed in unresolved, never guessed.

How it fits

Enrichment after discovery

Discovery, provenance and outreach stay in your product. HireLayer works on profiles you have already captured, and does not source candidates itself.

  1. Your system

    Step 1, your system: A profile is captured

    From any channel your product supports, with or without an attached CV.

  2. HireLayer

    Step 2, HireLayer API: Parse the CV, if there is one

    Adds work history, education, languages and typed skills to the record.

    POST /api/v3/parser

    • work_experiences[]
    • skills[]
  3. HireLayer

    Step 3, HireLayer API: Normalize profile skills in one call

    All of a profile’s skill strings as one text, up to 5,000 characters. Keep the original label for display and the skill id for search.

    POST /api/v1/skills/resolve

    • skills[].id
    • mention
  4. HireLayer

    Step 4, HireLayer API: Normalize the recruiter’s query

    Resolve what the recruiter typed to taxonomy skills before your search engine runs.

    POST /api/v1/skills/resolve

  5. HireLayer

    Step 5, HireLayer API: Rank the longlist

    Send the role description and the 10 profiles the recruiter will read first.

    POST /api/v1/matching/job-candidates/rank

    • rankings[]
  6. Your system

    Step 6, your system: The recruiter reaches out

    Outreach, sequences and consent stay in your product.

The whole skills taxonomy is one call away, with families and domains for your filters.

See the Skills API docs

Technical example

Normalize a profile’s skills in one call

A Python sketch for an enrichment worker. One request takes the profile’s whole skill list, up to 5,000 characters, and counts as one credit.

text
One free text up to 5,000 characters, French or English: a skill, a list or a skills section.
skills[].mention
The part of the text each skill came from, in the order of the text.
unresolved[]
Parts that match no taxonomy skill, with family_hints. Nothing is guessed.
Request · Python/api/v1/skills/resolve
import requests

resp = requests.post(
    "https://hirelayer.co/api/v1/skills/resolve",
    headers={"X-API-Key": API_KEY},
    json={"text": "React, Node, Cobol, gestion de projet", "language": "en"},
    timeout=65,
)
resp.raise_for_status()
result = resp.json()

for skill in result["skills"]:
    profile.add_skill(
        raw=skill["mention"],
        skill_id=skill["id"],  # store and filter on the id
        name=skill["name"],
    )
for part in result["unresolved"]:
    profile.flag_for_review(part["text"])  # never guessed
profile.taxonomy_version = result["taxonomy_version"]
Response · abridged
{
  "language": "en",
  "skills": [
    {
      "id": "react",
      "name": "React",
      "type": "software",
      "mention": "React",
      "families": [
        {
          "id": "frontend_development",
          "name": "Frontend development",
          "domain_id": "software_development"
        }
      ],
      "domains": [
        { "id": "software_development", "name": "Software Development" }
      ],
      "broader": null
    },
    // type, families, domains and broader left out below
    { "id": "node_js", "name": "Node.js", "mention": "Node" },
    { "id": "cobol", "name": "COBOL", "mention": "Cobol" },
    {
      "id": "project_management",
      "name": "Project management",
      "mention": "gestion de projet"
    }
  ],
  "unresolved": [],
  "taxonomy_version": "v1"
}

APIs used

The HireLayer APIs behind this workflow

Start with the core APIs, add the others when a feature needs them. All five share one API key and one credit balance.

Compare all products

Outcomes

What recruiters using your product notice

  • Search that survives synonyms

    Queries and profiles meet on skill ids rather than on spelling.

  • Richer profiles, no manual entry

    Attached CVs become structured fields as soon as they are captured.

  • A reading order for longlists

    Recruiters open the most relevant profiles first, with a rationale for each position.

  • Facets you can group

    Each skill has families and domains, the primary one first, to build skill clusters and filters.

FAQ

Sourcing tools: frequently asked questions

Does HireLayer find candidates?

No. HireLayer does not crawl or source profiles. It structures and compares the profiles your product has already captured, and your product keeps discovery, provenance and outreach.

How do we normalize skills on profiles imported in bulk?

Send each imported profile’s skill strings together as one text, up to 5,000 characters per call, and keep the original label for display beside the skill id used by search. One successful call costs one credit, however many skills the text names.

Can recruiters filter search by the same skill vocabulary?

Yes. GET /api/v1/skills returns the whole taxonomy, 11,061 skills with their families and domains, so your search filters can offer recruiters exactly the skills that sourced profiles are resolved to. Cache it on your side.

What if a recruiter’s query maps to the wrong skill?

Each resolved skill comes back with mention, the words of the query it was found in, so your product can show it as a chip the recruiter removes before the search runs. Parts of the query that match no skill are listed in unresolved rather than guessed; there is no score or threshold to tune.

How does ranking fit a long list of search results?

Let your search engine produce the longlist, then send the role and the first profiles the recruiter will open, up to 10, to Rank. Positions only compare profiles sent in the same call, so keep a shortlist together in one request.

Send a real recruiter query

Create an account and send your own query or skill list to /skills/resolve. One credit covers a whole text of up to 5,000 characters. The free plan includes 50 credits a month, shared by all five APIs.