OData Documentation

Introduction

The People First OData APIs are ideal for bulk data query operations, such as report generation. OData is a standard protocol that defines a RESTful API for consuming and querying data. As a RESTful API, it places very few technology constraints on how it can be accessed. It is supported natively by many third party products, such as Microsoft Excel and Microsoft Power BI. OData libraries are available for most popular programming languages. For detailed information and specifications regarding OData please refer to the OData site.

OData Support

While the OData protocol itself provides supports for data create, read, update, and delete operations, the People First OData APIs are designed specifically for data extraction purposes and is therefore read-only. The People First OData services support OData v4.0 and both JSON and XML response formats.


OData API Authentication

All OData API requests should be authenticated using an access token. For data tools that have native support for either HTTP Bearer, or Basic Authentication, you should follow the People First Access Token instructions here.

Where a data tool doesn't natively support Bearer or Basic Authentication, you might be able to configure a custom authentication mechanism within the tool. An example of creating a custom authentication configuration for tools using Microsoft Power Query (e.g. Excel and Power BI) can be found here.


API Compatibility Considerations

As with the other People First APIs, consumers of the OData APIs will need to be aware of the type of changes that are considered to be backwards compatible, and will need to code their applications to handle them. Further details are available here.


Data API Discovery

OData aims to provide a self-describing data model and API for accessing that data model. This allows generic clients to interact with an OData service by discovering its data API using well defined mechanisms. The starting point for accessing any OData service is the service root URI.

All OData services publish a service document resource. The service document lists all of the resources (entity sets, functions, singletons) that are available from the service. The service document resource can be retrieved by issuing a GET request to the service root URI.

In addition, an OData service will publish a metadata document resource. The metadata document lists all of the data types, sets, functions, and actions understood by the service. This allows you to understand the entities (resources) that the service exposes and how to interact with them. The metadata document resource can be retrieved by issuing a GET request to the URI obtained by appending /$metadata to the service root URI.

The following examples show the relationship between the discovery URIs:

  • Service Root - https://mydomain.com/myservice/odata
  • Service Document - https://mydomain.com/myservice/odata
  • Metadata Document - https://mydomain.com/myservice/odata/$metadata

Below is a snippet from a typical service document:

{
  "@odata.context": "https://mydomain.com/myservice/odata/$metadata",
  "value": [
    {
      "name": "applicationstates",
      "url": "applicationstates"
    },
    {
      "name": "applications",
      "url": "applications"
    },
    {
      "name": "applicants",
      "url": "applicants"
    }
  ]
}

The above service document describes an OData service that exposes three entity set resources, namely applicants, applications, and applicationstates. The service document also provides a link to the metadata document describing those resources.


Below is a snippet from a typical metadata document:


  <?xml version='1.0' encoding='UTF-8'?>
  <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
      <edmx:DataServices>
          <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="MyService">
              <EntityType Name="applicant">
                  <Key>
                      <PropertyRef Name="Id"/>
                  </Key>
                  <Property Name="Forename" Type="Edm.String" MaxLength="255"/>
                  <Property Name="Surname" Type="Edm.String" MaxLength="255"/>
                  <Property Name="Id" Type="Edm.Guid"/>
                  <NavigationProperty Name="Applications" Type="Collection(MyService.application)" Partner="Applicant">
                      <ReferentialConstraint Property="Id" ReferencedProperty="Applicantid"/>
                  </NavigationProperty>
              </EntityType>
              <EntityType Name="application">
                  <Key>
                      <PropertyRef Name="Id"/>
                  </Key>
                  <Property Name="Id" Type="Edm.Guid"/>
                  <Property Name="CurrentStateId" Type="Edm.Guid"/>
                  <Property Name="Applicantid" Type="Edm.Guid"/>
                  <NavigationProperty Name="CurrentState" Type="MyService.applicationstate">
                      <ReferentialConstraint Property="CurrentStateId" ReferencedProperty="Id"/>
                  </NavigationProperty>
                  <NavigationProperty Name="Applicant" Type="MyService.applicant" Partner="Applications">
                      <ReferentialConstraint Property="Applicantid" ReferencedProperty="Id"/>
                  </NavigationProperty>
              </EntityType>
              <EntityType Name="applicationstate">
                  <Key>
                      <PropertyRef Name="Id"/>
                  </Key>
                  <Property Name="CurrentStage" Type="Edm.String" MaxLength="255"/>
                  <Property Name="Id" Type="Edm.Guid"/>
                  <Property Name="CreationDate" Type="Edm.DateTimeOffset" Precision="3"/>
                  <Property Name="ApplicationId" Type="Edm.Guid"/>
                  <Property Name="CurrentStageDescription" Type="Edm.String" MaxLength="255"/>
                  <Property Name="NextStage" Type="Edm.String" MaxLength="255"/>
                  <NavigationProperty Name="Application" Type="MyService.application">
                      <ReferentialConstraint Property="ApplicationId" ReferencedProperty="Id"/>
                  </NavigationProperty>
              </EntityType>
              <EntityContainer Name="MyServiceContainer">
                  <EntitySet Name="applicationstates" EntityType="MyService.applicationstate">
                      <NavigationPropertyBinding Path="Application" Target="applications"/>
                  </EntitySet>
                  <EntitySet Name="applications" EntityType="MyService.application">
                      <NavigationPropertyBinding Path="CurrentState" Target="applicationstates"/>
                      <NavigationPropertyBinding Path="Applicant" Target="applicants"/>
                  </EntitySet>
                  <EntitySet Name="applicants" EntityType="MyService.applicant">
                      <NavigationPropertyBinding Path="Applications" Target="applications"/>
                  </EntitySet>
              </EntityContainer>
          </Schema>
      </edmx:DataServices>
  </edmx:Edmx>

