Skip to content

jb-tech1999/payspace_sdk

Repository files navigation

PaySpace SDK

A comprehensive Python SDK for interacting with the PaySpace Deel Local Payroll API v2.0. This SDK provides a clean, Pythonic interface to all PaySpace API endpoints, making it easy to integrate payroll operations into your Python applications.

Table of Contents

Features

  • Complete API v2.0 Coverage - Supports all PaySpace API v2.0 endpoints
  • 🔐 OAuth 2.0 Authentication - Secure authentication with client credentials or access tokens
  • 🌍 Multi-Environment Support - Production, Staging, and Development environments
  • 📊 Comprehensive Data Access - Employee info, payroll, leave, benefits, and more
  • 🔍 Lookup Tables - Access to all reference data and lookup values
  • Simple Interface - Clean, intuitive methods for all operations
  • 🐍 Type Hints - Full type hints for better IDE support
  • 📝 Extensive Documentation - Detailed docstrings and examples

Installation

From Source

git clone https://github.com/jb-tech1999/payspace_sdk.git
cd payspace_sdk
pip install -e .

Requirements

  • Python 3.7+
  • requests

Quick Start

from payspace_sdk import PaySpaceClient, PaySpaceEnvironment

# Initialize the client with your credentials
client = PaySpaceClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    environment=PaySpaceEnvironment.PRODUCTION
)

# Authenticate
client.authenticate()

# Get available companies
companies = client.get_companies()
print(f"Found {len(companies)} companies")

# Get employee data
company_id = companies[0]['CompanyId']
employees = client.get_biographical(company_id, 2024, 1, 1)
print(f"Found {len(employees)} employees")

Authentication

The SDK supports two authentication methods:

1. Client Credentials (Recommended)

client = PaySpaceClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    environment=PaySpaceEnvironment.PRODUCTION
)

# Authenticate and get access token
token = client.authenticate()

# Get available companies (returned during authentication)
companies = client.get_available_companies()

# Or fetch companies via API
companies = client.get_companies()

2. Pre-existing Access Token

client = PaySpaceClient(
    access_token="your_existing_token",
    environment=PaySpaceEnvironment.PRODUCTION
)

# No need to authenticate, token is already set
companies = client.get_companies()

Environments

The SDK supports three environments:

Environment URL Auth URL Rate Limit
Production https://api.payspace.com/odata/v2.0 https://identity.yourhcm.com/connect/token 2000 req/min
Staging https://apistaging.payspace.com/odata/v2.0 https://staging-identity.yourhcm.com/connect/token 200 req/min
Development https://localhost:44393/odata/v2.0 https://localhost:44392/connect/token No limit

Using Different Environments

from payspace_sdk import PaySpaceClient, PaySpaceEnvironment

# Production (default)
prod_client = PaySpaceClient(
    client_id="id",
    client_secret="secret",
    environment=PaySpaceEnvironment.PRODUCTION
)

# Staging
staging_client = PaySpaceClient(
    client_id="id",
    client_secret="secret",
    environment=PaySpaceEnvironment.STAGING
)

# Development
dev_client = PaySpaceClient(
    client_id="id",
    client_secret="secret",
    environment=PaySpaceEnvironment.DEVELOPMENT
)

# Custom environment
custom_client = PaySpaceClient(
    client_id="id",
    client_secret="secret",
    environment="https://custom-api.example.com/odata/v2.0",
    auth_url="https://custom-auth.example.com/connect/token"
)

API Coverage

The SDK provides comprehensive coverage of the PaySpace API v2.0:

Company Information

  • get_companies() - Get all companies
  • get_company_names() - Get company names
  • get_company_frequency() - Get pay frequencies
  • get_company_runs() - Get payroll runs
  • get_company_training_courses() - Get training courses
  • get_company_custom_forms() - Get custom forms
  • get_company_review_process() - Get review processes
  • get_organization_units() - Get organization units
  • get_currency_exchange_rates() - Get exchange rates

