Profile Scoring

Index, retrieve, and display HrFlow.ai's Profile Scoring results over 50 data points.

In this article, we'll take a look at how HrFlow.ai Profile Scoring API works by interacting with the endpoint 🧠 Score Profiles indexed in Sources. We will test queries through our public HrFlow.ai Postman collection.

The final goal is to allow you to seamlessly integrate HrFlow.ai into your website structure to deliver fast and personalized Profile Scoring experiences.

📘

Prerequisites

  1. ✨ Create a Workspace
  2. 🔑 Get your API Key
  3. 🧠 Activate Profile Searching API
  4. 🧠 Activate Profile Scoring API
  5. 🧠 Activate Job Searching API
  6. 🧠 Activate Job Scoring API
  7. 🔌 Create, Configure a Source
  8. 🔌 Create a Board
  9. 🎨 Create, Configure a Scoring Algorithm

📘

API Endpoint

Get more information about the endpoint 🧠 Score Profiles indexed in Sources for a Job.

Step 1: Index Profiles in your Source

Profiles in HrFlow.ai are indexed in special folders called Sources. To create a source, you can refer to this page 🔌 Create, Configure a Source.

Depending on the nature of your data, indexing a profile can be done through one of the two following ways:

  • From structured information
    In the case of highly-structured data, the first step consists of adapting your data to the HrFlow.ai Profile Object format. Please refer to 📖 Profile Object for all the required fields and values structures. Then, using the indexing endpoint, you can index your Profile Object in your desired Source. A complete description of the indexing endpoint can be found at 💾 Index a Profile in a Source.

  • From a resume file
    Besides structured data, we also have the case of unstructured documents. The most commonly encountered example is raw resumes. These documents need to be parsed by our Parsing API. A complete description of the parsing endpoint can be found at 🧠 Parse a Resume in a Source). Note that the Parsing module structures the CV and automatically indexes it afterward in the specified Source.

Before a profile is indexed in our Scoring API, ensuring its quality and completeness is crucial. The profile must meet the criteria for being indexable on the Searching API. For more information, refer to Profile Searching

Additionally, the following criteria are utilized to determine whether a profile should be indexed on the Scoring engine:

  • Experiences Check : The profile must contain at least 1 experience with a valid company entry.
  • Educations Check : The profile must include at least 1 education entry with essential information such as school ortitle.
  • Summary Check : The summary must be a non-empty string.
  • Skills Check : The profile must have at least 1 skill.
  • Tasks Check : The profile must contain at least 1 task.
Profile Scoring Validation Process

Profile Scoring Validation Process

Profile Experiences Validation Process

Profile Experiences Validation Process

Profile Education Validation Process

Profile Education Validation Process

🚧

Profiles failing to meet any of these requirements will not be indexed to the Scoring API

For a profile to be available through the Scoring API, it must any of these criteria, ensuring that only high-quality and relevant profiles are included in the search results.

📘

Index Profile with a reference

  • Specifying a reference eases Profile updates in HrFlow.ai.
  • This optional reference uniquely identifies the Profile in HrFlow.ai.
  • Profile always has a unique identification key (Profile key) generated by HrFlow.ai.
  • Define the granularity of your searching needs

🚧

Indexed Profiles in HrFlow.ai must be kept up-to-date

To prevent outdated results from our Searching API, ensure updating all Profiles on which changes have occurred. Check here for more details on how to 💾 Edit a Profile indexed in a Source.

Step 2: Index Jobs in your Board

Jobs in HrFlow.ai are indexed in special folders called Boards. You can refer to 🔌 Create a Board to create a Board.

First, you need to adapt your data to the HrFlow.ai Job Object format. All the required fields and values structures are defined at 📖 Job Object. Then, your Job Object is indexed in your desired Board using the indexing endpoint.

You can find a more thorough description of the indexing endpoint at 💾 Index a Job in a Board.

📘

