Servicing Result Schema
Servicing Result Schema
Section titled “Servicing Result Schema”The servicing result schema represents the complete output of a servicing calculation, including borrowing capacity, validation checks, rate breakdowns, and financial projections.
Overview
Section titled “Overview”When you call the compute servicing endpoint, you receive a comprehensive analysis of whether a lender can service a loan and what the maximum borrowing capacity is.
Schema Structure
Section titled “Schema Structure”interface ServicingResult { // Core Results lender_name: string; does_service: boolean; fail_service_reason: string | null; max_borrowing_capacity: number; net_monthly_surplus: number; debt_to_income_ratio: number; has_rate_override: boolean;
// Validation & Warnings validations: Validation[]; warnings: Warning[];
// Rate & Product Information per_loan_rate_breakdown: LoanRateBreakdown[];
// Projections ytd_results: YearToDateResult[][];
// Lender-Specific Data lender_specific_display_items?: LenderDisplayItem[]; lender_specific_results?: Record<string, any>;
// Detailed Breakdown (for advanced use) interim_values?: InterimValues;}Core Fields
Section titled “Core Fields”Primary Results
| Field | Type | Description |
|---|---|---|
lender_name | string | Name of the lender (e.g., 'redzed', 'cba', 'westpac') |
does_service | boolean | Whether this lender can service the proposed loan |
fail_service_reason | string | null | Reason for service failure if does_service is false, otherwise null |
max_borrowing_capacity | number | Maximum loan amount the lender will approve (AUD) |
net_monthly_surplus | number | Monthly cashflow surplus after all commitments |
debt_to_income_ratio | number | DTI ratio (total debt / annual income) |
has_rate_override | boolean | Whether custom rate overrides were applied to this calculation |
Example:
{ "lender_name": "redzed", "does_service": true, "fail_service_reason": null, "max_borrowing_capacity": 2094569, "net_monthly_surplus": 13916.81, "debt_to_income_ratio": 2.32, "has_rate_override": false}Validations
Array of validation checks performed by the lender’s servicing calculator.
| Field | Type | Description |
|---|---|---|
type | string | Validation type identifier (e.g., 'SIMPLE_BONUS_INCOME_WARNING') |
isValid | boolean | Whether the check passed |
message | string | Detailed description of the validation result (may include markdown) |
softWarning | boolean | If true, this is a warning that doesn’t prevent approval |
allowServiceability | boolean | Whether this validation allows the loan to proceed even if isValid is false |
Example:
{ "validations": [ { "type": "SIMPLE_BONUS_INCOME_WARNING", "isValid": false, "softWarning": true, "allowServiceability": true, "message": "**Simple Bonus Method Detected**: Please note that RedZed has a policy that bonus income will only be acceptable when the most recent two financial years are provided in servicing. Quickli is treating your bonus income as if it's already aligned with this policy." }, { "type": "REQUIRES_COMMITMENTS_MONTHLY_REPAYMENT", "allowServiceability": true, "isValid": false, "message": "RedZed will use the inputted monthly repayment to include your commitments in the assessment (except for Credit Card, Margin and Overdraft). Quickli has detected that some of your commitments has $0 repayment, and hence applied $0 for that commitment to align with RedZed. Please ensure you enter the correct repayment amount, as this can have a significant impact on your application." } ]}Understanding Validation Results:
isValid: false+allowServiceability: true= Warning only, loan can still proceedisValid: false+allowServiceability: false= Hard stop, loan cannot proceedsoftWarning: true= Informational notice for broker awareness- Messages may contain markdown formatting (e.g.,
**bold text**)
Common validation types:
- Income verification requirements (
SIMPLE_BONUS_INCOME_WARNING) - Commitment assessment policies (
REQUIRES_COMMITMENTS_MONTHLY_REPAYMENT) - Minimum income thresholds
- Maximum LVR limits
- Debt service coverage ratios
- Living expense minimums (HEM benchmark)
- Property type restrictions
- Employment type requirements
Warnings
Array of warning objects that don’t prevent loan approval but require attention. Warnings provide important context about policy interpretations, calculation methods, or potential risks.
| Field | Type | Description |
|---|---|---|
_id | string | Unique identifier for this warning type |
message | string | Detailed warning message (may contain markdown/newlines) |
warningLevel | string | Severity level (e.g., 'warning', 'info') |
logicToTriggerWarning | boolean | Whether the condition for this warning is currently met |
orderPriority | string | Display priority ('high', 'medium', 'low') |
shouldMakeRowAmber | boolean | Whether this warning should highlight the result row |
outOfScopeIfTriggered | boolean | Whether triggering makes the scenario out of scope |
outOfScopeHeader | string | Header text if out of scope |
internalTag | string | Internal classification tag |
Example:
{ "warnings": [ { "_id": "67ff4f7be2c3546ef71e4509", "logicToTriggerWarning": true, "orderPriority": "medium", "warningLevel": "warning", "message": "The HECS repayment used for RedZed is not based on their calculator, but on the ATO tables and can risk being open to interpretation or change without notice by the lender.\n\nThis is straightforward when there's only PAYG income, but less straightforward when there's other types of income, especially rental income/negative gearing.\n\nView HECS Policy below.", "shouldMakeRowAmber": false, "outOfScopeIfTriggered": false, "outOfScopeHeader": "", "internalTag": "GENERIC_HECS_CALCULATION" } ]}Common warning scenarios:
- HECS calculation methodology differences
- Income verification requirements
- Documentation needed for specific income types
- Policy interpretation notes
- Rate review periods
- Future payment changes (IO to P&I conversion)
- Lender-specific calculation approaches
How to handle warnings:
- Review all warnings with
logicToTriggerWarning: true - Pay special attention to warnings with
orderPriority: 'high' - Ensure clients understand policy differences noted in warning messages
- Check if
outOfScopeIfTriggered: trueindicates the scenario may not be suitable
Per-Loan Rate Breakdown
Detailed interest rate and product information for each proposed loan.
| Field | Type | Description |
|---|---|---|
product_name | string | Name of the lender’s product (e.g., 'SE Prime') |
svr | number | Standard Variable Rate (%) before discounts |
discount | number | Total discount applied to the SVR (%) |
productFees | Fee[] | Array of product fees (see Product Fees Schema) |
ongoingFee | number | Total ongoing monthly fees |
setupFee | number | Total one-time setup fees |
Example:
{ "per_loan_rate_breakdown": [ { "product_name": "SE Prime", "svr": 6.75, "discount": 0.36, "productFees": [ { "name": "Settlement Fee", "amount": 500, "frequency": "once", "payablePer": "split", "payAt": "end", "isPromotional": false }, { "name": "Account Management Fee", "amount": 25, "frequency": "monthly", "description": "Per loan split", "payablePer": "split", "payAt": "start", "isPromotional": false } // ... more fees (see Product Fees documentation) ], "ongoingFee": 0, "setupFee": 0 }, { "product_name": "SE Prime", "svr": 6.75, "discount": 0.36, "productFees": [/* ... */], "ongoingFee": 0, "setupFee": 0 } ]}Calculating the effective rate:
const effectiveRate = svr - discount;// Example: 6.75% - 0.36% = 6.39%Note: The productFees array can be extensive (10+ fees per product). See the Product Fees Schema for complete fee structure documentation.
Rate factors included in discount:
- LVR-based discounts/premiums
- Package/relationship discounts
- Owner-occupied vs investment adjustments
- Principal & Interest vs Interest-only adjustments
- Loan amount tier discounts
Year-to-Date Results
Financial projections showing cashflow and loan balances over time.
| Field | Type | Description |
|---|---|---|
year | number | Year number (0 = current, 1 = year 1, etc.) |
total_income | number | Total annual income |
total_expenses | number | Total annual expenses |
total_loan_repayments | number | Total annual loan repayments |
remaining_balance | number | Loan balance at end of year |
surplus | number | Annual cashflow surplus |
Example:
{ "ytd_results": [ { "year": 0, "total_income": 120000, "total_expenses": 42000, "total_loan_repayments": 48000, "remaining_balance": 680000, "surplus": 30000 }, { "year": 1, "total_income": 120000, "total_expenses": 43260, "total_loan_repayments": 48000, "remaining_balance": 670500, "surplus": 28740 } ]}Use cases:
- Understanding long-term affordability
- Planning for payment increases (e.g., IO to P&I conversion)
- Stress testing scenarios
- Comparing different loan structures
Note: ytd_results may be an empty array or array of empty arrays depending on lender and calculation type.
Lender-Specific Display Items
Additional metrics and calculations specific to each lender. These values provide insight into how the lender assesses the application.
| Field | Type | Description |
|---|---|---|
section | string | Where this item should be displayed ('results' or 'interim') |
name | string | Display name of the metric |
value | number | Calculated value |
units | string | Unit type ('ratio', 'dollar', 'percentage') |
Example:
{ "lender_specific_display_items": [ { "section": "results", "name": "DSR", "value": 2.45, "units": "ratio" }, { "section": "results", "name": "DTI", "value": 2.32, "units": "ratio" }, { "section": "interim", "name": "Personal Income", "value": 24084, "units": "dollar" }, { "section": "interim", "name": "Rental Income", "value": 8840, "units": "dollar" }, { "section": "interim", "name": "Total Monthly Net Income", "value": 32924, "units": "dollar" }, { "section": "interim", "name": "Living Expenses (Assessed)", "value": 9361, "units": "dollar" }, { "section": "interim", "name": "Available Income", "value": 23563, "units": "dollar" }, { "section": "interim", "name": "Total Monthly Commitments (Actual)", "value": 7969, "units": "dollar" }, { "section": "interim", "name": "Total Monthly Commitments (Assessed)", "value": 9646, "units": "dollar" } ]}Common lender-specific metrics:
- DSR (Debt Service Ratio): Total debt repayments / total income
- DTI (Debt to Income): Total debt / annual income
- Income breakdowns: Personal, rental, total net income
- Expense assessments: Actual vs assessed living expenses
- Commitment calculations: Actual vs assessed monthly commitments
- Available Income: Income remaining after expenses
Note: Different lenders provide different metrics. This field may not be present for all lenders.
Interim Values (Advanced)
Detailed breakdown of all calculations performed during servicing assessment. Useful for debugging, auditing, or understanding exactly how the lender assessed the application.
Structure:
interface InterimValues { net_monthly_surplus: { eligible_income: number; comparable_expenses: number; non_comparable_expenses: number; proposed_assessed_repayments: number; existing_assessed_repayments: number; existing_liability_repayments: number; }; households: { summaries: HouseholdSummary[]; assessed_expenses: number; }; income: { summaries: IncomeSummary[]; total_income: number; }; rental_income: RentalIncomeSummary[]; liabilities: { repayments: number[]; total_repayments: number; }; existing_home_loans: HomeLoanDetails; proposed_home_loans: HomeLoanDetails; remarks: PolicyRemarks;}Key sections:
- net_monthly_surplus: Components of the surplus calculation
- households: HEM benchmarks and assessed living expenses per household
- income: Detailed income breakdown per applicant (taxable salary, rental, bonuses, tax offsets, HECS)
- rental_income: Rental yield caps and shading applied per property
- liabilities: Assessment of existing debts and commitments
- existing_home_loans: Existing loan details and repayment calculations
- proposed_home_loans: Proposed loan details, actual rates, and assessment rates
- remarks: Family tax benefit eligibility and other policy-specific notes
When to use interim_values:
- Debugging why a calculation resulted in a specific value
- Understanding how different income types were assessed
- Auditing rental income shading or HECS calculations
- Comparing lender-specific policy implementations
- Building detailed reports for clients
Example access:
const applicant1Income = result.interim_values.income.summaries[0];console.log('Taxable salary:', applicant1Income.taxable_salary);console.log('Eligible income:', applicant1Income.eligible);console.log('HECS repayment:', applicant1Income.hecs_assessed_repayment);
const household1 = result.interim_values.households.summaries[0];console.log('HEM benchmark:', household1.hem_benchmark);console.log('Actual expenses:', household1.actual_expenses);Note: This field contains extensive calculation details and may be overwhelming for basic use cases. Most developers only need the top-level results fields.
Complete Example Response
Section titled “Complete Example Response”Below is a real response from the RedZed lender with lenderName: "redzed" and addToRates: 0.5:
{ "data": { "lender_name": "redzed", "does_service": true, "fail_service_reason": null, "max_borrowing_capacity": 2094569, "net_monthly_surplus": 13916.81, "debt_to_income_ratio": 2.32, "has_rate_override": false, "validations": [ { "type": "SIMPLE_BONUS_INCOME_WARNING", "isValid": false, "softWarning": true, "allowServiceability": true, "message": "**Simple Bonus Method Detected**: Please note that RedZed has a policy that bonus income will only be acceptable when the most recent two financial years are provided in servicing. Quickli is treating your bonus income as if it's already aligned with this policy." }, { "type": "REQUIRES_COMMITMENTS_MONTHLY_REPAYMENT", "allowServiceability": true, "isValid": false, "message": "RedZed will use the inputted monthly repayment to include your commitments in the assessment (except for Credit Card, Margin and Overdraft). Quickli has detected that some of your commitments has $0 repayment, and hence applied $0 for that commitment to align with RedZed. Please ensure you enter the correct repayment amount, as this can have a significant impact on your application." } ], "warnings": [ { "_id": "67ff4f7be2c3546ef71e4509", "logicToTriggerWarning": true, "orderPriority": "medium", "warningLevel": "warning", "message": "The HECS repayment used for RedZed is not based on their calculator, but on the ATO tables and can risk being open to interpretation or change without notice by the lender.\n\nThis is straightforward when there's only PAYG income, but less straightforward when there's other types of income, especially rental income/negative gearing.\n\nView HECS Policy below.", "shouldMakeRowAmber": false, "outOfScopeIfTriggered": false, "outOfScopeHeader": "", "internalTag": "GENERIC_HECS_CALCULATION" } ], "per_loan_rate_breakdown": [ { "product_name": "SE Prime", "svr": 6.75, "discount": 0.36, "productFees": [ { "name": "Settlement Fee", "amount": 500, "frequency": "once", "payablePer": "split", "payAt": "end", "isPromotional": false }, { "name": "Account Management Fee", "amount": 25, "frequency": "monthly", "description": "Per loan split", "payablePer": "split", "payAt": "start", "isPromotional": false }, { "name": "Establishment Fee", "amount": 399, "frequency": "once", "description": "Payable at settlement & includes one standard security appraisal of a property ≤ $2M.", "payablePer": "application", "payAt": "start", "isPromotional": false } // ... additional fees (see Product Fees documentation) ], "ongoingFee": 0, "setupFee": 0 } ], "ytd_results": [[], [], []], "lender_specific_display_items": [ { "section": "results", "name": "DSR", "value": 2.45, "units": "ratio" }, { "section": "results", "name": "DTI", "value": 2.32, "units": "ratio" }, { "section": "interim", "name": "Personal Income", "value": 24084, "units": "dollar" }, { "section": "interim", "name": "Total Monthly Net Income", "value": 32924, "units": "dollar" } ], "lender_specific_results": { "debt_service_ratio": 2.442751474621408 } // interim_values omitted for brevity (see Interim Values section above) }, "meta": { "timestamp": "2025-11-06T03:47:17.053Z" }}Understanding Results
Section titled “Understanding Results”Does Service = true
Section titled “Does Service = true”The loan passes all mandatory validation checks:
- ✅ Income is sufficient
- ✅ LVR is within limits
- ✅ Debt service ratios are acceptable
- ✅ Living expenses meet minimum benchmarks
- ✅ No deal-breaking policy restrictions
Action: Proceed with the loan application at the calculated rate.
Does Service = false
Section titled “Does Service = false”The loan fails one or more mandatory validation checks. This occurs when:
- A validation has
isValid: falseANDallowServiceability: false - Critical policy restrictions prevent loan approval
Common failure scenarios:
- ❌ Insufficient income for requested loan amount
- ❌ LVR too high
- ❌ Debt service coverage inadequate
- ❌ Hard policy restriction triggered
Action: Review validations array to find checks where isValid: false and allowServiceability: false, then adjust the scenario accordingly.
Important: Not all isValid: false validations prevent serviceability. Check the allowServiceability field to determine if it’s a hard stop or just a warning.
Max Borrowing Capacity
Section titled “Max Borrowing Capacity”Represents the maximum loan amount this lender will approve given:
- Applicant’s income
- Existing liabilities
- Living expenses
- Property details
- Lender’s assessment rate
If max_borrowing_capacity < requested loan_amount, the loan won’t service.
Net Monthly Surplus
Section titled “Net Monthly Surplus”Remaining monthly cashflow after:
- All loan repayments (at assessment rate)
- Existing liabilities
- Living expenses
- Other commitments
Most lenders require a minimum surplus (typically $0-$500) for loan approval.
Working with Results
Section titled “Working with Results”Check if Loan Services
Section titled “Check if Loan Services”if (result.does_service) { const effectiveRate = result.per_loan_rate_breakdown[0].svr - result.per_loan_rate_breakdown[0].discount; console.log(`✓ Loan services with ${result.lender_name}`); console.log(`Effective rate: ${effectiveRate.toFixed(2)}%`); console.log(`Max capacity: $${result.max_borrowing_capacity.toLocaleString()}`);} else { console.log('✗ Loan does not service'); console.log(`Reason: ${result.fail_service_reason}`);
// Show hard stops (validation failures that prevent serviceability) const hardStops = result.validations.filter(v => !v.isValid && !v.allowServiceability); if (hardStops.length > 0) { console.log('\nHard stops:'); hardStops.forEach(v => console.log(`- ${v.type}: ${v.message}`)); }}
// Always check for warnings, even if loan servicesconst activeWarnings = result.validations.filter(v => !v.isValid && v.allowServiceability);if (activeWarnings.length > 0) { console.log('\n⚠️ Warnings (loan can still proceed):'); activeWarnings.forEach(v => console.log(`- ${v.type}: ${v.message}`));}Find Maximum Loan Amount
Section titled “Find Maximum Loan Amount”console.log(`Maximum borrowing: $${result.max_borrowing_capacity.toLocaleString()}`);
if (result.max_borrowing_capacity < requestedAmount) { const shortfall = requestedAmount - result.max_borrowing_capacity; console.log(`Shortfall: $${shortfall.toLocaleString()}`); console.log('Consider: increasing income, reducing liabilities, or adding a co-applicant');}Analyze Rate Breakdown
Section titled “Analyze Rate Breakdown”result.per_loan_rate_breakdown.forEach((loan, index) => { console.log(`Loan ${index + 1} (${loan.product_name}):`); console.log(`- SVR: ${loan.svr}%`); console.log(`- Discount: ${loan.discount}%`); console.log(`- Effective rate: ${(loan.svr - loan.discount).toFixed(2)}%`);
// Show key fees const monthlyFees = loan.productFees.filter(f => f.frequency === 'monthly'); const onceFees = loan.productFees.filter(f => f.frequency === 'once');
if (monthlyFees.length > 0) { console.log('Monthly fees:'); monthlyFees.forEach(f => console.log(` - ${f.name}: $${f.amount}`)); }
if (onceFees.length > 0) { console.log('One-time fees:'); onceFees.forEach(f => console.log(` - ${f.name}: $${f.amount}`)); }});Review Long-term Affordability
Section titled “Review Long-term Affordability”// Note: ytd_results may be an empty array or array of empty arraysif (result.ytd_results && result.ytd_results.length > 0 && result.ytd_results[0].length > 0) { result.ytd_results[0].forEach((year, index) => { console.log(`Year ${index}:`); console.log(`- Income: $${year.total_income.toLocaleString()}`); console.log(`- Expenses: $${year.total_expenses.toLocaleString()}`); console.log(`- Repayments: $${year.total_loan_repayments.toLocaleString()}`); console.log(`- Surplus: $${year.surplus.toLocaleString()}`); });} else { console.log('YTD projections not available for this lender');}Access Lender-Specific Metrics
Section titled “Access Lender-Specific Metrics”// Display lender-specific calculations (e.g., DSR, DTI)const resultMetrics = result.lender_specific_display_items?.filter(item => item.section === 'results') || [];const interimMetrics = result.lender_specific_display_items?.filter(item => item.section === 'interim') || [];
console.log('Key Metrics:');resultMetrics.forEach(metric => { if (metric.units === 'ratio') { console.log(`- ${metric.name}: ${metric.value.toFixed(2)}`); } else if (metric.units === 'dollar') { console.log(`- ${metric.name}: $${metric.value.toLocaleString()}`); }});
// Access detailed income/expense breakdown if neededif (interimMetrics.length > 0) { console.log('\nDetailed Breakdown:'); interimMetrics.forEach(metric => { console.log(`- ${metric.name}: $${metric.value.toLocaleString()}`); });}Common Scenarios
Section titled “Common Scenarios”Scenario 1: Loan Services Comfortably
Section titled “Scenario 1: Loan Services Comfortably”{ "does_service": true, "fail_service_reason": null, "max_borrowing_capacity": 2094569, "net_monthly_surplus": 13916.81, "validations": [ { "type": "SIMPLE_BONUS_INCOME_WARNING", "isValid": false, "allowServiceability": true, "softWarning": true } ]}Interpretation: Strong application with significant buffer ($13,916 surplus). Loan amount well within capacity ($2M+). Note that isValid: false doesn’t prevent approval when allowServiceability: true.
Scenario 2: Marginal Servicing
Section titled “Scenario 2: Marginal Servicing”{ "does_service": true, "fail_service_reason": null, "max_borrowing_capacity": 650000, "net_monthly_surplus": 150, "validations": [ { "type": "MINIMUM_SURPLUS_CHECK", "isValid": true, "allowServiceability": true } ]}Interpretation: Loan just scrapes through with minimal surplus ($150/month). Small changes in income or expenses could tip it over. Consider stress testing with addToRates parameter.
Scenario 3: Does Not Service
Section titled “Scenario 3: Does Not Service”{ "does_service": false, "fail_service_reason": "Insufficient surplus to meet minimum requirements", "max_borrowing_capacity": 580000, "net_monthly_surplus": -450, "validations": [ { "type": "MINIMUM_SURPLUS_CHECK", "isValid": false, "allowServiceability": false, "message": "Monthly surplus of -$450 is below minimum requirement of $0" } ]}Interpretation: Loan amount ($650k requested) exceeds capacity ($580k). Hard stop with allowServiceability: false. Need to reduce loan by $70k, increase income, or reduce existing commitments.
Next Steps
Section titled “Next Steps”- Compute servicing endpoint - How to request calculations
- Scenario schema - Build realistic scenarios for accurate results
- Product schema - Understand lender product configurations
Last updated: 2025-11-03