Employee Information

  • get_biographical() - Get employee biographical data
  • get_biographical_including_terminated() - Include terminated employees
  • get_employee_addresses() - Get employee addresses
  • get_employee_bank_details() - Get bank account details
  • get_employee_dependants() - Get dependant information
  • get_employee_positions() - Get position details
  • get_employee_attachments() - Get employee documents
  • get_employee_skills() - Get employee skills
  • get_employee_qualifications() - Get qualifications
  • get_employee_suspension() - Get suspension records

Payroll & Compensation

  • get_payslips() - Get employee payslips
  • get_payslip_lines() - Get detailed payslip lines
  • get_costed_payslip_lines() - Get costed payslip lines
  • get_pay_rate_details() - Get pay rate information
  • get_financial_transactions() - Get financial transactions
  • get_recurring_costing_split() - Get recurring costs

Leave Management

  • get_leave_applications() - Get leave applications
  • get_leave_adjustments() - Get leave adjustments
  • get_payslip_leave_balances() - Get leave balances

Benefits & Deductions

  • get_employee_medical() - Medical aid information
  • get_employee_pension_fund() - Pension fund details
  • get_employee_disability() - Disability insurance
  • get_employee_group_life() - Group life insurance
  • get_employee_income_protection() - Income protection
  • get_employee_retirement_annuity() - Retirement annuities
  • get_employee_garnishee() - Garnishee orders
  • get_employee_loan() - Employee loans
  • get_employee_saving() - Savings schemes
  • get_employee_union() - Union membership
  • get_employee_company_car_detail() - Company car details
  • get_employee_bonus_provision() - Bonus provisions

Components & Custom Data

  • get_employee_component() - Get employee components
  • get_employee_component_values() - Get component values
  • get_employee_custom_forms() - Get custom form data

Training & Development

  • get_employee_training() - Get training records
  • get_employee_incidents() - Get incident records

Performance Management

  • get_employee_review_template() - Get review templates
  • get_employee_review_header() - Get review headers
  • get_employee_review_kpa() - Get KPA reviews

Projects & Costing

  • get_employee_project() - Get project assignments

Tax Information

  • get_tax_profile() - Get tax profile information

Lookup Tables (60+ lookup endpoints)

The SDK provides access to all lookup/reference data tables:

# Examples of lookup methods
client.get_account_type_lookup(company_id)
client.get_address_country_lookup(company_id)
client.get_citizenship_lookup(company_id)
client.get_classification_lookup(company_id)
client.get_currency_lookup(company_id)
client.get_employment_category_lookup(company_id)
client.get_job_lookup(company_id)
client.get_marital_status_lookup(company_id)
# ... and 50+ more lookup methods

Usage Examples

Example 1: Get Employee Payslips for Current Month

from payspace_sdk import PaySpaceClient, PaySpaceAPIHelper

client = PaySpaceClient(
    client_id="your_client_id",
    client_secret="your_client_secret"
)

client.authenticate()
companies = client.get_companies()
company_id = companies[0]['CompanyId']

# Get current period
year, month = PaySpaceAPIHelper.get_current_period()

# Fetch payslips
payslips = client.get_payslips(company_id, year, month)

for payslip in payslips:
    print(f"Employee: {payslip['EmployeeNumber']}")
    print(f"Net Pay: {payslip['NetPay']}")
    print(f"Period: {payslip['Period']}")
    print("---")

Example 2: Get Employee Details with Address

# Get biographical data
year, month, day = PaySpaceAPIHelper.get_current_date()
employees = client.get_biographical(company_id, year, month, day)

# Get addresses
addresses = client.get_employee_addresses(company_id, year, month, day)

# Combine data
for employee in employees:
    emp_number = employee['EmployeeNumber']
    emp_addresses = [a for a in addresses if a['EmployeeNumber'] == emp_number]
    
    print(f"Employee: {employee['FirstName']} {employee['LastName']}")
    print(f"Number: {emp_number}")
    for addr in emp_addresses:
        print(f"Address: {addr.get('AddressLine1', '')}")
    print("---")

Example 3: Search for Specific Company

# Search by company name
companies = client.get_companies(company_search="Acme Corp")