The above metadata document describes the types that are contained within the entity sets that the service exposes e.g. the applicants entity set is comprised of MyService.applicant entities.

The document also defines the data model for each of those entities e.g. MyService.applicant has an Id, Forename, Surname, and navigable collection of applications (MyService.application).


People First OData Service Endpoints

Below is a list of the Service Root URIs for the People First OData services:

HRM - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/hrm/odata

Absence - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/hrm/odata/absences

Learning - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/learning/odata

Talent - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/talent/odata

Checkins - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/checkins/odata

Goals - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/goals/odata

Recognitions - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recognitions/odata

Recruitment - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata

Socialfeed - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/socialfeed/odata

Custom cards - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/customcards/odata

Aggregate - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/aggregate/audit/odata

Payroll - (Object model of all entities here)

  • Service Root - https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/payroll/odata

OData Requests

There are many ways to request data via the OData APIs ranging from simple requests to complex requests containing queries with multiple conditions and actions, such as filter, orderby, and expand. There are often several ways to request the same data.

A few example requests (based upon the above service and metadata documents) are outlined below. For a detailed treatment of the different request and query options, please refer to the OData documentation.

For each example, the raw request, response, and a sample cURL command are presented.

The following parameters are used throughout:

  • TENANT_CODE is the tenant code that was provided by MHR.
  • ENVIRONMENT_CODE is the environment code that was provided by MHR. When accessing your default environment (typically your production environment) the -ENVIRONMENT_CODE hostname segment, and EnvironmentCode HTTP header field can be omitted.
  • ACCESS_TOKEN is the access token supplied by your System Administrator, or ID token obtained separately (see:OIDC ID Tokens).

Request a list of all applicants


