Python SDK

Official Python SDK for Apploi’s Partner API can be found at https://pypi.org/project/apploi-partner-api/

Overview

A production-ready Python client for the Apploi Partner API. It provides native Python types via dataclasses, input validation before requests, pagination utilities, and structured exceptions for reliable, testable integrations.

  • Use when building Python services or scripts that integrate with Apploi to read or sync applicants, jobs, and related entities.
  • Wraps the generated SDK with a higher-level, safer API and sensible defaults.

Installation

pip install apploi-partner-api

Quick Start

from apploi_partner_api import ApploiClient
from datetime import date

# Initialize client
client = ApploiClient(api_key="your-api-key")

# Get job applications with native Python types
job_applications = client.get_job_applications(
    job_id=12345,
    updated_after=date(2024, 1, 1),
    limit=50
)

# Work with strongly-typed results
for application in job_applications:
    print(f"{application.candidate.name} - {application.status.value}")
    print(f"  Email: {application.email}")
    print(f"  Applied: {application.applied_at}")
    print(f"  Job: {application.job.name}")

Key Features

🎯 Simple Integration

  • Single pip install - no complex setup required
  • Works with Python 3.7+ across all major platforms
  • Minimal dependencies for easy deployment

🔧 Native Python Experience

  • Use native Python types: int, date, datetime, bool
  • Automatic type conversion and validation
  • Pythonic method names and parameter handling
  • No need to manually format dates or convert integers to strings

🛡️ Robust Error Handling

  • Custom exception hierarchy for different error types
  • Descriptive error messages with actionable guidance
  • Automatic retry logic for transient network issues
  • Proper handling of rate limits and API quotas

📊 Rich Data Models

  • Structured dataclasses with full type annotations
  • Nested models for complex data (Job, Candidate, Application)
  • Convenient properties for common operations
  • Access to both processed and raw API response data

🚀 Production Ready

  • Comprehensive test coverage and validation
  • Built-in pagination for large datasets
  • Configurable timeouts and connection settings
  • Thread-safe for concurrent usage

API Reference

Client Initialization

from adapters.python import ApploiClient

client = ApploiClient(
    api_key="your-api-key",        # Required
    authorization="your-auth",      # Required
    base_url=None,                  # Optional, defaults to production
    timeout=60                      # Optional, request timeout in seconds
)

get_job_applications()

Retrieve job applications with filtering and pagination.

applicants = client.get_job_applications(
    state="applied",                          # Filter by status
    query="engineer",                         # Search query
    limit=50,                                 # Max results (1-1000)
    team_id=123,                             # Team ID (int or str)
    updated_before=datetime.now(),           # Before date
    offset=0,                                # Pagination offset
    job_id=456,                              # Job ID (int or str)
    updated_after=date(2024, 1, 1)          # After date
)

Parameters:

  • All parameters are optional
  • IDs accept int or str
  • Dates accept date, datetime, or ISO string
  • Limit must be 1-1000
  • Offset must be ≥ 0

Returns: ApplicantsList with:

  • items: List of JobApplication objects
  • total: Total count available
  • limit: Page size
  • offset: Current offset
  • has_more: Boolean for more pages

Domain Models

JobApplication

@dataclass
class JobApplication:
    # Identifiers
    id: int                              # Application ID
    candidate_id: int                    # Candidate ID
    job_id: int                          # Job ID
    
    # Required fields
    status: ApplicationStatus            # Application status
    job: Job                             # Job details (nested)
    candidate: Candidate                 # Candidate details (nested)
    email: str                           # Applicant email
    applicant_state: str                 # Current state
    applicant_state_id: int              # State ID
    
    # DateTime/State Management
    date_current_state_assigned: Optional[datetime]
    previous_applicant_state: Optional[str]
    previous_applicant_state_id: Optional[int]
    date_previous_state_assigned: Optional[datetime]
    applicant_updated: Optional[datetime]
    date_created: Optional[datetime]
    application_source: Optional[str]
    
    # Optional fields
    first_name: Optional[str]
    last_name: Optional[str]
    phone: Optional[str]
    applied_at: Optional[datetime]
    updated_at: Optional[datetime]
    team_id: Optional[int]

    @property
    def name(self) -> str:
        """Full name (first + last)"""