if companies:
    company = companies[0]
    print(f"Found: {company['CompanyName']}")
    print(f"ID: {company['CompanyId']}")
    print(f"Group: {company['CompanyGroup']}")

Example 4: Get Leave Applications for Date Range

from datetime import date

start_date = date(2024, 1, 1)
end_date = date(2024, 1, 31)

leave_apps = client.get_leave_applications(
    company_id=company_id,
    year=2024,
    month=1,
    start_date=start_date,
    end_date=end_date
)

for leave in leave_apps:
    print(f"Employee: {leave['EmployeeNumber']}")
    print(f"Type: {leave['LeaveType']}")
    print(f"Days: {leave['Days']}")
    print(f"Status: {leave['Status']}")
    print("---")

Example 5: Get Payroll Runs for a Frequency

# Get company frequencies first
frequencies = client.get_company_frequency(company_id)

for freq in frequencies:
    print(f"Frequency: {freq['Frequency']}")
    
    # Get runs for this frequency
    runs = client.get_company_runs(company_id, freq['Frequency'])
    
    for run in runs:
        print(f"  Period: {run['Period']}")
        print(f"  Start: {run['PeriodStartDate']}")
        print(f"  End: {run['PeriodEndDate']}")

Example 6: Using Lookup Tables

# Get employment categories
categories = client.get_employment_category_lookup(company_id)
for cat in categories:
    print(f"{cat['Code']}: {cat['Description']}")

# Get job titles
jobs = client.get_job_lookup(company_id)
for job in jobs:
    print(f"{job['Code']}: {job['Description']}")

# Get currencies
currencies = client.get_currency_lookup(company_id)
for curr in currencies:
    print(f"{curr['Code']}: {curr['Description']}")

Example 7: Working with Benefits

# Get pension fund details
pension = client.get_employee_pension_fund(
    company_id=company_id,
    frequency="Monthly",
    period="2024-01"
)

for record in pension:
    print(f"Employee: {record['EmployeeNumber']}")
    print(f"Fund: {record['PensionFund']}")
    print(f"Employee Contribution: {record['EmployeeContribution']}")
    print(f"Employer Contribution: {record['EmployerContribution']}")
    print("---")

# Get medical aid details
medical = client.get_employee_medical(
    company_id=company_id,
    frequency="Monthly",
    period="2024-01"
)

API Reference

PaySpaceClient Class

The main client class for interacting with the PaySpace API.

Constructor

PaySpaceClient(
    client_id: Optional[str] = None,
    client_secret: Optional[str] = None,
    access_token: Optional[str] = None,
    environment: str = PaySpaceEnvironment.PRODUCTION,
    auth_url: Optional[str] = None
)

Parameters:

  • client_id - OAuth client ID
  • client_secret - OAuth client secret
  • access_token - Pre-existing OAuth 2.0 access token (optional)
  • environment - API environment URL
  • auth_url - Authentication URL (auto-configured based on environment)

Authentication Methods

authenticate() -> str

Authenticate with the API and retrieve an access token.

Returns: Access token string

Raises: ValueError if client_id/client_secret not provided

get_available_companies() -> List[Dict]

Get the list of companies available to the authenticated user.

Returns: List of company dictionaries

PaySpaceAPIHelper Class

Helper class with utility methods.

Static Methods

get_current_period() -> tuple

Get the current year and month.

Returns: Tuple of (year, month)

get_current_date() -> tuple

Get the current year, month, and day.

Returns: Tuple of (year, month, day)

format_date(dt: Union[date, datetime]) -> str

Format a date for API queries (yyyy-MM-dd format).

Parameters:

  • dt - Date or datetime object

Returns: Formatted date string

Rate Limits

PaySpace API v2.0 enforces the following rate limits:

  • Production: 2000 requests per minute
  • Staging: 200 requests per minute
  • Development: No enforced limit

When rate limits are exceeded, the API returns a 429 status code. Implement appropriate retry logic with exponential backoff when needed.

Error Handling

The SDK raises exceptions for various error conditions:

from requests.exceptions import HTTPError

try:
    client = PaySpaceClient(client_id="id", client_secret="secret")
    client.authenticate()
    companies = client.get_companies()