GET /api/v1/recruitment/odata/applicants HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants",
  "value": [
    {
      "Forename": "Jimmy",
      "Surname": "Jobseeker",
      "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    },
    {
      "Forename": "Dotty",
      "Surname": "Net",
      "Id": "c33b1258-fe25-4a03-8ada-17bf3cb15dd1",
    }
  ]
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Request an applicant by their primary key (ID)


GET /api/v1/recruitment/odata/applicants(aa96f4fd-9df3-4ef1-8fac-17ae30f07e60) HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants/$entity",
  "Forename": "Jimmy",
  "Surname": "Jobseeker",
  "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60"
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants(aa96f4fd-9df3-4ef1-8fac-17ae30f07e60)" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Request an applicant by their name


GET /api/v1/recruitment/odata/applicants?$filter=(Forename eq 'Jimmy') and (Surname eq 'Jobseeker') HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants",
  "value": [
    {
      "Forename": "Jimmy",
      "Surname": "Jobseeker",
      "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    }
  ]
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants?$filter=(Forename eq 'Jimmy') and (Surname eq 'Jobseeker')" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Count the number of applicants


GET /api/v1/recruitment/odata/applicants?$count=true HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants",
  "@odata.count": 2,
  "value": [
    {
      "Forename": "Jimmy",
      "Surname": "Jobseeker",
      "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    },
    {
      "Forename": "Dotty",
      "Surname": "Net",
      "Id": "c33b1258-fe25-4a03-8ada-17bf3cb15dd1",
    }
  ]
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants?$count=true" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Request an ordered list of applicants


GET /api/v1/recruitment/odata/applicants?$orderby=Forename HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants",
  "value": [
    {
      "Forename": "Dotty",
      "Surname": "Net",
      "Id": "c33b1258-fe25-4a03-8ada-17bf3cb15dd1",
    },
    {
      "Forename": "Jimmy",
      "Surname": "Jobseeker",
      "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    }
  ]
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants?$orderby=Forename" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Request an applicant by their primary key (ID) and include all of their applications


GET /api/v1/recruitment/odata/applicants(aa96f4fd-9df3-4ef1-8fac-17ae30f07e60)?$expand=Applications HTTP/1.1
Host: TENANT_CODE-ENVIRONMENT_CODE.people-first.com
Accept-Language: en-GB
Content-Type: application/json; charset=utf-8
TenantCode: TENANT_CODE
EnvironmentCode: ENVIRONMENT_CODE
Authorization: Bearer ACCESS_TOKEN

{
  "@odata.context": "https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/api/v1/recruitment/odata/$metadata#applicants/$entity",
  "Forename": "Jimmy",
  "Surname": "Jobseeker",
  "Id": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
  "Applications": [
    {
      "Id": "47aedb1b-a2e2-4c6d-9065-17ae722ae740",
      "CurrentStateId": "f75c757c-8112-4847-9b0b-17ba06e338b0",
      "Applicantid": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    },
    {
      "Id": "bbb0b87a-9401-4528-815f-17b9c2403e00",
      "CurrentStateId": "5a1f8e17-c8a3-4a97-93d3-17b9d01d0ef0",
      "Applicantid": "aa96f4fd-9df3-4ef1-8fac-17ae30f07e60",
    }
  ]
}

curl --location --request GET "https://tpruk-dev.people-first.com/api/v1/recruitment/odata/applicants(aa96f4fd-9df3-4ef1-8fac-17ae30f07e60)?$expand=Applications" \
    --header "TenantCode: tpruk" \
    --header "EnvironmentCode: dev" \
    --header "Accept-Language: en-GB" \
    --header "Content-Type: application/json; charset=utf-8" \
    --header "Authorization: Bearer eyJ0eXAiOiJKVMsntWbLxWnNnRNZva2iueYc7KTFKP1Kz6Paog

Configuring Authentication for Microsoft Power Query

Below are some instructions on how to configure Power Query applications to authenticate with the People First OData API.

  1. From the Data tab select the Get Data dropdown menu. From the dropdown, select the From Other Sources and then Blank Query menu items. This will open the Power Query Editor.

  2. Select the query you want to configure from the list within the left-hand panel. Right-click and select Advanced Editor from the context menu. This will display the Advanced Editor dialog.

  3. Paste the following query script into the Advanced Editor, substituting the placeholders with values appropriate for your system and use case.
    let
        Source = OData.Feed("https://TENANT_CODE-ENVIRONMENT_CODE.people-first.com/ODATA_REQUEST_URI_PATH"
        , null
        , [Headers=[TenantCode="TENANT_CODE", EnvironmentCode="ENVIRONMENT_CODE", Authorization="Bearer ACCESS_TOKEN"]])
    in
        Source
    

    Where:

    • TENANT_CODE is the tenant code that was provided by MHR.
    • ENVIRONMENT_CODE is the environment code that was provided by MHR. When accessing your default environment (typically your production environment) the -ENVIRONMENT_CODE hostname segment, and EnvironmentCode HTTP header field can be omitted.
    • ODATA_REQUEST_URI_PATH is the URI path for the OData request you are making.
    • ACCESS_TOKEN is the access token supplied by your System Administrator, or ID token obtained separately (see:OIDC ID Tokens).


  4. You might be prompted to edit your credentials. If so, open the Edit Credentials dialog and choose anonymous access.

  5. You should now be presented with a preview of your OData query results.