Skip to main content

Python SDK for the Ophelos API

Project description

Ophelos Python SDK

Python SDK for the Ophelos API - a comprehensive debt management and customer communication platform.

Installation

From PyPI (when published)

pip install ophelos-sdk

From Local Distribution

# Install from wheel (recommended)
pip install dist/ophelos_sdk-1.4.0-py3-none-any.whl

# Or install from source distribution
pip install dist/ophelos-sdk-1.4.0.tar.gz

# Or install in development mode
pip install -e .

Requirements Files

The project includes separate requirements files:

  • requirements.txt - Runtime dependencies only (for end users)
  • requirements-dev.txt - Development dependencies only
  • pyproject.toml - Complete dependency specification (recommended)
# For end users (runtime only)
pip install -r requirements.txt

# For developers (includes testing, linting, formatting tools)
pip install -r requirements-dev.txt

# Or install everything via pyproject.toml (recommended)
pip install -e ".[dev]"

Quick Start

from ophelos_sdk import OphelosClient
from ophelos_sdk.models import Customer, Debt

# Initialize client with your credentials
client = OphelosClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    audience="your_audience",
    environment="staging",  # or "production"
    version="2025-04-01"  # API version (default: "2025-04-01")
)

# Option 1: Create using dictionaries (traditional approach)
customer = client.customers.create({
    "first_name": "John",
    "last_name": "Doe",
    "contact_details": [
        {"type": "email", "value": "john.doe@example.com", "primary": True}
    ]
})

# Option 2: Create using model instances (new approach)
from ophelos_sdk.models import Customer, ContactDetail

customer_model = Customer(
    id="temp_cust_123",  # Temporary ID
    first_name="Jane",
    last_name="Smith",
    contact_details=[
        ContactDetail(
            id="temp_cd_123",
            type="email",
            value="jane.smith@example.com",
            primary=True
        )
    ]
)

# Pass model directly to API - automatic conversion to API body
customer = client.customers.create(customer_model)

# Create a debt using model instance
debt_model = Debt(
    id="temp_debt_123",
    customer=customer.id,  # Use real customer ID
    organisation="org_123",
    currency="GBP",
    account_number="ACC-001",
    kind="purchased"
)

debt = client.debts.create(debt_model)

# Prepare the debt for processing
client.debts.ready(debt.id)

📋 For comprehensive usage examples and advanced features, see USAGE.md

Key Features

  • Complete API Coverage: All Ophelos API endpoints with comprehensive test coverage
  • Type Safety: Full type hints and Pydantic models with automatic API body generation
  • Model-First Approach: Create and pass Pydantic model instances directly to API calls
  • Request/Response Transparency: Access complete HTTP request and response details from any model instance
  • Smart Field Management: Automatic exclusion of server-generated fields and intelligent relationship handling
  • Comprehensive Error Handling: Full debugging context for all error types (API, timeout, parsing, unexpected)
  • Authentication: Automatic OAuth2 token management with thread-safe token caching
  • Multi-Tenant Support: Automatic tenant header injection
  • Pagination: Built-in pagination support with generators for memory-efficient iteration
  • Webhooks: Webhook event handling and validation with signature verification
  • Concurrent Safe: Thread-safe for use with concurrent request patterns

Request/Response Transparency

Every model instance returned by the SDK includes complete HTTP request and response details:

# Get a customer
customer = client.customers.get('cust_123')

# Access request details
print(customer.request_info)
# Output: {
#   'method': 'GET',
#   'url': 'https://api.ophelos.com/customers/cust_123',
#   'headers': {'Authorization': 'Bearer ...', 'Ophelos-Version': '2025-04-01'},
#   'body': None
# }

# Access response details
print(customer.response_info)
# Output: {
#   'status_code': 200,
#   'headers': {'Content-Type': 'application/json', ...},
#   'url': 'https://api.ophelos.com/customers/cust_123'
# }