except ValueError as e:
    print(f"Configuration error: {e}")
except HTTPError as e:
    if e.response.status_code == 401:
        print("Authentication failed - check credentials")
    elif e.response.status_code == 429:
        print("Rate limit exceeded - wait and retry")
    elif e.response.status_code == 404:
        print("Resource not found")
    else:
        print(f"HTTP error: {e}")
except Exception as e:
    print(f"Unexpected error: {e}")

Common Error Codes

  • 400 Bad Request - Invalid parameters or malformed request
  • 401 Unauthorized - Invalid or expired access token
  • 403 Forbidden - Insufficient permissions
  • 404 Not Found - Resource does not exist
  • 429 Too Many Requests - Rate limit exceeded
  • 500 Internal Server Error - Server-side error

API v2.0 Breaking Changes

If you're migrating from v1.0, note these changes:

  1. Lookup Endpoints: All lookup endpoints now require the /Lookup/ prefix
  2. Date Format: Dates must be in yyyy-MM-dd format for Edm.Date types
  3. OData Version: Requires OData 4.0 headers
  4. Rate Limits: Different limits for production (2000/min) vs staging (200/min)

Best Practices

1. Reuse Client Instances

# Good - reuse the same client
client = PaySpaceClient(client_id="id", client_secret="secret")
client.authenticate()

companies = client.get_companies()
for company in companies:
    employees = client.get_biographical(company['CompanyId'], 2024, 1, 1)

2. Use Environment Variables

import os

client = PaySpaceClient(
    client_id=os.getenv("PAYSPACE_CLIENT_ID"),
    client_secret=os.getenv("PAYSPACE_CLIENT_SECRET"),
    environment=os.getenv("PAYSPACE_ENV", PaySpaceEnvironment.PRODUCTION)
)

3. Handle Pagination for Large Datasets

# Some endpoints return large datasets
# The API uses OData pagination with @odata.nextLink
def get_all_employees(client, company_id):
    employees = []
    response = client.get_biographical(company_id, 2024, 1, 1)
    employees.extend(response)
    
    # Note: Current SDK returns 'value' list
    # If you need to handle nextLink, you may need to access raw response
    return employees

4. Cache Lookup Data

# Lookup data rarely changes - cache it
lookup_cache = {}

def get_cached_lookup(client, company_id, lookup_name):
    """
    Cache lookup data to avoid repeated API calls.
    lookup_name should be like 'currency', 'job', 'marital_status', etc.
    """
    cache_key = f"{company_id}_{lookup_name}"
    if cache_key not in lookup_cache:
        try:
            method = getattr(client, f"get_{lookup_name}_lookup")
            lookup_cache[cache_key] = method(company_id)
        except AttributeError:
            raise ValueError(f"Unknown lookup type: {lookup_name}")
    return lookup_cache[cache_key]

# Usage example
currencies = get_cached_lookup(client, company_id, "currency")
jobs = get_cached_lookup(client, company_id, "job")

Troubleshooting

Authentication Issues

Problem: ValueError: client_id and client_secret are required

Solution: Ensure you provide both client_id and client_secret when initializing the client.

Problem: 401 Unauthorized error

Solution:

  • Verify your credentials are correct
  • Check that you're using the right environment
  • Ensure your token hasn't expired (get a new one with authenticate())

Connection Issues

Problem: Connection timeout or refused

Solution:

  • For Development environment, ensure the local API is running
  • Check your network connection
  • Verify the environment URL is correct

Data Not Found

Problem: Empty results when you expect data

Solution:

  • Verify the company_id is correct
  • Check the date parameters (year, month, day)
  • Ensure the company has data for the requested period
  • Verify the frequency matches the company's pay frequency

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Development Setup

git clone https://github.com/jb-tech1999/payspace_sdk.git
cd payspace_sdk
pip install -e .

License

This project is open source. Please check the repository for license details.

Support

For issues, questions, or contributions, please visit:

Disclaimer

This SDK is provided as-is. Always test thoroughly in a staging environment before using in production. Ensure you comply with PaySpace's terms of service and API usage guidelines.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors