Back to blog
Unified APIGuides & TutorialsAccounting

Using Accounting APIs for Smart Lending Decisions

This comprehensive guide shows fintech developers and lending platforms how to transform raw accounting data into actionable credit insights using financial statement APIs and proven lending ratios.

GJGJ

GJ

27 min read
Using Accounting APIs for Smart Lending Decisions

Profit and Loss & Balance Sheet API

The Profit and Loss (P&L) and Balance Sheet are the two most critical financial statements for assessing business health and creditworthiness. Using Apideck's unified Accounting API, you can retrieve standardized financial data from multiple accounting platforms through single endpoints.

API Endpoints:

  • GET /accounting/profit-and-loss - Income statement
  • GET /accounting/balance-sheet - Financial position snapshot

Documentation Reference: Apideck Accounting API


Understanding the Financial Statements

Profit and Loss Statement (Income Statement)

Answers: "Did we make money or lose money during this period?"

Time Frame: Period of time (e.g., month, quarter, year)

Shows:

  • Revenue earned during the period
  • Expenses incurred during the period
  • Profitability over time

Balance Sheet (Statement of Financial Position)

Answers: "What does the company own and owe at this moment?"

Time Frame: Snapshot at a specific point in time (e.g., December 31, 2025)

Shows:

  • Assets (what the company owns)
  • Liabilities (what the company owes)
  • Equity (owner's stake in the business)

Why Both Matter for Lending

StatementWhat It RevealsLending Insight
P&LProfitability & cash generationCan they afford loan payments?
Balance SheetFinancial strength & leverageDo they have enough assets? Are they over-leveraged?
CombinedComplete financial pictureComprehensive risk assessment

Example:

  • A business might show strong profits (P&L) but have weak liquidity (Balance Sheet) - risky for short-term loans
  • A business might have low profits (P&L) but strong assets (Balance Sheet) - good for secured loans

B2B Lending & Credit Assessment Use Cases

Why These Statements Matter for Lenders

Profit and Loss Analysis:

  1. Revenue Consistency - Is income stable or volatile?
  2. Profitability - Can the business generate sustainable profits?
  3. Operating Efficiency - How well does the company control costs?
  4. Debt Service Capacity - Can the business afford loan payments?

Balance Sheet Analysis:

  1. Liquidity - Can the business pay short-term obligations?
  2. Solvency - Is the business over-leveraged with debt?
  3. Asset Quality - What collateral is available?
  4. Working Capital - Is the business efficiently managing operations?

Common Lending Scenarios

1. Working Capital Loans

  • P&L Focus: Cash flow generation and operating expenses
  • Balance Sheet Focus: Current assets, current liabilities, working capital
  • Key Metrics: Current ratio, quick ratio, revenue trends
  • Typical Use: Short-term financing for inventory, payroll, or operations

2. Equipment Financing

  • P&L Focus: Profitability and depreciation capacity
  • Balance Sheet Focus: Existing fixed assets, total debt levels
  • Key Metrics: Debt-to-assets ratio, asset turnover
  • Typical Use: Asset purchases that improve operations

3. Term Loans

  • P&L Focus: Sustained profitability and EBITDA
  • Balance Sheet Focus: Total debt, equity, collateral availability
  • Key Metrics: Debt-to-equity ratio, DSCR, ROE
  • Typical Use: Business expansion, acquisitions

4. Asset-Based Lending

  • P&L Focus: Revenue stability
  • Balance Sheet Focus: Accounts receivable, inventory quality
  • Key Metrics: AR turnover, inventory turnover, collateral value
  • Typical Use: Leveraging assets for immediate cash needs

API Usage

Profit and Loss API

Basic Request

GET /accounting/profit-and-loss HTTP/1.1
Host: unify.apideck.com
Authorization: Bearer {your-api-key}
x-apideck-consumer-id: {consumer-id}
x-apideck-app-id: {application-id}
x-apideck-service-id: {connector-service-id}

Request Parameters

ParameterTypeRequiredDescription
start_datestringNoStart date for the report (ISO 8601 format: YYYY-MM-DD)
end_datestringNoEnd date for the report (ISO 8601 format: YYYY-MM-DD)
filter[currency]stringNoFilter by specific currency code (e.g., USD, EUR)

Date Handling Rules

Default Behavior (when no dates provided):

  • Returns data for the current month (from 1st of the month to today)

Partial Date Scenarios:

  • If only end_date provided: Returns data from the first day of that month to the specified end date
  • If only start_date provided: Returns data from the start date to the last day of that month
  • If both dates provided: Returns data for the exact date range specified

Balance Sheet API

Basic Request

GET /accounting/balance-sheet HTTP/1.1
Host: unify.apideck.com
Authorization: Bearer {your-api-key}
x-apideck-consumer-id: {consumer-id}
x-apideck-app-id: {application-id}
x-apideck-service-id: {connector-service-id}

Request Parameters

ParameterTypeRequiredDescription
datestringNoDate for the balance sheet snapshot (ISO 8601 format: YYYY-MM-DD)
filter[currency]stringNoFilter by specific currency code (e.g., USD, EUR)

Date Handling Rules

Default Behavior (when no date provided):

  • Returns balance sheet as of today's date

Specified Date:

  • Returns balance sheet snapshot as of the specified date

Response Structures

Profit and Loss Response

{
  "status_code": 200,
  "status": "OK",
  "data": {
    "id": "profit-loss-2025-10",
    "report_name": "Profit and Loss",
    "start_date": "2025-10-01",
    "end_date": "2025-10-31",
    "currency": "USD",
    "revenue": {
      "title": "Revenue",
      "type": "Revenue",
      "total": 125000.00,
      "records": [
        {
          "id": "110",
          "title": "Sales Revenue",
          "type": "Revenue",
          "total": 100000.00,
          "records": [
            {
              "id": "acc-001",
              "title": "Product Sales",
              "code": "4100",
              "total": 75000.00
            }
          ]
        }
      ]
    },
    "expenses": {
      "title": "Expenses",
      "type": "Expenses",
      "total": 80000.00,
      "records": [
        {
          "id": "111",
          "title": "Cost of Goods Sold",
          "type": "Expenses",
          "total": 40000.00,
          "records": [
            {
              "id": "acc-101",
              "title": "Direct Materials",
              "code": "5100",
              "total": 40000.00
            }
          ]
        }
      ]
    },
    "gross_profit": 85000.00,
    "net_operating_income": 55000.00,
    "net_income": 45000.00
  }
}

Balance Sheet Response

{
  "status_code": 200,
  "status": "OK",
  "data": {
    "id": "balance-sheet-2025-10-31",
    "report_name": "Balance Sheet",
    "date": "2025-10-31",
    "currency": "USD",
    "assets": {
      "title": "Assets",
      "type": "Assets",
      "total": 500000.00,
      "current_assets": {
        "title": "Current Assets",
        "total": 250000.00,
        "records": [
          {
            "id": "cash",
            "title": "Cash and Cash Equivalents",
            "code": "1000",
            "total": 75000.00
          },
          {
            "id": "ar",
            "title": "Accounts Receivable",
            "code": "1200",
            "total": 100000.00
          },
          {
            "id": "inventory",
            "title": "Inventory",
            "code": "1300",
            "total": 75000.00
          }
        ]
      },
      "non_current_assets": {
        "title": "Non-Current Assets",
        "total": 250000.00,
        "records": [
          {
            "id": "ppe",
            "title": "Property, Plant & Equipment",
            "code": "1500",
            "total": 200000.00
          },
          {
            "id": "intangibles",
            "title": "Intangible Assets",
            "code": "1600",
            "total": 50000.00
          }
        ]
      }
    },
    "liabilities": {
      "title": "Liabilities",
      "type": "Liabilities",
      "total": 250000.00,
      "current_liabilities": {
        "title": "Current Liabilities",
        "total": 100000.00,
        "records": [
          {
            "id": "ap",
            "title": "Accounts Payable",
            "code": "2000",
            "total": 50000.00
          },
          {
            "id": "short-debt",
            "title": "Short-term Debt",
            "code": "2100",
            "total": 30000.00
          },
          {
            "id": "accrued",
            "title": "Accrued Expenses",
            "code": "2200",
            "total": 20000.00
          }
        ]
      },
      "non_current_liabilities": {
        "title": "Non-Current Liabilities",
        "total": 150000.00,
        "records": [
          {
            "id": "long-debt",
            "title": "Long-term Debt",
            "code": "2500",
            "total": 150000.00
          }
        ]
      }
    },
    "equity": {
      "title": "Equity",
      "type": "Equity",
      "total": 250000.00,
      "records": [
        {
          "id": "capital",
          "title": "Owner's Capital",
          "code": "3000",
          "total": 200000.00
        },
        {
          "id": "retained",
          "title": "Retained Earnings",
          "code": "3100",
          "total": 50000.00
        }
      ]
    }
  }
}

Balance Sheet Structure Explained

The Accounting Equation

Assets = Liabilities + Equity

This fundamental equation must always balance.

Assets

What the company owns

Current Assets (liquid within 12 months)

  • Cash - Money in bank accounts
  • Accounts Receivable - Money customers owe
  • Inventory - Goods for sale
  • Prepaid Expenses - Advance payments

Non-Current Assets (long-term)

  • Property, Plant & Equipment (PP&E) - Buildings, machinery, vehicles
  • Intangible Assets - Patents, trademarks, goodwill
  • Long-term Investments - Stocks, bonds held >1 year

Liabilities

What the company owes

Current Liabilities (due within 12 months)

  • Accounts Payable - Money owed to suppliers
  • Short-term Debt - Loans due within 1 year
  • Accrued Expenses - Wages, taxes owed but not yet paid

Non-Current Liabilities (long-term)

  • Long-term Debt - Loans due after 1 year
  • Deferred Revenue - Payments received for future services
  • Pension Obligations - Future retirement payments

Equity

Owner's stake in the business

  • Owner's Capital - Initial investment
  • Retained Earnings - Accumulated profits not distributed
  • Additional Paid-in Capital - Stock proceeds above par value

Financial Ratios Using P&L and Balance Sheet

1. Profitability Ratios (P&L Focus)

Gross Profit Margin

const grossProfitMargin = (plData.gross_profit / plData.revenue.total) * 100

// Example: 68% (Strong - keeps 68% of revenue after direct costs)

Net Profit Margin

const netProfitMargin = (plData.net_income / plData.revenue.total) * 100

// Example: 36% (Excellent - keeps 36% of revenue as profit)

Return on Assets (ROA) - P&L + Balance Sheet

const roa = (plData.net_income / bsData.assets.total) * 100

// Example: 9% (Strong - generates $9 profit per $100 of assets)
// Good: >5% for most industries

Return on Equity (ROE) - P&L + Balance Sheet

const roe = (plData.net_income / bsData.equity.total) * 100

// Example: 18% (Excellent - generates $18 profit per $100 of equity)
// Good: >15% for most industries

2. Liquidity Ratios (Balance Sheet Focus)

Current Ratio

const currentRatio = 
  bsData.assets.current_assets.total / 
  bsData.liabilities.current_liabilities.total

// Example: 2.5 (Strong - $2.50 in current assets for every $1 of current liabilities)
// Good: 1.5 - 3.0
// Warning: <1.0 (may struggle to pay bills)

Quick Ratio (Acid Test)

const quickAssets = 
  bsData.assets.current_assets.total - 
  findAccount(bsData.assets.current_assets, 'Inventory')

const quickRatio = quickAssets / bsData.liabilities.current_liabilities.total

// Example: 1.75 (Strong - can cover liabilities without selling inventory)
// Good: >1.0
// Warning: <0.5 (liquidity crisis risk)

Cash Ratio

const cash = findAccount(bsData.assets.current_assets, 'Cash')
const cashRatio = cash / bsData.liabilities.current_liabilities.total

// Example: 0.75 (75 cents of cash for every $1 of current liabilities)
// Good: >0.5
// Warning: <0.2 (very tight cash position)

Working Capital

const workingCapital = 
  bsData.assets.current_assets.total - 
  bsData.liabilities.current_liabilities.total

// Example: $150,000 (positive working capital - healthy)
// Good: Positive and growing
// Warning: Negative (can't cover short-term obligations)

3. Leverage Ratios (Balance Sheet Focus)

Debt-to-Assets Ratio

const debtToAssets = (bsData.liabilities.total / bsData.assets.total) * 100

// Example: 50% (Half of assets financed by debt)
// Good: <50% for most businesses
// Warning: >70% (highly leveraged, risky)

Debt-to-Equity Ratio

const debtToEquity = bsData.liabilities.total / bsData.equity.total

// Example: 1.0 (Equal parts debt and equity)
// Good: <1.0 for most industries (more equity than debt)
// Acceptable: 1.0-2.0 (depending on industry)
// Warning: >3.0 (over-leveraged)

Equity Ratio

const equityRatio = (bsData.equity.total / bsData.assets.total) * 100

// Example: 50% (Owners fund half the business)
// Good: >40%
// Warning: <20% (most assets financed by debt)

4. Efficiency Ratios (P&L + Balance Sheet)

Asset Turnover

// Measures how efficiently assets generate revenue
const assetTurnover = plData.revenue.total / bsData.assets.total

// Example: 0.25 (Generates $0.25 revenue per $1 of assets)
// Good: >1.0 for retail, >0.5 for manufacturing
// Industry varies widely

Inventory Turnover

// How many times inventory is sold and replaced per period
const cogs = findExpenseCategory(plData, 'Cost of Goods Sold')
const inventory = findAccount(bsData.assets.current_assets, 'Inventory')

const inventoryTurnover = cogs / inventory

// Example: 5.33 (Inventory sold and replaced 5.33 times per year)
// Good: 5-10 for retail, varies by industry
// Warning: <3 (slow-moving inventory)

Days Inventory Outstanding (DIO)

const dio = (inventory / cogs) * 365

// Example: 68 days (Inventory sits for ~2 months before selling)
// Good: 30-60 days for retail
// Warning: >90 days (potential obsolescence risk)

Accounts Receivable Turnover

const ar = findAccount(bsData.assets.current_assets, 'Accounts Receivable')
const arTurnover = plData.revenue.total / ar

// Example: 12.5 (Collect receivables 12.5 times per year)
// Good: >10 for most businesses
// Warning: <6 (slow collections)

Days Sales Outstanding (DSO)

const ar = findAccount(bsData.assets.current_assets, 'Accounts Receivable')
const dso = (ar / plData.revenue.total) * 365

// Example: 29 days (Takes 29 days on average to collect payment)
// Good: <30 days for most businesses
// Warning: >60 days (collection issues, cash flow problems)

Accounts Payable Turnover

const ap = findAccount(bsData.liabilities.current_liabilities, 'Accounts Payable')
const cogs = findExpenseCategory(plData, 'Cost of Goods Sold')
const apTurnover = cogs / ap

// Example: 8 (Pay suppliers 8 times per year)
// Good: 6-12 for most businesses
// Warning: <4 (may indicate cash flow problems) or >15 (not utilizing credit terms)

Days Payable Outstanding (DPO)

const dpo = (ap / cogs) * 365

// Example: 46 days (Takes 46 days on average to pay suppliers)
// Good: 30-60 days (using credit terms effectively)
// Warning: >90 days (may damage supplier relationships)

Cash Conversion Cycle (CCC)

// Measures how long cash is tied up in operations
const ccc = dio + dso - dpo

// Example: 51 days (Cash tied up for 51 days before returning)
// Good: <30 days (efficient working capital management)
// Acceptable: 30-60 days
// Warning: >90 days (inefficient, needs more working capital)

5. Debt Service Coverage Ratios (P&L + Balance Sheet)

EBITDA

function calculateEBITDA(plData, bsData) {
  const netIncome = plData.net_income

  // Add back non-cash expenses
  const depreciation = findExpenseCategory(plData, 'Depreciation') || 0
  const amortization = findExpenseCategory(plData, 'Amortization') || 0

  // Add back interest and taxes
  const interestExpense = findAccountsByKeyword(plData, 'interest')
  const taxes = findExpenseCategory(plData, 'Income Taxes') || 0

  const ebitda = netIncome + interestExpense + taxes + depreciation + amortization

  return ebitda
}

// Example: $75,000 EBITDA

Debt Service Coverage Ratio (DSCR)

async function calculateDSCR(plData, bsData, annualDebtService) {
  const ebitda = calculateEBITDA(plData, bsData)
  const dscr = ebitda / annualDebtService

  return {
    ebitda,
    annualDebtService,
    dscr,
    assessment: getDSCRAssessment(dscr)
  }
}

function getDSCRAssessment(dscr) {
  if (dscr >= 2.0) return 'Excellent - Strong debt capacity'
  if (dscr >= 1.5) return 'Good - Adequate coverage'
  if (dscr >= 1.25) return 'Acceptable - Minimum coverage'
  if (dscr >= 1.0) return 'Marginal - Tight coverage'
  return 'Critical - Cannot cover debt service'
}

// Example: DSCR = 1.5 (Business generates $1.50 for every $1 of debt payments)

Interest Coverage Ratio

const interestExpense = findAccountsByKeyword(plData, 'interest')
const interestCoverage = plData.net_operating_income / interestExpense

// Example: 5.5 (Operating income covers interest 5.5 times)
// Good: >3.0 (comfortable coverage)
// Warning: <1.5 (may struggle with interest payments)
// Critical: <1.0 (cannot cover interest from operations)

Complete Credit Assessment Framework

Comprehensive Risk Scoring Model

async function comprehensiveCreditAssessment(customerId, assessmentPeriod) {
  // Fetch both statements
  const [plData, bsData] = await Promise.all([
    getProfitAndLoss(assessmentPeriod.start, assessmentPeriod.end),
    getBalanceSheet(assessmentPeriod.end)
  ])

  // Fetch historical data for trends
  const historicalPL = await getHistoricalPL(customerId, 12) // 12 months

  let assessment = {
    overallScore: 100,
    ratings: {},
    redFlags: [],
    greenFlags: [],
    recommendation: null
  }

  // 1. Profitability Assessment (20 points)
  const profitability = assessProfitability(plData, historicalPL)
  assessment.overallScore -= profitability.deduction
  assessment.ratings.profitability = profitability

  // 2. Liquidity Assessment (25 points)
  const liquidity = assessLiquidity(bsData)
  assessment.overallScore -= liquidity.deduction
  assessment.ratings.liquidity = liquidity

  // 3. Leverage Assessment (20 points)
  const leverage = assessLeverage(bsData)
  assessment.overallScore -= leverage.deduction
  assessment.ratings.leverage = leverage

  // 4. Debt Service Capacity (25 points)
  const debtCapacity = await assessDebtCapacity(plData, bsData)
  assessment.overallScore -= debtCapacity.deduction
  assessment.ratings.debtCapacity = debtCapacity

  // 5. Efficiency & Working Capital (10 points)
  const efficiency = assessEfficiency(plData, bsData)
  assessment.overallScore -= efficiency.deduction
  assessment.ratings.efficiency = efficiency

  // Compile flags
  assessment.redFlags = [
    ...profitability.redFlags,
    ...liquidity.redFlags,
    ...leverage.redFlags,
    ...debtCapacity.redFlags,
    ...efficiency.redFlags
  ]

  assessment.greenFlags = [
    ...profitability.greenFlags,
    ...liquidity.greenFlags,
    ...leverage.greenFlags,
    ...debtCapacity.greenFlags,
    ...efficiency.greenFlags
  ]

  // Final assessment
  assessment.overallScore = Math.max(0, assessment.overallScore)
  assessment.creditRating = getCreditRating(assessment.overallScore)
  assessment.recommendation = getRecommendation(assessment.overallScore, assessment.ratings)

  return assessment
}

// Profitability Assessment
function assessProfitability(plData, historicalPL) {
  let deduction = 0
  let redFlags = []
  let greenFlags = []

  // Net profit margin
  const netMargin = (plData.net_income / plData.revenue.total) * 100
  if (netMargin < 0) {
    deduction += 20
    redFlags.push({ severity: 'CRITICAL', issue: 'Business is unprofitable' })
  } else if (netMargin < 5) {
    deduction += 10
    redFlags.push({ severity: 'HIGH', issue: `Low net margin: ${netMargin.toFixed(1)}%` })
  } else if (netMargin > 15) {
    greenFlags.push(`Strong net margin: ${netMargin.toFixed(1)}%`)
  }

  // Revenue trend
  const revenueGrowth = calculateGrowthRate(historicalPL, 'revenue')
  if (revenueGrowth < -10) {
    deduction += 5
    redFlags.push({ severity: 'HIGH', issue: `Declining revenue: ${revenueGrowth.toFixed(1)}%` })
  } else if (revenueGrowth > 20) {
    greenFlags.push(`Strong revenue growth: ${revenueGrowth.toFixed(1)}%`)
  }

  return {
    deduction,
    redFlags,
    greenFlags,
    score: 20 - deduction,
    metrics: {
      netMargin,
      revenueGrowth,
      grossMargin: (plData.gross_profit / plData.revenue.total) * 100
    }
  }
}

// Liquidity Assessment
function assessLiquidity(bsData) {
  let deduction = 0
  let redFlags = []
  let greenFlags = []

  // Current ratio
  const currentRatio = bsData.assets.current_assets.total / bsData.liabilities.current_liabilities.total
  if (currentRatio < 1.0) {
    deduction += 15
    redFlags.push({ severity: 'CRITICAL', issue: `Current ratio below 1.0: ${currentRatio.toFixed(2)}` })
  } else if (currentRatio < 1.5) {
    deduction += 8
    redFlags.push({ severity: 'MEDIUM', issue: `Low current ratio: ${currentRatio.toFixed(2)}` })
  } else if (currentRatio > 2.0) {
    greenFlags.push(`Strong current ratio: ${currentRatio.toFixed(2)}`)
  }

  // Working capital
  const workingCapital = bsData.assets.current_assets.total - bsData.liabilities.current_liabilities.total
  if (workingCapital < 0) {
    deduction += 10
    redFlags.push({ severity: 'CRITICAL', issue: 'Negative working capital' })
  } else {
    const wcRatio = (workingCapital / bsData.assets.current_assets.total) * 100
    if (wcRatio > 30) {
      greenFlags.push(`Healthy working capital: ${wcRatio.toFixed(0)}% of current assets`)
    }
  }

  return {
    deduction,
    redFlags,
    greenFlags,
    score: 25 - deduction,
    metrics: {
      currentRatio,
      workingCapital,
      quickRatio: calculateQuickRatio(bsData)
    }
  }
}

// Leverage Assessment
function assessLeverage(bsData) {
  let deduction = 0
  let redFlags = []
  let greenFlags = []

  // Debt-to-equity ratio
  const debtToEquity = bsData.liabilities.total / bsData.equity.total
  if (debtToEquity > 3.0) {
    deduction += 15
    redFlags.push({ severity: 'CRITICAL', issue: `Very high debt-to-equity: ${debtToEquity.toFixed(2)}` })
  } else if (debtToEquity > 2.0) {
    deduction += 8
    redFlags.push({ severity: 'MEDIUM', issue: `High debt-to-equity: ${debtToEquity.toFixed(2)}` })
  } else if (debtToEquity < 1.0) {
    greenFlags.push(`Conservative leverage: ${debtToEquity.toFixed(2)}`)
  }

  // Debt-to-assets ratio
  const debtToAssets = (bsData.liabilities.total / bsData.assets.total) * 100
  if (debtToAssets > 70) {
    deduction += 5
    redFlags.push({ severity: 'HIGH', issue: `High debt-to-assets: ${debtToAssets.toFixed(0)}%` })
  } else if (debtToAssets < 40) {
    greenFlags.push(`Low debt-to-assets: ${debtToAssets.toFixed(0)}%`)
  }

  return {
    deduction,
    redFlags,
    greenFlags,
    score: 20 - deduction,
    metrics: {
      debtToEquity,
      debtToAssets,
      equityRatio: (bsData.equity.total / bsData.assets.total) * 100
    }
  }
}

Practical Integration Examples

Example 1: Complete Credit Check

async function performCreditCheck(customerId) {
  try {
    // Fetch current period P&L and Balance Sheet
    const endDate = new Date().toISOString().split('T')[0]
    const startDate = new Date(new Date().setMonth(new Date().getMonth() - 12))
      .toISOString().split('T')[0]

    const [plData, bsData] = await Promise.all([
      fetch(`/accounting/profit-and-loss?start_date=${startDate}&end_date=${endDate}`, {
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'x-apideck-consumer-id': customerId,
          'x-apideck-app-id': 'APP_ID',
          'x-apideck-service-id': 'quickbooks'
        }
      }).then(r => r.json()),

      fetch(`/accounting/balance-sheet?date=${endDate}`, {
        headers: {
          'Authorization': 'Bearer YOUR_API_KEY',
          'x-apideck-consumer-id': customerId,
          'x-apideck-app-id': 'APP_ID',
          'x-apideck-service-id': 'quickbooks'
        }
      }).then(r => r.json())
    ])

    // Calculate key ratios
    const ratios = {
      profitability: {
        netMargin: (plData.data.net_income / plData.data.revenue.total) * 100,
        roa: (plData.data.net_income / bsData.data.assets.total) * 100,
        roe: (plData.data.net_income / bsData.data.equity.total) * 100
      },
      liquidity: {
        currentRatio: bsData.data.assets.current_assets.total / bsData.data.liabilities.current_liabilities.total,
        quickRatio: calculateQuickRatio(bsData.data),
        workingCapital: bsData.data.assets.current_assets.total - bsData.data.liabilities.current_liabilities.total
      },
      leverage: {
        debtToEquity: bsData.data.liabilities.total / bsData.data.equity.total,
        debtToAssets: (bsData.data.liabilities.total / bsData.data.assets.total) * 100
      }
    }

    // Generate recommendation
    const recommendation = generateLendingRecommendation(ratios)

    return {
      customerId,
      assessmentDate: endDate,
      ratios,
      recommendation,
      rawData: { plData, bsData }
    }

  } catch (error) {
    console.error('Credit check failed:', error)
    throw error
  }
}