# Access raw response object for advanced use cases
response = customer.response_raw
print(f"Response took: {response.elapsed.total_seconds()} seconds")
print(f"Server: {response.headers.get('Server')}")

# Works with all operations - create, update, list, search
debts = client.debts.list(limit=10)
for debt in debts.data:
    print(f"Debt {debt.id} response time: {debt.response_raw.elapsed}")

# Also works with paginated responses
print(f"List request: {debts.request_info}")
print(f"List response status: {debts.response_info['status_code']}")

This transparency enables:

  • Request debugging: See exactly what was sent to the API (works for errors too)
  • Response monitoring: Track response times, status codes, headers
  • Error diagnosis: Full request context available even for timeouts and failures
  • Audit trails: Log complete request/response details for compliance
  • Performance analysis: Monitor API response times and patterns

Model-First API Usage

The SDK supports both traditional dictionary-based API calls and a modern model-first approach:

from ophelos_sdk.models import Customer, Debt, ContactDetail

# Create models with type safety and validation
customer = Customer(
    id="temp_123",  # Temporary ID for creation
    first_name="John",
    last_name="Doe",
    contact_details=[
        ContactDetail(
            id="temp_cd_1",
            type="email",
            value="john@example.com",
            primary=True
        )
    ]
)

# Pass model directly to API - automatic conversion
created_customer = client.customers.create(customer)

# Smart API body generation - automatically excludes server-generated fields
api_body = customer.to_api_body()
print(api_body)
# Output: {
#   "first_name": "John",
#   "last_name": "Doe",
#   "contact_details": [
#     {"type": "email", "value": "john@example.com", "primary": True}
#   ]
# }
# Note: id, object, created_at, updated_at are automatically excluded

Authentication

Option 1: OAuth2 Client Credentials (Recommended)

# OAuth2 authentication (automatic token management)
client = OphelosClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    audience="your_audience",
    environment="production",  # "development", "staging", or "production"
    version="2025-04-01"  # API version (default: "2025-04-01")
)

Option 2: Direct Access Token

# Direct access token authentication
client = OphelosClient(
    access_token="your_access_token",
    version="2025-04-01"
)

Multi-Tenant Support

# Initialize client with tenant ID
client = OphelosClient(
    client_id="your_client_id",
    client_secret="your_client_secret",
    audience="your_audience",
    environment="production",
    tenant_id="tenant_123"  # Automatically adds OPHELOS_TENANT_ID header
)

Contact Ophelos support to obtain credentials.

Examples

Working with Debts

from ophelos_sdk.models import Debt

# List debts with pagination
debts = client.debts.list(limit=10, expand=["customer"])

# Access request/response details
print(f"Request URL: {debts.request_info['url']}")
print(f"Response time: {debts.response_raw.elapsed.total_seconds()}s")

# Search debts
results = client.debts.search("status:paying AND updated_at>=2024-01-01")

# Get debt details
debt = client.debts.get("debt_123", expand=["customer", "payments"])

# Create using model instance
debt_model = Debt(
    id="temp_debt",
    customer="cust_123",
    organisation="org_123",
    currency="GBP",
    account_number="ACC-001",
    kind="purchased"
)

created_debt = client.debts.create(debt_model)

# Access creation request details
print(f"Created debt with request: {created_debt.request_info}")

Working with Contact Details

from ophelos_sdk.models import ContactDetail

# Create contact detail for a customer
contact = client.contact_details.create("cust_123", {
    "type": "email",
    "value": "john.doe@example.com",
    "primary": True,
    "usage": "billing"
})

# Get specific contact detail
contact_detail = client.contact_details.get("cust_123", contact.id)

# Update contact detail
updated_contact = client.contact_details.update("cust_123", contact.id, {
    "usage": "notifications"
})

# List all contact details for customer
contacts = client.contact_details.list("cust_123")

# Access request/response details
print(f"Contact creation time: {contact.response_raw.elapsed.total_seconds()}s")
print(f"List request: {contacts.request_info['url']}")