Index Job with a reference

  • Specifying a reference eases Job updates in HrFlow.ai
  • This reference is optional and uniquely identifies a Job in HrFlow.ai.
  • Job always has a unique identification key (Job key) generated by HrFlow.ai.

🚧

Indexed Jobs in HrFlow.ai must be kept up-to-date

To prevent outdated results from our Searching API, ensure updating all Jobs on which changes have taken place. Check here for more details on how to 💾 Edit a Job indexed in a Source.

Step 3: Get your First Scoring Results with Postman

We are now ready to use the Scoring API with the AI Scoring Algorithm previously created. We will show you how to retrieve and sort Profiles according to their matching score for a given Job.

Let's dig deeper into our Profile Scoring endpoint possibilities. In the following, we are going to use our Postman Collection and focus on the endpoint that allows us to 🧠 Scoring Profiles indexed in Sources for a Job.

📘

HrFlow.ai Postman

Check our publication on HrFlow.ai Postman to get started with our Postman collection.

Run in Postman

1. Configure your Postman Environment

Once you have followed the first steps described in this article, you will land on this page:

First, click on the "Environments" tab on the left side of your Postman window. Then, fill in the Empty - Environment template with the correct values. The compulsory variables for Profiles Scoring are:

  • x-api-key: follow the steps from 🔑 API Authentication to retrieve it
  • x-user-email: follow the steps from 🔑 API Authentication to retrieve it
  • board_key: the Board containing the Job for which we are looking for relevant Profiles
  • source_key: the Source on which we will score and search for Profiles
  • job_key/job_reference: the key/reference of the Job for which we are looking for relevant Profiles.
  • scoring_algorithm_key: the key of the Scoring algorithm

Finally, save the environment and ensure that you selected Empty - Environment as your current environment.

2. Score Profiles in a Source

Now that the environment is selected, we can test our first request to Score Profiles from a Source against a Job. But, first, let's try a default request:

Let's break down the Scoring request's response. The field data of the response object contains two nested lists with the same length:

  • predictions: array given by the Scoring Algorithm
  • profiles: Profile Objects that correspond to the criteria

Both lists are synchronized. The n-th prediction is associated with the n-th Profile.

🚧

How to read the values in predictions ?

For each Profile, the associated prediction is a list of two numbers: [1-P, P]
where P represents the matching score between the Profile and the target Job.

In our example above, the first Profile came along with the prediction [0.18171161413192749, 0.81828838586807251].
Thus, the matching score is the second one: 0.81828838586807251.

3. Filter Scoring Results by Adding Multiple Searching Criteria

Adding filtering parameters to the request will filter the Profiles returned by the Scoring endpoint. Thus, it will keep results corresponding to some Searching criteria. As a result:

  1. The Scoring Algorithm will score all the Profiles in the selected Sources with regards to the target Job
  2. Afterwards, the Profiles are going to be filtered out according to the filtering parameters

In the example below, the following filters are being used:

  • Seniority: at least four years of experiences, experiences_duration_min = 4
  • Skills: profiles with Python skill, by setting it in the field skills (list of objects, see 📖 Trait Objects for more details)

📘

FIltering results post Scoring order

The sort_by parameter changes the sorting strategy rule.

  • sort_by = created_at: it is the default behavior where profiles will be shown from the most recent to the oldest.
  • sort_by = searching: by adding Searching filter parameters, the Scoring API will sort the results according to the relevance based on the Searching criteria.
  • sort_by = scoring: applies the Searching filters while maintaining the highest scores at the top

Other sorting rules are available. Feel free to get more details at 🧠 Scoring Profiles indexed in Sources for a Job.

Step 4: Integrate and Display Profile Scoring Results in your Website

You can integrate the overall setup into one place where users can set multi-criteria filters. First, the Profile Scoring endpoint is called with the underlying query. Then, the results are displayed in a more user-friendly format.

Here’s a new code demo using Plain HTML, Plain CSS, and Vanilla Javascript showing how to display Profiles in a website page leveraging HrFlow.ai Profile Searching results.

<div id="app">
  <div class="profiles" id="profiles">
  </div>