Example 2: Loan Amount Calculator

function calculateMaxLoanAmount(plData, bsData, loanTermMonths) {
  // Calculate EBITDA
  const ebitda = calculateEBITDA(plData, bsData)

  // Assume lender requires DSCR of 1.5
  const requiredDSCR = 1.5
  const maxAnnualDebtService = ebitda / requiredDSCR

  // Convert to monthly payment
  const maxMonthlyPayment = maxAnnualDebtService / 12

  // Calculate loan amount based on term and interest rate (assume 8%)
  const monthlyRate = 0.08 / 12
  const maxLoanAmount = maxMonthlyPayment * 
    ((1 - Math.pow(1 + monthlyRate, -loanTermMonths)) / monthlyRate)

  // Also check collateral availability (typically 70-80% of assets)
  const collateralBased = bsData.assets.total * 0.75

  // Use lower of the two
  const recommendedAmount = Math.min(maxLoanAmount, collateralBased)

  return {
    ebitda,
    maxAnnualDebtService,
    maxMonthlyPayment,
    cashFlowBasedLimit: maxLoanAmount,
    collateralBasedLimit: collateralBased,
    recommendedLoanAmount: recommendedAmount,
    monthlyPayment: calculateMonthlyPayment(recommendedAmount, 0.08, loanTermMonths)
  }
}

