Image
abstract swish line in gradient colouring from pink to blue on a dark blue background

People First API

HATEOAS

What is HATEOAS?

HATEOAS stands for Hypermedia As The Engine Of Application State. HATEOAS is an architectural constraint of REST based APIs whereby in response to requests from the client the server provides not only resource data, but also hyperlinks which allow the client to dynamically traverse various related resources kept on the API server merely by association.

What benefit does HATEOAS provide?

HATEOAS can make a REST application self discoverable by the consumer, meaning the consumer need only know a single fixed entry URI and thereby the hypermedia links provided dynamically by each subsequent response should allow any and all resources provided by the REST application to be discoverable by traversing the associated links. These restrictions imposed by HATEOAS decouple the client and server meaning that both the frontend and backend designs can evolve independently and allow for much better scalability. HATEOAS also applies a standardised design to the REST application meaning there is little to no need for documentation.

What kind of hypermedia links are provided by People First API responses? and how can these be utilised by PF API integrators?

If you haven't yet read through this websites quick start guides for authentication and first API calls then click here and read those first. It will give you a better understanding of this section and its applications.

Within the guide you will have sent a request to the People First APIs for 'Create Person', the example response object can be viewed below and its full content can be fully accessed by the using the scroll bar to the right-hand side of the viewing window:
 

{
    "meta": {
        "links": {
            "self": {
                "href": "/hrm/people"
            }
        },
        "person.personalReference": {
            "disabled": "true"
        },
        "person.lastName": {
            "mandatory": "true"
        },
        "person.firstName": {
            "mandatory": "true"
        },
        "person.title": {
            "mandatory": "true",
            "values": [
                {
                    "value": "Mr",
                    "id": "9e188b9d-737b-4c9d-92bb-199d8a6fba5c",
                    "code": "TITLE0001"
                }
            ]
        },
        "person.socialSecurityNumbers": {
            "mandatory": "true"
        },
        "person.socialSecurityNumbers.legislation": {
            "mandatory": "true",
            "values": [
                {
                    "value": "United Kingdom",
                    "id": "47c23873-057b-4b22-b2d9-a1a31ccec3fb",
                    "code": "UK"
                }
            ]
        },
        "person.socialSecurityNumbers.socialSecurityNumber": {
            "mandatory": "true"
        },
        "person.startDate": {
            "disabled": "true",
            "hidden": "true"
        }
    },
    "data": {
        "person": {
            "_links": {
                "createBannerImage": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/bannerimage/resourcetemplate"
                },
                "disabilityInformation": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/disabilityinformation"
                },
                "sensitiveInformation": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/sensitiveinformation"
                },
                "team": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/team?page%5BLimit%5D=10&page%5BOffset%5D=0"
                },
                "teamPeople": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/team/people?page%5BLimit%5D=10&page%5BOffset%5D=0"
                },
                "photoUpload": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/photo"
                },
                "attachments": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/attachments",
                    "template": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/attachments/resourcetemplate"
                },
                "notes": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/notes",
                    "template": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/notes/resourcetemplate"
                },
                "events": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/events"
                },
                "absenceTypes": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absencetypes"
                },
                "contacts": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/contactinfo"
                },
                "absenceDisabledPeriods": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/globalAbsenceDisabledPeriods"
                },
                "createHolidayAbsence": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absences/absencetypes/c7a9ef1a-69a3-4cf6-bd82-67a34d3a9c2d/resourcetemplate"
                },
                "createSicknessAbsence": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absences/absencetypes/31467a35-a27b-45dd-be22-629816d9aa93/resourcetemplate"
                },
                "transfer": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/transferrequest/resourcetemplate"
                },
                "startOccupancy": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/occupancies/resourcetemplate"
                },
                "rightToWork": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/righttowork"
                },
                "passports": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/passports"
                },
                "residencyPermits": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/residencyPermits"
                },
                "emergencyContacts": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/emergencyContacts"
                },
                "createEmergencyContacts": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/friendsfamily/resourcetemplate"
                },
                "friendsFamily": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/friendsfamily"
                },
                "createFriendsFamily": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/friendsfamily/resourcetemplate"
                },
                "drivers": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers"
                },
                "createDrivers": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers/resourcetemplate"
                },
                "visas": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/visas"
                },
                "address": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/address"
                },
                "createAddress": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/address"
                },
                "peers": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/peers?page%5BLimit%5D=10&page%5BOffset%5D=0"
                },
                "personStatement": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/statement"
                },
                "editPersonStatement": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/statement"
                },
                "personManagerStatement": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/managerstatement"
                },
                "publicHolidays": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/publicholidays"
                },
                "employmentPeriods": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/employmentperiods"
                },
                "occupancies": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/occupancies"
                },
                "bankAccounts": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/bankaccounts"
                },
                "absenceProfile": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absenceProfile"
                },
                "outOfOffice": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/colleagues/outofoffice"
                },
                "outOfOfficePeers": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/outofoffice/peers"
                },
                "outOfOfficeManagers": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/outofoffice/managers"
                },
                "employmentProfile": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/employmentProfile"
                },
                "employmentStatus": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/employmentstatus"
                },
                "editLeaveAllowance": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absenceallowancedetails/effdate/2022-06-20"
                },
                "patternSchedule": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/patterntype/WP/schedule"
                },
                "absenceAllowanceScheme": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/absenceAllowanceScheme/effdate/2022-06-20"
                },
                "certificateOfSponsorships": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/sponsorshipcertificates"
                },
                "workPermits": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/workpermits"
                },
                "settlementStatuses": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/settlementstatuses"
                },
                "leaveOccupancy": {
                    "href": "/hrm/employmentperiods/38596d64-11c4-4525-9953-aeba007316d8"
                },
                "personSignatureHeld": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/signatureheld"
                },
                "self": {
                    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4"
                }
            },
            "personId": "7c24544e-2b36-495f-91b6-aeba007316a4",
            "firstName": "Edward",
            "lastName": "Norton",
            "title": "9e188b9d-737b-4c9d-92bb-199d8a6fba5c",
            "otherNames": "",
            "knownAs": "Edward",
            "pronouns": "",
            "previousLastName": "",
            "startDate": "2022-06-01",
            "personalReference": "A07",
            "socialSecurityNumbers": [
                {
                    "legislation": "47c23873-057b-4b22-b2d9-a1a31ccec3fb",
                    "socialSecurityNumber": "AB123457A",
                    "_status": "est"
                }
            ]
        }
    }
}
            


This JSON response object contains two initial member objects which are 'meta' and 'data'. The data object, as the name suggests, contains the response data relating to the request which called it. In this case we have made a request to create a person with the relevant data attached in the body, the person has been created by the functionality of the API then saved within the relevant database and then the response object has been returned to the client.

From the initial Create Person response object we are going to traverse a couple of the hypermedia links using the Postman requests which were used in the quick start guide referenced above (Making first call to People First API), as well as some of our own in order to demonstrate the HATEOAS principal using the People First APIs.
 


  "createDrivers": {
    "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers/resourcetemplate"
  },
              


For this HATEOAS demonstration we shall be adding Drivers Details to the example Person (Edward Norton) as per the above response object. When we created our person we needed a resource template in order to provide the structure for our request body object. We will also require a 'Create Drivers Resource Template' to again provide the structure for our next request. If we were to use Dot Notation on the above response object to locate the required URI path for our request then the JSON object path would be 'x.data.person._links.createDrivers.href'. This will locate the href property in the above object called "createDrivers".
 

Screenshot to demonstrate Driver Resource Template


We then copy our URI path value from the 'href' key and paste it into a new Postman 'GET' request immediately after the People First base URI as indicated above. Make sure your 'access-token' is valid, hasn't expired and is inserted as a header within the request, as per the quick start guide demonstration. Everything is now in place, so hit send.
 


{
    "meta": {
        "links": {
            "self": {
                "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers/resourcetemplate"
            }
        }
    },
    "data": {
        "persondrivers": {
            "_links": {
                "create": {
                    "href":  "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers"
                }
            },
            "countryId": "",
            "dateVerified": "",
            "disqualificationEndDate": "",
            "disqualificationStartDate": "",
            "isCurrentlyDisqualified": false,
            "licenceNumber": "",
            "carRegistrationNumber": "",
            "documentDiscriminator": "",
            "issuingStateId": "",
            "nameOnLicence": "",
            "validFrom": "",
            "validTo": "",
            "insuranceDateVerified": "",
            "insuranceValidFrom": "",
            "insuranceValidTo": "",
            "internationalDrivingPermitType": "",
            "internationalDrivingPermitExpiryDate": ""
        }
    }
}
              


The resource template required for adding driver details for our person can be seen above within the 'data' object, which is nested within the resource template response object. The object is called "persondrivers" (object name highlighted in blue). The response also contains a hyperlink for our next action to create the driver details (hyperlink highlighted in red).
 

Screenshots to demonstrate Driver Resource request


As we did with our previous request copy the URI path value from within the last response body received in reaction to the 'Drivers Details Resource Template'. The URI path is highlighted in red above. Paste the URI path value onto the end of your own People First base URI in a new Postman 'POST' request as indicated in the image above. As before ensure that your 'access-token' is valid and that your tenant / environment codes are correct.

Within your request, select 'Body' from the tabs below the request URI, and then click the 'raw' radio button then select 'JSON' from the dropdown menu at the end of the row. Extract the driver details resource template from the resource template response object and paste it into your Postman request body as demonstrated in the example above. Switch out the demo driver details for your details you wish to create. The fields which have been filled in are mandatory, so cannot be left blank. When you have completed all the details hit send.
 


{
    "meta": {
        "links": {
            "self": {
                "href": "/hrm/people/7c24544e-2b36-495f-91b6-aeba007316a4/drivers"
            }
        },
        "persondrivers.countryId": {
            "values": [
                {
                    "value": "United Kingdom",
                    "id": "5c586b7e-9417-4465-ab37-c8bb1471f967",
                    "code": "GBR"
                }
            ]
        }
    },
    "data": {
        "persondrivers": {
            "_links": {
                "self": {
                    "href": "/hrm/persondrivers/0c7cf253-5415-47dd-9399-aee500850a68"
                },
                "attachments": {
                    "href": "/hrm/persondrivers/0c7cf253-5415-47dd-9399-aee500850a68/attachments",
                    "template": "/hrm/persondrivers/0c7cf253-5415-47dd-9399-aee500850a68/attachments/resourcetemplate"
                }
            },
            "driverId": "0c7cf253-5415-47dd-9399-aee500850a68",
            "countryId": "5c586b7e-9417-4465-ab37-c8bb1471f967",
            "dateVerified": "",
            "disqualificationEndDate": "",
            "disqualificationStartDate": "",
            "isCurrentlyDisqualified": false,
            "licenceNumber": "NORT9701317TW9UB",
            "nameOnLicence": "Mr Edward Norton",
            "carRegistrationNumber": "YT02MYS",
            "documentDiscriminator": "",
            "issuingStateId": "",
            "personId": "7c24544e-2b36-495f-91b6-aeba007316a4",
            "validFrom": "1990-02-20",
            "validTo": "2040-02-20",
            "insuranceDateVerified": "",
            "insuranceValidFrom": "",
            "insuranceValidTo": "2023-03-12",
            "internationalDrivingPermitType": "",
            "internationalDrivingPermitExpiryDate": ""
        }
    }
}
              


Our example response can be seen in the above code extract. We can see that as well as returning the successfully created drivers details further hyperlinks have been returned to carry out further actions in relation to 'attachments' (highlighted in red). This brings the demonstration aspect an end. You should now have enough information to explore different resources using the People First APIs.

In this demonstration we have applied the basic principles of HATEOAS to the People First APIs. This has allowed us to explore different resources by traversing from one resource to another purely by using the hyperlinks provided in the response objects returned from the current PF API request.

 

Looking for something specific?