</div>
#app {
  font-family: -apple-system,system-ui,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen-Sans,Ubuntu,Cantarell,'Helvetica Neue',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';
  letter-spacing: .01em;
  -webkit-font-smoothing: antialiased;
  font-feature-settings: 'calt' 0;
  overflow-x: hidden;
  background: #eee
}

.profiles {
  width: 50%;
  margin: auto;
  padding: 1rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.card {
  width: 100%;
  padding: 1.5rem;
  border-radius: 5px;
  transition: all 0.2s cubic-bezier(0.41, 0.094, 0.54, 0.07) 0s;
  border-width: 1px;
  border-style: solid;
  border-color: rgb(238, 238, 238);
    box-shadow: rgba(0, 0, 0, 0.05) 1px 2px 4px;
    backface-visibility: hidden;
    background-color: rgb(255, 255, 255);
    border-image: initial;
    margin-bottom: 1.5rem;
}
.content {
    width: 100%;
    display: flex;
    justify-content: flex-start;
    text-decoration: none;
    color: #000;
    position: relative;
}

.info {
    flex: 1 1 auto;
}


.icon {
    width: 17px;
    height: auto;
    margin-right: 0.5rem;
}

.urls {
    display: flex;
    flex-direction: column;
}

.url {
    display: flex;
    align-items: center;
    text-decoration: none;
    color: inherit;
    margin-bottom: 0.5rem;
    margin-top: 0.5rem;
}

.error {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.text-light {
    color: #333333;
    font-size: 0.9rem;
    line-height: 1.5;
    opacity: 0.5;
    font-weight: normal;
}

.icon {
  margin-right: 0.5rem;
}

.score {
  padding: 2px 8px;
  color: white;
  font-size: 15px;
  border-radius: 50px;
  magin-left: 5px;
}
const axiosHrflow = axios.create({
  baseURL: 'https://api.hrflow.ai/v1',
  headers: {
    'X-API-KEY': 'YOUR_SECRET_API_KEY'
  }
});

const  buildQueryString =  (url, queryObject) => {
  let queryString = `${url}?`;
  Object.keys(queryObject).forEach(item => {
  if (typeof queryObject[item] === 'string'
      || queryObject[item] instanceof String) {
    queryString += `${item}=${queryObject[item]}&`;
  } else {
    queryString += `${item}=${JSON.stringify(queryObject[item])}&`;
  }
});
    return queryString; 
}

  const displayProfiles = profiles => {
  const profilesListHtml =  profiles.map(profile => {
  const name = profile.info.full_name
  const location = profile.info.location.text
  const summary = profile.info.summary
  const type = profile.tags.filter(tag => tag.name === 'type')[0].value
  const category = profile.tags.filter(tag => tag.name === 'category')[0].value
  const workingFrom = profile.tags.filter(tag => tag.name === 'working-type')[0].value
  const linkedin = profile.info.urls.linkedin
  const instagram = profile.info.urls.instagram
  const twitter = profile.info.urls.twitter
  const position = profile.experiences[0].title
  const score = profile.score ? Math.min(Math.round(profile.score * 100, 0), 100) : null;
  let scoreColor = '';
    if (score < 50) {
      scoreColor = '#ff6b6b';
    }
    if (score >= 50 && score < 75) {
      scoreColor = '#ff9f43';
    }
    if (score >= 75) {
      scoreColor = '#1dd1a1';
    }
    return (
      `<div class="card profile" key=${profile.key}>
         <h3>${name} <span style="background:${scoreColor}" class="score">${score}%</span></h3>
         <div class="info">
          <div>worked as ${type}</div>
          <div>
            ${position}
            <span class="text-light"> (${category})</span>
          </div>
         <div>
            ${location}
            <span class="text-light"> (open to ${workingFrom})</span>
         </div>
        </div>
        <div class="urls">
          <a href=${linkedin} target="_blank" class="url"}>
            <i class="fab fa-linkedin icon"></i>Linkedin
          </a>
          <a href=${instagram} target="_blank" class="url">
            <i class="fab fa-instagram icon"></i>Instagram
          </a>
        </div>
        <div>
          <i class="fa fa-star icon"></i><span>${summary}</span>
        </div>
      </div>
      `
    )
  }).join(' ');
  const appElmt = document.getElementById('profiles');
  appElmt.innerHTML = profilesListHtml
}

const query = {
  job_key: "YOUR_JOB_KEY",
  source_keys: ["YOUR_SOURCE_KEY"],
  stage: 'yes',
  sort_by: 'scoring',
  order_by: 'desc',
  limit: 10,
  page: 1,
  location_distance: 30,
  location_geopoint: {},
  use_agent: 1,
  text_keywords: [],
  tags_included: [[]],
  board_key: "YOUR_BOARD_KEY",
  agent_key: "YOUR_ALGORITHM_KEY"
 }

 const url = buildQueryString('profiles/scoring', query);

axiosHrflow.get(url)
  .then( res => {
  const  scores = res.data.data.predictions;
  const  profiles = res.data.data.profiles;
  profiles.forEach( (profile, index) => {
      if (scores.length === profiles.length) {
        profile.score = scores[index][1];
      }
    });
  const fetchedProfiles = { 
    profiles: profiles,
    meta: res.data.meta
  }
  displayProfiles(fetchedProfiles.profiles);
}).catch( err => {
  console.log('error', err)
});

Advanced Topics

1. Add Custom Attributes

You can further adapt your Profile Object by adding Tags relevant to your business needs. Tags are custom attributes uniquely identified by their name and value. The example below shows how two additional Tags, contract_type and entity, are integrated within a HrFlow.ai Profile Object.

{
  "tags": [
    {
      "name": "contract_type",
      "value": "Full Time"
    },     
    {
      "name": "entity", 
      "value": "R&D"
    }
  ]
}
{
  "key": "8af2b7a0b48fbc936ace283ec020b0d6d4c4b018",
  "reference": null,
  "consent_algorithmic": {
    "owner": {
      "parsing": true,
      "revealing": false,
      "embedding": true,
      "searching": true,
      "scoring": true,
      "reasoning": false
    },
    "controller": {
      "parsing": true,
      "revealing": false,
      "embedding": true,
      "searching": true,
      "scoring": true,
      "reasoning": false
    }
  },
  "archived_at": null,
  "updated_at": "2021-12-10T15:18:46+0000",
  "created_at": "2021-12-10T15:18:46+0000",
  "info": {
    "full_name": "Harry James Potter",
    "first_name": "Harry James",
    "last_name": "Potter",
    "email": "",
    "phone": "",
    "date_birth": "",
    "location": {
      "text": "",
      "lat": null,
      "lng": null,
      "gmaps": null,
      "fields": []
    },
    "urls": {
      "from_resume": [],
      "linkedin": "",
      "twitter": "",
      "facebook": "",
      "github": ""
    },
    "picture": "",
    "gender": "",
    "summary": ""
  },
  "text_language": "en",
  "text": "Harry James Potter",
  "experiences_duration": 0,
  "educations_duration": 0,
  "experiences": [],
  "educations": [],
  "attachments": [],
  "skills": [],
  "languages": [],
  "certifications": [],
  "courses": [],
  "tasks": [],
  "interests": [],
  "labels": [],
  "tags": [
    {
      "name": "archive",
      "value": false
    },
    {
      "name": "contract_type",
      "value": "Full Time"
    },
    {
      "name": "entity",
      "value": "R&D"
    }
  ],
  "metadatas": []
}

2. Try Profile Scoring in your Favorite Programming Language

You might want to try the same experience in your favorite programming language. Luckily, Postman automatically provides us with the correct code corresponding to the request in several programming languages.

All you have to do is:

  1. Go to the code tab in the upper right corner,
  2. Then select your target programming language from the dropdown,

And voilà, all you have to do now is copy and paste this code and try it out straight away.