Skip to main content

Official Python client for Apploi Partner API with high-level abstractions

Project description

Python Adapter for Apploi Partner API

A clean, type-safe Python adapter that wraps the Fern-generated SDK with better abstractions, validation, and error handling.

Installation

# Install dependencies
pip install httpx python-dateutil

# Or install all requirements
pip install -r requirements.txt

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.name} - {application.status.value}")
    print(f"  Email: {application.email}")
    print(f"  Applied: {application.applied_at}")

💡 See example_usage.py for comprehensive usage examples including pagination, error handling, and comparisons with the raw SDK.

Features

  • Native Python Types: Use int, date, datetime instead of strings
  • Type Safety: Dataclasses with proper type hints
  • Validation: Parameters validated before API calls
  • Error Handling: Custom exception hierarchy
  • IDE Support: Full autocomplete and type checking

API Reference

Client Initialization

from apploi_partner_api import ApploiClient

client = ApploiClient(
    api_key="your-api-key",        # 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.

job_applications = client.get_job_applications(
    state="applied",                          # Filter by status
    query="Smith",                            # Search query filters by name, phone number, or email
    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: JobApplicationsList 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=apploi_partner_api

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

Project Structure

python/
├── __init__.py              # Package initialization
├── client.py                # Main ApploiClient class
├── exceptions.py            # Custom exceptions
├── models/
│   ├── __init__.py
│   ├── job_application.py  # JobApplication, JobApplicationsList
│   └── common.py           # Shared models
├── validators/
│   ├── __init__.py
│   ├── dates.py            # Date validation/parsing
│   └── parameters.py       # Parameter validation
├── example_usage.py        # Usage examples
├── requirements.txt        # Dependencies
└── README.md              # This file

Requirements

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

Differences from Raw SDK

Without Adapter (Fern SDK)

# Everything must be strings
sdk.applicants.get_applicants(
    job_id="12345",
    limit="50",
    updated_after="2024-01-01"
)  # Returns: Dict[str, Any]

With Adapter

# Native Python types
client.get_job_applications(
    job_id=12345,
    limit=50,
    updated_after=date(2024, 1, 1)
)  # Returns: ApplicantsList (typed)

Architecture

See ARCHITECTURE.md for detailed design documentation.

Contributing

  1. Follow existing patterns
  2. Add tests for new features
  3. Update type hints
  4. Run tests before submitting

License

[Your License Here]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apploi_partner_api-0.1.7.tar.gz (5.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apploi_partner_api-0.1.7-py3-none-any.whl (31.4 kB view details)

Uploaded Python 3

File details

Details for the file apploi_partner_api-0.1.7.tar.gz.

File metadata

  • Download URL: apploi_partner_api-0.1.7.tar.gz
  • Upload date:
  • Size: 5.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.3

File hashes

Hashes for apploi_partner_api-0.1.7.tar.gz
Algorithm Hash digest
SHA256 c33f25af5bcd9eb576d9a12410001bec8d8fbdee88dae85e8267e87110443d67
MD5 6aa218af2d3ce2f9e05283769868f0bb
BLAKE2b-256 9e89dbad1a1e9fdb94dd7e6d9228ba5aa8d1087568e8cd3e560b21d10eec7e55

See more details on using hashes here.

File details

Details for the file apploi_partner_api-0.1.7-py3-none-any.whl.

File metadata

File hashes

Hashes for apploi_partner_api-0.1.7-py3-none-any.whl
Algorithm Hash digest
SHA256 78e3bb6b13fdf71cd0a19f4606ac39e55aa9cffa5dcdf574d06266dd052c60d3
MD5 583a271ac1475bbea6737fde572d6fdc
BLAKE2b-256 96ee38ed683d5314210082ff000bbb37582f8470c5f82877918a7149601dbc7a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page