Documentation Index
Fetch the complete documentation index at: https://tonic-ai.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Loan Recovery System automates the detection and management of loan defaults with integrated Twilio SMS and voice communication capabilities. It provides a comprehensive workflow for managing borrower contacts, recovery actions, and CDM event tracking. Code Reference:app/services/loan_recovery_service.py, app/services/twilio_service.py, app/api/recovery_routes.py, client/src/components/LoanRecoverySidebar.tsx
Key Features
Automatic Default Detection
The system automatically detects two types of defaults:Payment Defaults
- Detection Method: Monitors
PaymentEventrecords withpayment_status == "pending" - Calculation: Compares payment due date (created_at + 30 days) with current date
- Severity Levels:
- Low: 1-7 days past due
- Medium: 8-30 days past due
- High: 31-60 days past due
- Critical: 60+ days past due
app/services/loan_recovery_service.py (detect_payment_defaults method)
Covenant Breaches
- Detection Method: Monitors
LoanAssetrecords withrisk_status == "BREACH" - Trigger: Satellite verification detects compliance breach (e.g., NDVI below threshold)
- Severity: Typically “high” for all breaches
app/services/loan_recovery_service.py (detect_covenant_breaches method)
Twilio Integration
SMS Notifications
- E.164 Format Validation: Phone numbers validated before sending
- Status Callbacks: Real-time delivery status updates via webhooks
- Message Tracking: Twilio message SID stored for status tracking
- Error Handling: Comprehensive error handling with detailed error messages
app/services/twilio_service.py (send_sms method)
Voice Calls
- TwiML Generation: Automatic TwiML response generation
- Interactive Calls: Support for digit gathering and interactive responses
- Status Tracking: Call SID tracking and status monitoring
- Multi-Language: Support for different language codes
app/services/twilio_service.py (make_voice_call, generate_twiml_response methods)
Webhook Support
- Signature Verification: Secure webhook signature validation
- Status Updates: Automatic status updates for SMS and voice calls
- Delivery Tracking: Real-time delivery and read receipts
app/api/twilio_routes.py (webhook handlers)
Recovery Actions
The system supports multiple recovery action types with automatic escalation:Action Types
sms_reminder: SMS notification (days 1-3)voice_call: Voice call notification (days 4-7)email: Email notification (days 8-30)escalation: Escalated communication (30+ days)
app/services/loan_recovery_service.py (trigger_recovery_actions method)
Action Status
pending: Action created but not executedsent: Action executed successfullydelivered: Message delivered (SMS only)failed: Action failed with errorresponded: Borrower responded to communication
app/db/models.py (RecoveryAction model)
Message Templates
- Jinja2 Templating: Dynamic message generation with template variables
- Severity-Based Templates: Different templates for low/medium/high/critical
- Default Type Templates: Separate templates for payment defaults vs covenant breaches
- Fallback Templates: Default templates if custom templates not found
app/services/recovery_template_service.py
Borrower Contact Management
- Contact Information: Phone numbers, email addresses, preferred contact methods
- Primary Contacts: Designate primary contact for each deal
- Contact Preferences: Timezone, preferred hours, communication preferences
- Active/Inactive: Manage contact status
app/db/models.py (BorrowerContact model)
CDM Event Integration
All recovery operations generate CDM-compliant events:Loan Default Events
app/models/cdm_events.py (generate_cdm_loan_default function)
Recovery Action Events
app/models/cdm_events.py (generate_cdm_recovery_action function)
Workflow
1. Default Detection
Automatic Detection:- System periodically checks for overdue payments
- System monitors loan assets for breach status
- Defaults are created automatically when detected
- CDM events are generated for each default
- Navigate to Loan Recovery sidebar
- Click “Detect Defaults” button
- System scans for new defaults
- Results displayed in default list
app/services/loan_recovery_service.py (detect_payment_defaults, detect_covenant_breaches methods)
2. Recovery Action Creation
Automatic Triggering:- System automatically determines action types based on days past due
- Actions are created and executed immediately
- Messages are sent via Twilio
- Status is tracked in real-time
- Select a default from the list
- Click “Trigger Actions” button
- Choose action types (or let system auto-determine)
- Actions are created and executed
- Status updates displayed in real-time
app/services/loan_recovery_service.py (trigger_recovery_actions method)
3. Action Execution
SMS Execution:- Validate phone number (E.164 format)
- Generate message content from template
- Send SMS via Twilio API
- Store Twilio message SID
- Update action status to “sent”
- Generate CDM event
- Validate phone number (E.164 format)
- Generate TwiML response
- Initiate call via Twilio API
- Store Twilio call SID
- Update action status to “sent”
- Generate CDM event
app/services/loan_recovery_service.py (execute_recovery_action method)
4. Status Updates
Webhook Processing:- Twilio sends webhook to
/api/twilio/webhook/smsor/api/twilio/webhook/voice - Signature is verified for security
- RecoveryAction record is updated with new status
- CDM event is updated if needed
- Frontend is notified of status change
app/api/twilio_routes.py (webhook handlers)
User Interface
Loan Recovery Sidebar
Location:client/src/components/LoanRecoverySidebar.tsx
Features:
- Default List: View all active defaults with filtering by status, severity, deal
- Default Detail View: Comprehensive default information including:
- Default type and reason
- Amount overdue (if payment default)
- Days past due
- Severity level
- Status
- Related recovery actions
- Recovery Actions:
- View all actions for a default
- Trigger new actions
- Execute pending actions
- View action status and delivery information
- Borrower Contacts:
- View borrower contact information
- Add new contacts
- Update contact details
- Filtering: Filter defaults by status, severity, deal ID
- Real-time Updates: Status updates via webhooks
API Endpoints
Default Management
List all loan defaults with optional filtering. Query Parameters:deal_id: Filter by deal IDstatus: Filter by status (open, in_recovery, resolved, written_off)severity: Filter by severity (low, medium, high, critical)page: Page number (default: 1)limit: Items per page (default: 50, max: 100)
app/api/recovery_routes.py (default endpoints)
Recovery Actions
Trigger recovery actions for a loan default. Request Body:default_id: Filter by default IDstatus: Filter by statusdeal_id: Filter by deal IDpage: Page numberlimit: Items per page
app/api/recovery_routes.py (action endpoints)
Borrower Contacts
List all borrower contacts. Query Parameters:deal_id: Filter by deal ID
app/api/recovery_routes.py (contact endpoints)
Twilio Webhooks
SMS status callback endpoint (called by Twilio). Request: Form data from Twilio with signature verification Response: 200 OK Voice call status callback endpoint (called by Twilio). Request: Form data from Twilio with signature verification Response: TwiML response or 200 OK Generic status callback endpoint. Code Reference:app/api/twilio_routes.py (webhook endpoints)
Configuration
Environment Variables
Enable Twilio integration. Default:
falseTwilio Account SID (required if TWILIO_ENABLED=true)
Twilio Auth Token (required if TWILIO_ENABLED=true)
Twilio phone number in E.164 format (e.g., +1234567890)
Enable SMS functionality. Default:
trueEnable voice call functionality. Default:
trueBase URL for Twilio webhook callbacks (e.g., https://yourdomain.com/api/twilio)
Database Models
LoanDefault
Table:loan_defaults
Key Fields:
loan_id: Loan identifier (string)deal_id: Deal identifier (foreign key)default_type: Type (payment_default, covenant_breach, infraction)default_date: Date when default occurreddefault_reason: Reason for defaultamount_overdue: Amount overdue (for payment defaults)days_past_due: Number of days past dueseverity: Severity level (low, medium, high, critical)status: Status (open, in_recovery, resolved, written_off)cdm_events: JSONB array of CDM events
app/db/models.py (LoanDefault class, lines 2366-2409)
RecoveryAction
Table:recovery_actions
Key Fields:
loan_default_id: Foreign key to LoanDefaultaction_type: Type (sms_reminder, voice_call, email, escalation, legal_notice)communication_method: Method (sms, voice, email)recipient_phone: Recipient phone number (E.164 format)recipient_email: Recipient email addressmessage_template: Template name usedmessage_content: Actual message senttwilio_message_sid: Twilio message SID (for SMS)twilio_call_sid: Twilio call SID (for voice)status: Status (pending, sent, delivered, failed, responded)scheduled_at: Scheduled execution timesent_at: Actual send timedelivered_at: Delivery time (SMS)error_message: Error message if failed
app/db/models.py (RecoveryAction class, lines 2412-2465)
BorrowerContact
Table:borrower_contacts
Key Fields:
deal_id: Foreign key to Dealuser_id: Foreign key to User (if borrower is a user)contact_name: Contact namephone_number: Phone number (E.164 format)email: Email addresspreferred_contact_method: Preferred method (sms, voice, email)contact_preferences: JSONB preferences (timezone, hours, etc.)is_primary: Primary contact flagis_active: Active status flag
app/db/models.py (BorrowerContact class, lines 2468-2507)
Message Templates
Template Location
Templates are stored inapp/templates/recovery/ directory.
Template Naming Convention
{communication_method}_{default_type}.txt: Base template{communication_method}_{default_type}_{severity}.txt: Severity-specific template{communication_method}_escalation.txt: Escalation template
sms_payment_default.txt: Base SMS template for payment defaultssms_payment_default_high.txt: High severity SMS templatevoice_covenant_breach.txt: Voice template for covenant breachessms_escalation.txt: Escalation SMS template
Template Variables
Available template variables:borrower_name: Borrower contact namedefault_type: Type of defaultdefault_reason: Reason for defaultamount_overdue: Amount overdue (if payment default)days_past_due: Days past dueseverity: Severity levelloan_id: Loan identifierdeal_id: Deal identifier
app/services/recovery_template_service.py (render_template method)
Best Practices
- Timely Detection: Configure default detection to run regularly (e.g., daily)
- Multi-Channel Approach: Use SMS, voice, and email for better reach
- Compliance: Ensure all communications comply with regulations (TCPA, GDPR)
- Documentation: Maintain complete audit trail via CDM events
- Follow-up: Track borrower responses and adjust recovery strategy
- Phone Number Validation: Always validate phone numbers in E.164 format
- Error Handling: Monitor failed actions and retry if appropriate
- Template Customization: Customize message templates for your organization
Troubleshooting
SMS Not Delivered
Possible Causes:- Invalid phone number format (must be E.164)
- Twilio account balance insufficient
- Phone number not SMS-capable
- Twilio account restrictions
- Verify phone number format:
+[country code][number](e.g.,+1234567890) - Check Twilio Console for delivery status
- Verify Twilio account balance
- Review Twilio error codes in action metadata
Voice Calls Not Working
Possible Causes:- Phone number not voice-capable
- TwiML response format incorrect
- Webhook URL not accessible
- Twilio account restrictions
- Verify phone number has Voice capabilities in Twilio
- Check TwiML response format
- Ensure webhook URL is publicly accessible
- Review call logs in Twilio Console
Defaults Not Detected
Possible Causes:- PaymentEvent records not in “pending” status
- LoanAsset records not in “BREACH” status
- Date calculations incorrect
- Verify PaymentEvent payment_status
- Check LoanAsset risk_status
- Review default detection logic in service
Additional Resources
Last Updated: 2026-01-14
Code Reference:
app/services/loan_recovery_service.py, app/services/twilio_service.py, app/api/recovery_routes.py, client/src/components/LoanRecoverySidebar.tsx