How to fetch employees from Paylocity using Python

Editor's note: this article is part of a series on building third-party API integrations. Explore Merge if you’re looking to add 180+ integrations across HR and payroll, ATS, CRM, accounting, ticketing, marketing automation, and file storage with one unified API.

Paylocity is an all-inclusive Human Resources Information System (HRIS) that consolidates payroll, benefits, talent management, and other HR-related tasks into a single platform. Utilizing cloud technology, it provides instantaneous data and potent tools for businesses of varying sizes, augmenting efficiency and informed decision-making. Additionally, Paylocity boasts a potent API, enabling developers to weave its features into bespoke applications, allowing for automated extraction of employee information and other HR-centric data.

For a developer, extracting Employee data from a client's Paylocity system can automate HR procedures, curtail manual data input, and maintain data uniformity across several systems. This integration point empowers the developer to obtain real-time, precise employee data, which can subsequently be used to create robust applications, dashboards, or analytics tools that improve decision-making and workflow within the company.

Merge is a Unified API that facilitates developers in adding several integrations, Paylocity included, with a singular API. This article guides you on how to connect to the Paylocity API to acquire a list of Employees using both the Paylocity API and the Merge HRIS Unified API.

Setting Up Authentication for Paylocity API

When integrating with Paylocity API, one of the first steps you must undertake is configuring your authentication. Paylocity API uses OAuth 2.0 for authentication, specifically the Client Credentials grant type.

To authenticate, you will need to make a request to the token URL, which is <code class="blog_inline-code">https://api.paylocity.com/IdentityServer/connect/token</code>. This request should include your <code class="blog_inline-code">client_id</code>, <code class="blog_inline-code">client_secret</code>, and any other parameters that are required as body parameters.

The header of your request should be formatted in the following way:

"Authorization: Basic {BASE-64}{CLIENT-ID}:{CLIENT-SECRET}{BASE-64}"

After successfully exchanging tokens, you can find the <code class="blog_inline-code">access_token</code> by following the keys in the response. This token is crucial as it is used to authorize all your subsequent requests to the Paylocity API.

The token's lifespan, or how long it is valid, can be found in the <code class="blog_inline-code">expires_in</code> value in the response body. Once your token expires, you can use the <code class="blog_inline-code">refresh_token</code> key in the response to get a new one.

Remember, all requests to the Paylocity API must also include the header field <code class="blog_inline-code">Content-Type: application/x-www-form-urlencoded</code>. This ensures that the server interprets your request correctly.

import requests
import base64
import json

# Step 1: Getting Access Token
token_url = "https://api.paylocity.com/IdentityServer/connect/token"
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
data = {
    "client_id": client_id,
    "client_secret": client_secret,
    "grant_type": "client_credentials",
    "scope": "api"
}

credentials = base64.b64encode(f"{client_id}:{client_secret}".encode("utf-8")).decode("utf-8")
headers = {
    "Authorization": f"Basic {credentials}",
    "Content-Type": "application/x-www-form-urlencoded"
}

response = requests.post(token_url, data=data, headers=headers)
access_token = response.json()['access_token']

# Step 2: Fetching Employees
domain = "YOUR_DOMAIN"
page_number = 0
headers = {
    "Authorization": f"Bearer {access_token}",
    "Content-Type": "application/json"
}

while True:
    employee_url = f"https://api.paylocity.com/api/v2/companies/{domain}/employees?page={page_number}"
    response = requests.get(employee_url, headers=headers)
    employees = response.json()

    if not employees:
        break

    for employee in employees:
        employee_id = employee['employeeId']
        employee_details_url = f"https://api.paylocity.com/api/v2/companies/{domain}/employees/{employee_id}"
        response = requests.get(employee_details_url, headers=headers)
        employee_details = response.json()
        print(employee_details)

    page_number += 1

In the above code, replace <code class='blog_inline-code'>YOUR_CLIENT_ID</code>, <code class='blog_inline-code'>YOUR_CLIENT_SECRET</code>, and <code class='blog_inline-code'>YOUR_DOMAIN</code> with your actual client ID, client secret, and domain.

This code first retrieves an access token using your client credentials. It then uses this token to authenticate the API requests. The employees are fetched page by page, and for each employee, additional details are fetched using their employee ID. The loop continues until there are no more employees to fetch (i.e., the response is empty).

An example of an individual item returned by this API Endpoint is:

{
    "ssn": "123-45-6789",
    "gender": "Male",
    "status": {
        "hireDate": "2021-01-01",
        "statusType": "Full-Time",
        "effectiveDate": "2021-01-01",
        "employeeStatus": "Active",
        "terminationDate": "",
        "isEligibleForRehire": true
    },
    "suffix": "Jr",
    "webTime": {
        "chargeRate": 15,
        "badgeNumber": "A123",
        "isTimeLaborEnabled": true
    },
    "currency": "USD",
    "isSmoker": false,
    "lastName": "Doe",
    "taxSetup": {
        "taxForm": "W-4",
        "suiState": "NY"
    },
    "birthDate": "1990-01-01",
    "ethnicity": "Hispanic",
    "firstName": "John",
    "employeeId": "E123",
    "federalTax": {
        "amount": 100,
        "percentage": 15,
        "w4FormYear": 2021,
        "filingStatus": "Single",
        "taxCalculationCode": "Standard"
    },
    "middleName": "F",
    "salutation": "Mr",
    "companyFEIN": "12-3456789",
    "companyName": "ABC Corp",
    "homeAddress": {
        "city": "New York",
        "phone": "123-456-7890",
        "state": "NY",
        "county": "New York",
        "country": "USA",
        "address1": "123 Main St",
        "address2": "Apt 1",
        "postalCode": "10001",
        "mobilePhone": "123-456-7890",
        "emailAddress": "johndoe@example.com"
    },
    "workAddress": {
        "city": "New York",
        "pager": "",
        "phone": "123-456-7890",
        "state": "NY",
        "country": "USA",
        "address1": "123 Broadway",
        "address2": "",
        "location": "HQ",
        "postalCode": "10001",
        "mobilePhone": "123-456-7890",
        "emailAddress": "johndoe@abccorp.com"
    },
    "maritalStatus": "Single",
    "primaryPayRate": {
        "salary": 50000,
        "payType": "Salary",
        "ratePer": "Year",
        "baseRate": 15,
        "payGrade": "A",
        "isAutoPay": true,
        "annualSalary": 50000,
        "changeReason": "Promotion",
        "defaultHours": 40,
        "payFrequency": "Bi-Weekly",
        "effectiveDate": "2021-01-01",
        "beginCheckDate": "2021-02-01"
    },
    "primaryStateTax": {
        "amount": 50,
        "taxCode": "NY",
        "exemptions": 1,
        "percentage": 5,
        "w4FormYear": 2021,
        "exemptions2": 0,
        "filingStatus": "Single",
        "taxCalculationCode": "Standard"
    },
    "customNumberFields": [
        {
            "label": "custom1",
            "value": 10,
            "category": "custom"
        }
    ],
    "departmentPosition": {
        "jobTitle": "Software Engineer",
        "payGroup": "IT",
        "costCenter1": "IT",
        "costCenter2": "Development",
        "costCenter3": "Web",
        "employeeType": "Full-Time",
        "effectiveDate": "2021-01-01",
        "isOvertimeExempt": true,
        "isMinimumWageExempt": true,
        "isSupervisorReviewer": false,
        "isUnionDuesCollected": false,
        "supervisorEmployeeId": "E124",
        "supervisorCompanyNumber": "1",
        "isUnionInitiationCollected": false
    },
    "customBooleanFields": [
        {
            "label": "custom1",
            "value": true,
            "category": "custom"
        }
    ]
}

Related: Steps for performing API integration in Python

FETCH Employees with Merge HRIS Unified API

The Merge API is a great way to pull normalized HRIS data from a variety of HRIS tools, including Paylocity.

When making requests to the Merge API, you will need to pass proper authentication parameters so that you can identify yourself as an authorized user. You'll need to include a Merge API Key (YOUR_API_KEY) and a Linked Account Token (END_USER_ACCOUNT_TOKEN) for every request you send to the Merge API.

import time
import HRIS
from HRIS.api import employees_api
from pprint import pprint

configuration = HRIS.Configuration()

# Swap YOUR_API_KEY below with your production key from:
# https://app.merge.dev/keys
configuration.api_key['tokenAuth'] = 'YOUR_API_KEY'
configuration.api_key_prefix['tokenAuth'] = 'Bearer'

Once you've authenticated to Merge, you'll next use the API client to make a GET request using the Linked Account Token of the customer whose data you're accessing.

api_client = MergeHRISClient.ApiClient(configuration)

employees_api_instance = employees_api.EmployeesApi(api_client)

