Examples and Use Cases
This page provides real-world examples of using the Apala API for various loan and financial scenarios.
Loan Application Inquiry
Handle customer inquiries about loan applications:
from apala_client import ApalaClient, Message, MessageFeedback
def handle_loan_inquiry():
client = ApalaClient(api_key="your-api-key")
client.authenticate()
# Customer conversation about loan application
messages = [
Message(
content="Hi, I submitted a loan application last week but haven't heard back. Can you check the status?",
channel="EMAIL",
reply_or_not=False
),
Message(
content="The application reference number is LA-2024-1234.",
channel="EMAIL",
reply_or_not=False
)
]
# Your proposed response
candidate = Message(
content="Thank you for following up on your loan application LA-2024-1234. I've checked your status and your application is currently under review. You can expect a decision within 3-5 business days. I'll send you an email as soon as we have an update.",
channel="EMAIL"
)
# Process and optimize
response = client.message_process(
message_history=messages,
candidate_message=candidate,
customer_id="customer-uuid",
zip_code="90210",
company_guid="company-uuid"
)
optimization = client.optimize_message(
message_history=messages,
candidate_message=candidate,
customer_id="customer-uuid",
zip_code="90210",
company_guid="company-uuid"
)
print(f"Original: {candidate.content}")
print(f"Optimized: {optimization['optimized_message']}")
print(f"Channel: {optimization['recommended_channel']}")
return response, optimization
Rate Shopping Conversation
Help customers compare loan rates and terms:
def handle_rate_shopping():
client = ApalaClient(api_key="your-api-key")
client.authenticate()
# Customer asking about rates
messages = [
Message(
content="I'm shopping for a mortgage and want to compare your rates with other lenders.",
channel="SMS",
reply_or_not=False
),
Message(
content="I have excellent credit (790+ score) and 20% down payment.",
channel="SMS",
reply_or_not=False
),
Message(
content="Looking at a $400K home purchase in California.",
channel="SMS",
reply_or_not=False
)
]
candidate = Message(
content="Great credit score! For a $400K purchase with 20% down, our current rates start at 3.25% APR for 30-year fixed. With your credit profile, you'd likely qualify for our best rates. Can I schedule a quick call to discuss your specific situation?",
channel="SMS"
)
# Process the conversation
response = client.message_process(
message_history=messages,
candidate_message=candidate,
customer_id="customer-uuid",
zip_code="90210",
company_guid="company-uuid"
)
return response
Document Collection Process
Guide customers through document submission:
def handle_document_collection():
client = ApalaClient(api_key="your-api-key")
client.authenticate()
# Customer confused about documents
messages = [
Message(
content="I'm ready to submit my loan documents but I'm not sure what you need exactly.",
channel="EMAIL",
reply_or_not=False
),
Message(
content="I'm self-employed so my income documentation might be different than usual.",
channel="EMAIL",
reply_or_not=False
)
]
candidate = Message(
content="Perfect timing! For self-employed borrowers, we need: 2 years of tax returns with all schedules, 2 years of profit & loss statements, 3 months of bank statements, and a CPA letter. I'll email you a secure upload link and checklist right now.",
channel="EMAIL"
)
# Get optimized version
optimization = client.optimize_message(
message_history=messages,
candidate_message=candidate,
customer_id="customer-uuid",
zip_code="90210",
company_guid="company-uuid"
)
return optimization
Batch Processing Multiple Conversations
Process multiple customer conversations efficiently:
def batch_process_conversations():
client = ApalaClient(api_key="your-api-key")
client.authenticate()
# Multiple customer scenarios
conversations = [
{
"customer_id": "customer-1-uuid",
"zip_code": "90210",
"messages": [
Message(content="Need refinancing help", channel="SMS"),
],
"candidate": Message(content="I'd be happy to help with refinancing options.", channel="SMS")
},
{
"customer_id": "customer-2-uuid",
"zip_code": "10001",
"messages": [
Message(content="First time home buyer questions", channel="EMAIL"),
],
"candidate": Message(content="Congratulations on your first home purchase journey!", channel="EMAIL")
}
]
results = []
for conv in conversations:
response = client.message_process(
message_history=conv["messages"],
candidate_message=conv["candidate"],
customer_id=conv["customer_id"],
zip_code=conv["zip_code"],
company_guid="company-uuid"
)
results.append(response)
return results
Feedback Tracking Workflow
Implement comprehensive feedback tracking:
def track_message_performance():
client = ApalaClient(api_key="your-api-key")
client.authenticate()
# Simulate message processing
response = process_customer_message(client)
message_id = response["candidate_message"]["message_id"]
message_content = response["candidate_message"]["content"]
# Simulate different customer response scenarios
scenarios = [
{
"name": "Quick Positive Response",
"responded": True,
"quality_score": 90,
"response_time_minutes": 15
},
{
"name": "Delayed Response",
"responded": True,
"quality_score": 75,
"response_time_minutes": 240 # 4 hours
},
{
"name": "No Response",
"responded": False,
"quality_score": 40,
"response_time_minutes": None
}
]
feedback_results = []
for scenario in scenarios:
feedback = MessageFeedback(
original_message_id=message_id,
sent_message_content=message_content,
customer_responded=scenario["responded"],
quality_score=scenario["quality_score"],
time_to_respond_ms=scenario["response_time_minutes"] * 60 * 1000 if scenario["response_time_minutes"] else None
)
result = client.submit_single_feedback(feedback)
feedback_results.append({
"scenario": scenario["name"],
"feedback_id": result["feedback_id"]
})
return feedback_results
Error Handling and Retry Logic
Implement robust error handling for production use:
import requests
import time
from typing import Optional
def robust_message_processing(
client: ApalaClient,
messages: list,
candidate: Message,
customer_id: str,
zip_code: str,
company_guid: str,
max_retries: int = 3
) -> Optional[dict]:
"""
Process messages with retry logic and comprehensive error handling.
"""
for attempt in range(max_retries):
try:
# Ensure we have valid authentication
if not client.access_token or time.time() >= (client.token_expires_at or 0):
print(f"Attempt {attempt + 1}: Refreshing authentication...")
client.authenticate()
# Process the messages
response = client.message_process(
message_history=messages,
candidate_message=candidate,
customer_id=customer_id,
zip_code=zip_code,
company_guid=company_guid
)
print(f"✅ Success on attempt {attempt + 1}")
return response
except requests.HTTPError as e:
print(f"❌ HTTP error on attempt {attempt + 1}: {e.response.status_code}")
if e.response.status_code == 401:
# Authentication issue - try to re-authenticate
print("🔄 Re-authenticating due to 401 error...")
try:
client.authenticate()
except Exception as auth_error:
print(f"❌ Re-authentication failed: {auth_error}")
elif e.response.status_code == 429:
# Rate limited - wait before retry
wait_time = 2 ** attempt # Exponential backoff
print(f"⏳ Rate limited, waiting {wait_time} seconds...")
time.sleep(wait_time)
elif e.response.status_code >= 500:
# Server error - retry might help
wait_time = 2 ** attempt
print(f"⏳ Server error, waiting {wait_time} seconds before retry...")
time.sleep(wait_time)
else:
# Client error - don't retry
print(f"❌ Client error {e.response.status_code}, not retrying")
break
except requests.ConnectionError as e:
print(f"❌ Connection error on attempt {attempt + 1}: {e}")
wait_time = 2 ** attempt
print(f"⏳ Waiting {wait_time} seconds before retry...")
time.sleep(wait_time)
except ValueError as e:
# Validation error - don't retry
print(f"❌ Validation error: {e}")
break
except Exception as e:
print(f"❌ Unexpected error on attempt {attempt + 1}: {e}")
wait_time = 2 ** attempt
time.sleep(wait_time)
print(f"❌ Failed after {max_retries} attempts")
return None
Custom Session Configuration
Configure the HTTP session for specific requirements:
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def create_custom_client():
"""Create a client with custom session configuration."""
client = ApalaClient(api_key="your-api-key")
# Create custom session with retry strategy
session = requests.Session()
# Configure retry strategy
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
# Set custom timeout
session.timeout = 30
# Add custom headers
session.headers.update({
'User-Agent': 'MyApp/1.0 ApalaSDK/0.1.0'
})
# Replace the client's session
client._session = session
return client
Production Deployment Example
Example of how to use the SDK in a production environment:
import os
import logging
from contextlib import contextmanager
from apala_client import ApalaClient
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class ProductionApalaService:
"""Production-ready wrapper for Apala API operations."""
def __init__(self):
self.api_key = os.environ["APALA_API_KEY"]
self.base_url = os.environ["APALA_BASE_URL"]
self.company_guid = os.environ["APALA_COMPANY_GUID"]
self.client = None
@contextmanager
def get_client(self):
"""Context manager for client lifecycle."""
client = ApalaClient(api_key=self.api_key, base_url=self.base_url)
try:
client.authenticate()
logger.info("Apala client authenticated successfully")
yield client
except Exception as e:
logger.error(f"Apala client error: {e}")
raise
finally:
client.close()
logger.info("Apala client closed")
def process_customer_message(self, customer_data: dict) -> dict:
"""Process a customer message with full error handling."""
with self.get_client() as client:
try:
response = client.message_process(
message_history=customer_data["messages"],
candidate_message=customer_data["candidate"],
customer_id=customer_data["customer_id"],
zip_code=customer_data["zip_code"],
company_guid=self.company_guid
)
logger.info(f"Message processed: {response['candidate_message']['message_id']}")
return response
except Exception as e:
logger.error(f"Message processing failed: {e}")
raise
# Usage
service = ProductionApalaService()
result = service.process_customer_message({
"messages": [Message(content="Help needed", channel="EMAIL")],
"candidate": Message(content="Happy to help!", channel="EMAIL"),
"customer_id": "customer-uuid",
"zip_code": "90210"
})
Interactive Development with Jupyter
Use the SDK in Jupyter notebooks for analysis and experimentation:
# Cell 1: Setup
%pip install apala-api
import pandas as pd
from apala_client import ApalaClient, Message, MessageFeedback
# Cell 2: Initialize
client = ApalaClient(api_key="your-api-key")
auth_response = client.authenticate()
print(f"Connected as: {auth_response['company_name']}")
# Cell 3: Process multiple messages and analyze results
results = []
test_scenarios = [
{"content": "Need loan help", "channel": "SMS"},
{"content": "Rate inquiry", "channel": "EMAIL"},
{"content": "Document questions", "channel": "OTHER"}
]
for scenario in test_scenarios:
messages = [Message(content=scenario["content"], channel=scenario["channel"])]
candidate = Message(content="I'm here to help!", channel=scenario["channel"])
response = client.message_process(
message_history=messages,
candidate_message=candidate,
customer_id="test-customer-uuid",
zip_code="90210",
company_guid="company-uuid"
)
results.append({
"original_channel": scenario["channel"],
"content": scenario["content"],
"message_id": response["candidate_message"]["message_id"],
"processed_content": response["candidate_message"]["content"]
})
# Cell 4: Analyze with pandas
df = pd.DataFrame(results)
print(df.head())
Testing and Development
Example test patterns for your own applications:
import pytest
from unittest.mock import Mock, patch
from apala_client import ApalaClient, Message
class TestApalaIntegration:
@pytest.fixture
def mock_client(self):
"""Mock client for testing."""
client = ApalaClient(api_key="test-key")
client.access_token = "mock-token"
client.token_expires_at = 9999999999 # Far future
return client
@patch('requests.Session.post')
def test_message_processing(self, mock_post, mock_client):
"""Test message processing with mocked response."""
# Mock the API response
mock_response = Mock()
mock_response.json.return_value = {
"company": "test-company",
"customer_id": "test-customer",
"candidate_message": {
"content": "Test response",
"channel": "EMAIL",
"message_id": "test-msg-123"
}
}
mock_response.raise_for_status.return_value = None
mock_post.return_value = mock_response
# Test the processing
messages = [Message(content="Test", channel="EMAIL")]
candidate = Message(content="Response", channel="EMAIL")
response = mock_client.message_process(
message_history=messages,
candidate_message=candidate,
customer_id="test-customer",
zip_code="90210",
company_guid="test-company"
)
assert response["candidate_message"]["message_id"] == "test-msg-123"
mock_post.assert_called_once()
These examples should give you a solid foundation for building production applications with the Apala API. Remember to always handle errors gracefully and implement appropriate retry logic for your use case!