Example 3: Monitoring Dashboard

async function generateLenderDashboard(portfolioCustomers) {
  const dashboardData = await Promise.all(
    portfolioCustomers.map(async (customer) => {
      const [plData, bsData] = await Promise.all([
        getProfitAndLoss(customer.id),
        getBalanceSheet(customer.id)
      ])

      return {
        customerId: customer.id,
        name: customer.name,
        loanAmount: customer.loanAmount,
        health: {
          dscr: calculateDSCR(plData, bsData, customer.annualDebtService),
          currentRatio: bsData.assets.current_assets.total / bsData.liabilities.current_liabilities.total,
          debtToEquity: bsData.liabilities.total / bsData.equity.total
        },
        alerts: identifyAlerts(plData, bsData, customer),
        trend: customer.historicalHealth?.dscr > calculateDSCR(plData, bsData, customer.annualDebtService) ? 'declining' : 'improving'
      }
    })
  )

  return {
    totalPortfolioValue: dashboardData.reduce((sum, c) => sum + c.loanAmount, 0),
    healthyLoans: dashboardData.filter(c => c.health.dscr >= 1.5).length,
    watchList: dashboardData.filter(c => c.health.dscr < 1.5 && c.health.dscr >= 1.25),
    highRisk: dashboardData.filter(c => c.health.dscr < 1.25),
    customers: dashboardData
  }
}

