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.
- Features
- Installation
- Quick Start
- Authentication
- Environments
- API Coverage
- Usage Examples
- API Reference
- Rate Limits
- Error Handling
- Contributing
- License
- ✅ 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
git clone https://github.com/jb-tech1999/payspace_sdk.git
cd payspace_sdk
pip install -e .- Python 3.7+
- requests
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")The SDK supports two authentication methods:
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()client = PaySpaceClient(
access_token="your_existing_token",
environment=PaySpaceEnvironment.PRODUCTION
)
# No need to authenticate, token is already set
companies = client.get_companies()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 |
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"
)The SDK provides comprehensive coverage of the PaySpace API v2.0:
get_companies()- Get all companiesget_company_names()- Get company namesget_company_frequency()- Get pay frequenciesget_company_runs()- Get payroll runsget_company_training_courses()- Get training coursesget_company_custom_forms()- Get custom formsget_company_review_process()- Get review processesget_organization_units()- Get organization unitsget_currency_exchange_rates()- Get exchange rates
get_biographical()- Get employee biographical dataget_biographical_including_terminated()- Include terminated employeesget_employee_addresses()- Get employee addressesget_employee_bank_details()- Get bank account detailsget_employee_dependants()- Get dependant informationget_employee_positions()- Get position detailsget_employee_attachments()- Get employee documentsget_employee_skills()- Get employee skillsget_employee_qualifications()- Get qualificationsget_employee_suspension()- Get suspension records
get_payslips()- Get employee payslipsget_payslip_lines()- Get detailed payslip linesget_costed_payslip_lines()- Get costed payslip linesget_pay_rate_details()- Get pay rate informationget_financial_transactions()- Get financial transactionsget_recurring_costing_split()- Get recurring costs
get_leave_applications()- Get leave applicationsget_leave_adjustments()- Get leave adjustmentsget_payslip_leave_balances()- Get leave balances
get_employee_medical()- Medical aid informationget_employee_pension_fund()- Pension fund detailsget_employee_disability()- Disability insuranceget_employee_group_life()- Group life insuranceget_employee_income_protection()- Income protectionget_employee_retirement_annuity()- Retirement annuitiesget_employee_garnishee()- Garnishee ordersget_employee_loan()- Employee loansget_employee_saving()- Savings schemesget_employee_union()- Union membershipget_employee_company_car_detail()- Company car detailsget_employee_bonus_provision()- Bonus provisions
get_employee_component()- Get employee componentsget_employee_component_values()- Get component valuesget_employee_custom_forms()- Get custom form data
get_employee_training()- Get training recordsget_employee_incidents()- Get incident records
get_employee_review_template()- Get review templatesget_employee_review_header()- Get review headersget_employee_review_kpa()- Get KPA reviews
get_employee_project()- Get project assignments
get_tax_profile()- Get tax profile information
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 methodsfrom 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("---")# 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("---")# 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']}")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("---")# 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']}")# 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']}")# 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"
)The main client class for interacting with the PaySpace API.
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 IDclient_secret- OAuth client secretaccess_token- Pre-existing OAuth 2.0 access token (optional)environment- API environment URLauth_url- Authentication URL (auto-configured based on environment)
Authenticate with the API and retrieve an access token.
Returns: Access token string
Raises: ValueError if client_id/client_secret not provided
Get the list of companies available to the authenticated user.
Returns: List of company dictionaries
Helper class with utility methods.
Get the current year and month.
Returns: Tuple of (year, month)
Get the current year, month, and day.
Returns: Tuple of (year, month, day)
Format a date for API queries (yyyy-MM-dd format).
Parameters:
dt- Date or datetime object
Returns: Formatted date string
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.
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}")- 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
If you're migrating from v1.0, note these changes:
- Lookup Endpoints: All lookup endpoints now require the
/Lookup/prefix - Date Format: Dates must be in
yyyy-MM-ddformat for Edm.Date types - OData Version: Requires OData 4.0 headers
- Rate Limits: Different limits for production (2000/min) vs staging (200/min)
# 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)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)
)# 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# 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")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())
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
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
Contributions are welcome! Please feel free to submit issues or pull requests.
git clone https://github.com/jb-tech1999/payspace_sdk.git
cd payspace_sdk
pip install -e .This project is open source. Please check the repository for license details.
For issues, questions, or contributions, please visit:
- GitHub: https://github.com/jb-tech1999/payspace_sdk
- Issues: https://github.com/jb-tech1999/payspace_sdk/issues
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.