Job

@dataclass  
class Job:
    id: Optional[int]
    name: Optional[str]               # Job title
    archived: Optional[bool]          # Is archived
    archived_date: Optional[datetime]
    address: Optional[str]            # Job location
    source: Optional[str]             # Job source
    brand_name: Optional[str]         # Company brand
    job_code: Optional[str]           # Internal job code
    creator_id: Optional[int]         # Creator ID
    team_id: Optional[int]            # Team ID
    team_name: Optional[str]          # Team name
    role_type: Optional[str]          # Role type
    longitude: Optional[float]        # Geo coordinates
    latitude: Optional[float]

Candidate

@dataclass
class Candidate:
id: int                           # Candidate ID
first_name: Optional[str]
last_name: Optional[str]
email: Optional[str]
home_phone_number: Optional[str]
mobile_phone_number: Optional[str]
city: Optional[str]
state: Optional[str]
country: Optional[str]
address: Optional[str]
zip_code: Optional[str]

@property
def name(self) -> str:
"""Full name (first + last)"""

@property
def phone(self) -> Optional[str]:
"""Primary phone (mobile or home)"""

ApplicationStatus

class ApplicationStatus(Enum):
    APPLIED = "applied"
    SCREENING = "screening"
    INTERVIEWING = "interviewing"
    REFERENCE_CHECK = "reference_check"
    OFFER_EXTENDED = "offer_extended"
    HIRED = "hired"
    REJECTED = "rejected"
    WITHDRAWN = "withdrawn"
    ON_HOLD = "on_hold"
    UNKNOWN = "unknown"  # Fallback for unrecognized values

Note: The enum supports legacy values "interview" and "offer" for backwards compatibility, automatically mapping them to INTERVIEWING and OFFER_EXTENDED respectively.

Error Handling

from apploi_partner_api import (
    ApploiValidationError,
    ApploiAuthenticationError,
    ApploiAPIError
)

try:
    job_applications = client.get_job_applications(limit=50)

except ApploiValidationError as e:
    # Invalid parameters (e.g., limit > 1000)
    print(f"Validation error: {e}")

except ApploiAuthenticationError as e:
    # 401/403 errors
    print(f"Auth failed: {e}")

except ApploiAPIError as e:
    # Other API errors
    print(f"API error: {e}")
    if e.status_code == 429:
        # Handle rate limiting
        time.sleep(60)

Usage Examples

Basic Usage

# Get all job applications
all_job_applications = client.get_job_applications()
print(f"Found {len(all_job_applications)} job applications")

Filtering

# Filter with native types
filtered_job_applications = client.get_job_applications(
    job_id=12345,                         # Integer
    team_id=789,                          # Integer
    updated_after=date(2024, 1, 1),       # Date object
    state="applied",                      # String
    limit=50                              # Integer
)

Pagination

# Paginate through all results
all_results = []
offset = 0
page_size = 50

while True:
    page = client.get_job_applications(
        limit=page_size,
        offset=offset
    )

    all_results.extend(page.items)

    if not page.has_more:
        break

    offset += page_size

print(f"Total fetched: {len(all_results)}")

Working with Results

job_applications = client.get_job_applications(limit=1)

if job_applications:
    application = job_applications[0]

    # Strongly typed fields
    print(f"ID: {application.id}")
    print(f"Name: {application.candidate.name}")
    print(f"Status: {application.status.value}")

    # Date handling
    if application.applied_at:
        days_ago = (datetime.now() - application.applied_at).days
        print(f"Applied {days_ago} days ago")

    # Access raw data if needed
    raw = application.raw_data

Testing

# Run all tests
pytest tests/

# Run specific test file
pytest tests/test_client.py -v

# Run with coverage
pytest tests/ --cov=adapters.python

# Integration tests (requires credentials)
export APPLOI_API_KEY="your-key"
export APPLOI_AUTHORIZATION="your-auth"
pytest tests/integration/ -m integration

Requirements

  • Python 3.7+
  • httpx (for Fern SDK)
  • python-dateutil (optional, for date parsing)

What’s Next