x_account_token = 'END_USER_ACCOUNT_TOKEN'
while cursor != None:
    api_response = employees_api_instance.employees_list(x_account_token)
    pprint(api_response)
    cursor = api_response.next

The response you get back from the Merge API will include normalized data for any HRIS integration, including Paylocity. To explore the standard response format, check out the API reference at https://prod.cdn.paylocity.com/developer/index.html#tag/Company-Codes.

{
    "id": "0958cbc6-6040-430a-848e-aafacbadf4ae",
    "remote_id": "19202938",
    "modified_at": "2021-10-16T00:00:00Z",
    "integration_params": {
        "unique_integration_field": "unique_integration_field_value"
    },
    "linked_account_params": {
        "unique_linked_account_field": "unique_linked_account_field_value"
    },
    "field_mappings": {
        "organization_defined_targets": {
            "custom_key": "custom_value"
        },
        "linked_account_defined_targets": {
            "custom_key": "custom_value"
        }
    },
    "employee_number": "2",
    "company": "8d9fd929-436c-4fd4-a48b-0c61f68d6178",
    "first_name": "Greg",
    "last_name": "Hirsch",
    "username": "cousingreg",
    "display_full_name": "Cousin Greg Hirsch",
    "work_email": "greg@merge.dev",
    "personal_email": "greg@gmail.com",
    "mobile_phone_number": "+1234567890",
    "employments": [
        "17a54124-287f-494d-965e-3c5b330c9a68"
    ],
    "home_location": "d2f972d0-2526-434b-9409-4c3b468e08f0",
    "work_location": "9efbc633-3387-4306-aa55-e2c635e6bb4f",
    "manager": "0048ea5b-911e-4dff-9364-92070dea62ff",
    "team": "249c9faa-3045-4a31-953b-8f22d3613301",
    "groups": [
        "21a54124-397f-494d-985e-3c5b330b8a68"
    ],
    "pay_group": "ad1264e2-39be-4787-b749-f1aade9e3405",
    "ssn": "1234567890",
    "gender": "MALE",
    "ethnicity": "WHITE",
    "marital_status": "SINGLE",
    "date_of_birth": "1990-11-10T00:00:00Z",
    "hire_date": "2020-10-10T00:00:00Z",
    "start_date": "2020-10-11T00:00:00Z",
    "remote_created_at": "2020-10-11T00:00:00Z",
    "employment_status": "INACTIVE",
    "termination_date": "2021-10-12T00:00:00Z",
    "avatar": "http://alturl.com/h2h8m"
}

Now that you've accessed data via the Merge HRIS Unified API, you can easily add other integrations on behalf of any of your customers. Check out Merge Link to see how to automate your customers authorizing connections on your behalf and generating Linked Account Tokens.

Leveraging a Unified HRIS API for Efficient Integrations

Suppose you're not well-versed in programming languages such as Python, or perhaps Paylocity is merely one among multiple integrations that you and your team are tasked with developing and managing. This is where a Unified API like Merge steps in.

Merge proposes a solution for HRIS integrations by introducing a single API endpoint that connects to various platforms and services, Paylocity included. This API endpoint serves as a conduit between different platforms, enabling users to communicate with all of them via a single API endpoint.

Merge accomplishes this by utilizing a plugin system that enables it to establish connections to diverse platforms and services. These plugins form a bridge between Merge's API endpoint and the data housed in different HRIS applications. Each plugin is entrusted with managing the distinct communication protocols, APIs, and data structures of the system to which it connects.

When a user sends an API call to Merge, the call is directed to the suitable plugin based on the information given within the call. The plugin then processes the call and delivers the relevant response. This process facilitates users to engage with various systems via a single, Unified API endpoint.

Merge manages these integrations, streamlining authentication with a click-through UI component, and promptly identifying permissioning errors instigated by your customers (such as an incorrect API key). This substantially diminishes the long-term engineering effort associated with an integration product.In this guide, we demonstrated the process of using Python to communicate with the Paylocity API in order to retrieve Employee data.

For those seeking to connect with more than just a single HRIS application, Merge's unified API offers a robust solution. This single API allows you to tap into a multitude of HRIS platforms, Paylocity included, with just one call, thus removing the necessity for multiple separate integrations. This streamlines your integration ecosystem construction process, enabling you to concentrate on enhancing your primary product while simultaneously broadening your potential market.

{{blog-cta-100+}}