CredAIOpen the demo
v1OpenAPI 3.1credai-scorecard-2.0.0

API reference

Score anyone from raw alternative data with one request, or connect CredAI to your own data service and use the lender console on top of it.

openapi.jsonSource on GitHub

Endpoints

Score a customer

A CustomerRecord holds whatever raw history the customer agreed to share. Every source is optional; missing ones lower confidence rather than failing the request. Arrays are trimmed here — a full, valid example lives in examples/customer-record.json.

Request · POST /api/v1/score
{
  "customer": {
    "customerId": "cus_ix60001",
    "displayName": "Ayesha Khan",
    "city": "Lahore",
    "segment": "Freelancer",
    "asOf": "2026-09-30",
    "declaredMonthlyIncome": 120000,
    "consent": {
      "utility": true,
      "telecom": true,
      "wallet": true,
      "bank": true,
      "credit": true
    },
    "utility": {
      "accountRef": "LESCO-74029367",
      "bills": [
        {
          "provider": "LESCO",
          "kind": "electricity",
          "issuedAt": "2026-09-04",
          "dueDate": "2026-09-18",
          "paidAt": "2026-09-18",
          "amount": 12260
        },
        {
          "provider": "SNGPL",
          "kind": "gas",
          "issuedAt": "2026-09-04",
          "dueDate": "2026-09-18",
          "paidAt": "2026-09-18",
          "amount": 1940
        }
      ]
    },
    "telecom": {
      "operator": "Zong",
      "accountOpenedAt": "2020-06-28",
      "payments": [
        {
          "date": "2026-07-27",
          "amount": 200,
          "kind": "recharge",
          "status": "success"
        },
        {
          "date": "2026-08-14",
          "amount": 350,
          "kind": "recharge",
          "status": "success"
        }
      ]
    },
    "wallet": {
      "provider": "Easypaisa",
      "transactions": [
        {
          "date": "2026-09-21",
          "amount": 7800,
          "direction": "out",
          "status": "failed",
          "balanceAfter": 3950,
          "counterparty": "Bill payment"
        },
        {
          "date": "2026-09-28",
          "amount": 5000,
          "direction": "out",
          "status": "failed",
          "balanceAfter": 3950,
          "counterparty": "Transfer"
        }
      ]
    },
    "bank": {
      "institution": "Indus Savings Bank",
      "transactions": [
        {
          "date": "2026-09-25",
          "amount": 6000,
          "direction": "out",
          "category": "Medical",
          "balanceAfter": 378200
        },
        {
          "date": "2026-09-26",
          "amount": 11050,
          "direction": "out",
          "category": "Food",
          "balanceAfter": 367150
        }
      ]
    }
  },
  "loan": {
    "amount": 150000,
    "tenureMonths": 12,
    "purpose": "Laptop"
  }
}
Response · 200
{
  "report": {
    "customerId": "cus_ix60001",
    "displayName": "Ayesha Khan",
    "asOf": "2026-09-30",
    "modelVersion": "credai-scorecard-2.0.0",
    "score": 691,
    "grade": "B",
    "gradeLabel": "Good",
    "repaymentProbability": 0.8413,
    "baseScore": 666,
    "helping": [
      {
        "key": "utility_on_time_ratio",
        "label": "Utility bills paid on time",
        "source": "utility",
        "value": 0.8333,
        "display": "83%",
        "points": 49.7,
        "missing": false,
        "reason": "Paid 20 of 24 utility bills on or before the due date."
      }
    ],
    "hurting": [
      {
        "key": "telecom_active_ratio",
        "label": "Mobile account activity",
        "source": "telecom",
        "value": 0.6667,
        "display": "67%",
        "points": -22.3,
        "missing": false,
        "reason": "Mobile account was topped up in 8 of the last 12 months."
      }
    ],
    "sources": {
      "utility": true,
      "telecom": true,
      "wallet": true,
      "bank": true,
      "credit": false
    },
    "missingSources": [
      "credit"
    ],
    "confidence": "High",
    "features": {
      "utility_on_time_ratio": 0.8333,
      "utility_unpaid_ratio": 0,
      "utility_months_observed": 12,
      "telecom_active_ratio": 0.6667,
      "telecom_tenure_months": 75,
      "telecom_failed_rate": 0.05,
      "wallet_active_ratio": 0.9167,
      "wallet_failed_rate": 0.24,
      "wallet_buffer_ratio": 0.4725,
      "income_regularity": 0.7487,
      "cash_flow_coverage": 1.1074,
      "expense_volatility": 0.2133,
      "negative_balance_days": 0,
      "buffer_months": 2.2699,
      "repayment_on_time_ratio": null,
      "repayment_avg_days_late": null,
      "data_coverage": 0.8
    },
    "contributions": [
      {
        "key": "utility_on_time_ratio",
        "label": "Utility bills paid on time",
        "source": "utility",
        "value": 0.8333,
        "display": "83%",
        "points": 49.7,
        "missing": false,
        "reason": "Paid 20 of 24 utility bills on or before the due date."
      },
      {
        "key": "telecom_active_ratio",
        "label": "Mobile account activity",
        "source": "telecom",
        "value": 0.6667,
        "display": "67%",
        "points": -22.3,
        "missing": false,
        "reason": "Mobile account was topped up in 8 of the last 12 months."
      }
    ]
  },
  "decision": {
    "recommendation": "approve",
    "tier": "reviewed",
    "requiresHumanReview": true,
    "checks": [
      {
        "id": "score",
        "label": "Credit score",
        "status": "pass",
        "detail": "691 vs approve ≥ 660, decline < 560"
      },
      {
        "id": "affordability",
        "label": "Debt-to-income",
        "status": "pass",
        "detail": "13% of income vs 40% limit"
      }
    ],
    "affordability": {
      "monthlyIncome": 111300,
      "incomeSource": "bank",
      "existingObligations": 0,
      "installment": 14476,
      "debtToIncome": 0.13,
      "maxAffordableAmount": 461000
    }
  },
  "meta": {
    "model": "credai-scorecard-2.0.0",
    "digest": "d3ae086d25b32109"
  }
}
Validation error · 422
{
  "error": "invalid_customer_record",
  "issues": [
    {
      "path": "customer.utility.bills.3.dueDate",
      "message": "Expected an ISO-8601 date (YYYY-MM-DD…)"
    }
  ]
}

Connect your data

Implement three read endpoints that return the same contract, then point CredAI at them. The lender console, customer app and model card switch over with no code changes.

Your service
GET /customers        → CustomerRecord[] | { data: CustomerRecord[] }
GET /customers/{id}   → CustomerRecord
GET /applications     → Application[]   (optional, 404 = none)

Authorization: Bearer <CREDAI_DATA_API_KEY>
.env.local
CREDAI_DATA_PROVIDER=http
CREDAI_DATA_API_URL=https://data.your-bank.example/v1
CREDAI_DATA_API_KEY=...
CREDAI_DATA_REVALIDATE=60   # seconds to cache upstream reads
Try it locally with the bundled mock partner API
npm run mock:api          # serves 40 different customers on :4010
CREDAI_DATA_PROVIDER=http CREDAI_DATA_API_URL=http://localhost:4010 CREDAI_DATA_API_KEY=dev-key npm run dev

Retrain on real outcomes

The training script runs the production feature engine over raw records and writes the artifact the app loads. Replace the synthetic generator with your labelled history and rerun it.

npm run model:train            # writes src/lib/model/artifact.json + evaluation.json
npm test                       # feature, scoring, policy and provider tests