Profile Searching

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

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

The final goal is to integrate HrFlow.ai into your website structure to deliver fast and personalized Profile Searching experiences.

πŸ“˜

Prerequisites

  1. ✨ Create a Workspace
  2. πŸ”‘ Get your API Key
  3. 🧠 Activate Profile Searching API
  4. πŸ”Œ Create, Configure a Source

πŸ“˜

API Endpoint

Get more information about the endpoint 🧠 Search Profiles indexed in Sources.

Step 1: Index Profiles in your Sources

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.

πŸ“˜

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: Get your First Searching Results with Postman

We are now ready to use the HrFlow.ai Searching API to make multi-criteria query searches over one or multiple Sources of Profiles.

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

πŸ“˜

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

Following the steps from the HrFlow.ai Postman publication will land you on this page:

2880

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 Profile Searching are:

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

1920

2. Multiple Criteria Search in a Source

Now that the environment is selected, we can try our first request to Search Profiles in the specified Source by source_key. Let's try a default request:

1920

Now let's add two filters :

  • Seniority: by specifying experiences_duration_min = 4
  • Skills: looking for profiles with Python skills by setting it in the field skills, which is a list of objects, see for more details.
1920

πŸ“˜

Retrieving query results with pagination

Pagination enables you to have complete control over how you retrieve query results. For example, you can fetch a specific page by using the page parameter, which serves as a page offset combined with the limit parameter that specifies the number of profiles per page.
We strongly recommend using a reasonably low value for the limit and leveraging the pagination system to retrieve all your queries results.

3. Multiple Criteria Search in Multiple Sources

Now, let's search Profiles in two Sources. To do so, we can simply :

  1. Add its source_key to the list of source_keys
  2. Send the request and see the new retrieved hits
1920

For further details on query structure and the different criteria used to filter Profiles in selected Sources, you can refer to 🧠 Search Profiles indexed in Sources.

🚧

Sorting Results

  • By default, the results are sorted with regards to profiles' creation date: sort_by=created_at. Thus, the results start from the most recent to the oldest.
  • Sorting by searching relevance requires at least one criteria.

Step 3: Integrate and Display Profile Searching Results in your Website

You can integrate the overall setup into one place where users can set multi-criteria filters. First, the Profile Searching 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 by 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;
}
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
    return (
      `<div class="card profile" key=${profile.key}>
         <h3>${name}</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: "",
  source_keys: ["YOUR_SOURCE_KEY"],
  stage: 'new',
  sort_by: 'created_at',
  order_by: 'desc',
  limit: 10,
  page: 1,
  location_distance: 30,
  location_geopoint: {},
  use_agent: 0,
  text_keywords: [],
  tags_included: [[]],
 }

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

axiosHrflow.get(url)
  .then( res => {
  const fetchedProfiles = { 
    profiles: res.data.data.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 it 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.

1920

What’s Next