Error Handling with Request/Response Debugging

from ophelos_sdk.exceptions import (
    OphelosAPIError, AuthenticationError, TimeoutError,
    ParseError, UnexpectedError
)

try:
    debt = client.debts.get("invalid_debt_id")
except OphelosAPIError as e:
    print(f"API Error: {e.message} (Status: {e.status_code})")
    print(f"Request: {e.request_info}")  # Full request details
    print(f"Response time: {e.response_raw.elapsed.total_seconds()}s")
except TimeoutError as e:
    print(f"Request timed out: {e.message}")
    print(f"Request details: {e.request_info}")  # Available even for timeouts
except UnexpectedError as e:
    print(f"Unexpected error: {e.message}")
    print(f"Original error: {e.original_error}")
    print(f"Request context: {e.request_info}")

Webhook Handling

from ophelos_sdk.webhooks import WebhookHandler

# Initialize webhook handler
webhook_handler = WebhookHandler("your_webhook_secret")

# Validate and parse webhook
try:
    event = webhook_handler.verify_and_parse(
        payload=request.body,
        signature=request.headers.get("Ophelos-Signature")
    )

    if event.type == "debt.created":
        print(f"New debt created: {event.data.id}")

except Exception as e:
    print(f"Webhook validation failed: {e}")

API Resources

  • Debts: Create, update, and manage debts with lifecycle operations
  • Customers: Customer CRUD operations with contact detail management
  • Contact Details: Manage customer contact information (email, phone, address)
  • Payments: Payment processing and tracking
  • Organisations: Organisation setup and configuration
  • Invoices: Invoice creation and management
  • Communications: Communication tracking and management
  • Payment Plans: Payment plan management
  • Webhooks: Webhook management and validation

Pagination

# List with automatic pagination
debts = client.debts.list(limit=50)

# Check pagination status
if debts.has_more:
    print(f"Total count: {debts.total_count}")

    # Navigate using cursors
    next_page = client.debts.list(limit=50, after=debts.pagination['next']['after'])

# Memory-efficient iteration
for debt in client.debts.iterate(limit_per_page=100):
    print(f"Processing debt: {debt.id}")

Development

# Clone and install
git clone https://github.com/ophelos/ophelos-python-sdk.git
cd ophelos-python-sdk
pip install -e ".[dev]"

# Run tests (250+ tests including 143 model tests)
pytest

# Run linting
flake8 ophelos_sdk/
mypy ophelos_sdk/
black ophelos_sdk/ --line-length 120

Support

License

This project is licensed under the MIT License - see the LICENSE file for details.

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

ophelos_sdk-1.4.0.tar.gz (70.2 kB view details)

Uploaded Source

Built Distribution

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

ophelos_sdk-1.4.0-py3-none-any.whl (43.9 kB view details)

Uploaded Python 3

File details

Details for the file ophelos_sdk-1.4.0.tar.gz.

File metadata

  • Download URL: ophelos_sdk-1.4.0.tar.gz
  • Upload date:
  • Size: 70.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for ophelos_sdk-1.4.0.tar.gz
Algorithm Hash digest
SHA256 2579dec109f6cb7aa29a2b9963ca998e2df7ef7f0a5a1d4367b15aa5573e8a4c
MD5 a433240e295809a5aed34b33cb973a61
BLAKE2b-256 4db30aae743f44ec808619e64c299dafd8b787bc877aac2c3db68558e840a6a8

See more details on using hashes here.

File details

Details for the file ophelos_sdk-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: ophelos_sdk-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 43.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.1

File hashes

Hashes for ophelos_sdk-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ed8dd8fa11af4fc457362035da1e178f01e70e59d787d6a8640e16c1e974fc6
MD5 5e5dac65369cd77462be49f72a9c6bce
BLAKE2b-256 74a47ef6466538c15244b38b18be452e3d931206f61545c600efa0ce28d9c3a9

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