Best Practices

1. Always Fetch Both Statements

// ✅ Good: Fetch in parallel for complete picture
const [plData, bsData] = await Promise.all([
  getProfitAndLoss(startDate, endDate),
  getBalanceSheet(endDate)
])

// ❌ Avoid: Using only one statement
const plData = await getProfitAndLoss(startDate, endDate)
// Missing critical balance sheet insights!

2. Use Appropriate Time Periods

// P&L: Use period matching loan term
// For 1-year loan, analyze 12+ months of P&L
const plData = await getProfitAndLoss('2024-01-01', '2024-12-31')

// Balance Sheet: Use most recent snapshot
const bsData = await getBalanceSheet('2024-12-31') // End of period

3. Combine with External Data

const creditAssessment = {
  financialRatios: calculateAllRatios(plData, bsData),
  creditScore: await getCreditScore(customerId), // External bureau
  industryBenchmarks: await getIndustryBenchmarks(customer.industry),
  paymentHistory: await getPaymentHistory(customerId)
}

Additional Resources

FAQ

Q: How often should I pull financial statements for monitoring?
A: For active loans, pull monthly Balance Sheets and quarterly P&L reports. High-risk customers may require monthly P&L monitoring.

Q: What if the Balance Sheet doesn't balance (Assets ≠ Liabilities + Equity)?
A: This indicates a data integrity issue. Contact the customer or verify the accounting system is properly closed for the period.

Q: Should I use cash or accrual accounting data?
A: Most lenders prefer accrual accounting as it provides a more accurate picture of financial health. Cash basis may understate obligations.

Q: What's more important - P&L or Balance Sheet?
A: Both are critical. P&L shows earning power; Balance Sheet shows financial strength. You need both for complete assessment.

Q: How do I handle seasonal businesses?
A: Compare year-over-year periods (Q3 2024 vs Q3 2025) rather than sequential quarters. Analyze 12+ months of data to capture full seasonal cycle.

Ready to get started?

Scale your integration strategy and deliver the integrations your customers need in record time.

Ready to get started?
Talk to an expert

Trusted by fast-moving product & engineering teams

Nmbrs
Benefex
Invoice2go by BILL
Trengo
Ponto | Isabel Group
Apideck Blog

Insights, guides, and updates from Apideck

Discover company news, API insights, and expert blog posts. Explore practical integration guides and tech articles to make the most of Apideck's platform.

ERP Integration for Fintech and SaaS: Connecting QuickBooks, NetSuite, and Sage the Smart Way
AccountingUnified APIGuides & Tutorials

ERP Integration for Fintech and SaaS: Connecting QuickBooks, NetSuite, and Sage the Smart Way

This guide explains why ERP integration is critical for fintech and SaaS platforms and why it’s often such a bottleneck. You’ll learn the key challenges of connecting QuickBooks, NetSuite, and Sage, common pitfalls that derail projects, best practices for implementation, and how unified APIs can simplify integrations, cut costs, and speed up time to market.

Kateryna Poryvay

Kateryna Poryvay

10 min read
How to Get Your OpenRouter API Key
AIGuides & Tutorials

How to Get Your OpenRouter API Key

This guide walks you through how to get your OpenRouter API key in just a few minutes. You’ll learn how to create an account, add credits, generate your key, store it securely, and also how to run a quick test to confirm everything is working.

Saurabh Rai

Saurabh Rai

2 min read
Bank Feeds API Integration: Why You Can’t Afford to Skip This Feature
Unified APIGuides & Tutorials+2 more

Bank Feeds API Integration: Why You Can’t Afford to Skip This Feature

Finance teams reject fintech products without bank feed integrations. Learn how unified APIs let you ship automated accounting sync for Xero, QuickBooks, and 20+ platforms in weeks instead of building direct integrations for 18+ months.

Saurabh Rai

Saurabh Rai

11 min read