Servicing reports
Each report answers one operating question, echoes the query it actually applied, and links back to the work behind every number it shows.
Seven reports, each answering one question a supervisor actually has this morning — where work is piling up, who has capacity, which delinquent borrowers can be contacted today, and whether the promises the team took are being kept.
A focused report
- One report, one operating question
- It shows you the query it actually ran, after its own defaults and caps
- Every number opens as the work behind it
Not a warehouse
- No general query surface with a filter panel bolted on
- returnedCount counts the rows in this response, not the population behind it
- A planning aid is never an authorization
One report, one operating question
Seven reports, and each one names its question:
| Report | Route | Answers |
|---|---|---|
| Workforce | GET /v1/servicing/reports/workforce |
Where is work piling up, and who has capacity? |
| Collections | GET /v1/servicing/reports/collections |
Which delinquent matters are contactable, and when? |
| Interaction exceptions | GET /v1/servicing/reports/interactions/exceptions |
Which channel work was missed, unmatched, or failed? |
| Compliance | GET /v1/servicing/reports/compliance |
What did policy decide, under which rules and regimes? |
| AI quality | GET /v1/servicing/reports/ai-quality |
How grounded and how reviewed is AI output? |
| Reconciliation | GET /v1/servicing/reports/reconciliation |
Where has servicing state drifted from the Lending Core? |
| Promise & allocation | GET /v1/servicing/reports/promise-allocation |
Are promises being kept, and is work reaching the people who can keep them? |
All seven take READ_SERVICING_REPORTS, accept exact structured filters plus limit/offset and sort/order, and return the same outer shape:
{
"asOf": "2027-05-05T18:30:00Z",
"effectiveQuery": { "limit": 50, "offset": 0 },
"rows": [],
"returnedCount": 0,
"hasMore": false
}
Read effectiveQuery before trusting a total: a report page is a bounded slice.
Drill-through, not a dead end
The workforce report aggregates by QUEUE or WORKER and gives each row a link straight back into the base collection:
{
"dimension": "QUEUE",
"summary": {
"openTaskCount": 18,
"activeTaskCount": 7,
"staleAcceptedTaskCount": 1,
"overdueTaskCount": 2,
"slaBreachedTaskCount": 1,
"openCaseCount": 42,
"availableWorkerCapacity": 21
},
"rows": [
{
"queueCode": "COLLECTIONS",
"openTaskCount": 18,
"overdueTaskCount": 2,
"oldestTaskAgeMinutes": 91,
"eligibleWorkerCapacity": 28,
"availableWorkerCount": 4,
"drillThrough": "/v1/servicing/tasks?queueCode=COLLECTIONS"
}
]
}
staleAccepted=true isolates accepted work that has stopped moving — the case a throughput average hides.
A planning aid is not an authorization
The collections report joins current Lending Core financial facts to servicing work state, so a row carries both the money and the permission to act on it:
{
"caseId": 1001,
"customerRef": "412",
"loanRef": "7204",
"priority": "HIGH",
"promiseState": "ACTIVE",
"financialFactsSource": "LMS",
"daysOverdue": 22,
"delinquencyBucket": "DPD_1_29",
"overdueAmount": 517.14,
"currency": "USD",
"contactIntensity": 2,
"remainingContactCapacity": 5,
"lastContactAttemptAt": "2027-05-04T21:04:00Z",
"nextPermittedContactAt": "2027-05-06T15:00:00Z",
"protectiveStateActive": false,
"contactBlocked": false
}
financialFactsSource names where the balance came from; the servicing workspace does not recompute delinquency. nextPermittedContactAt and remainingContactCapacity are planning aids from the contact budget, not authorizations — the owning operation still runs its own execution-time check immediately before contact, and can block work this report showed as permitted.
Compliance and AI-quality reports
The compliance report exposes decision outcomes with their rule and regime detail, filterable by outcome, hardStop, regime, ruleCode, channel, and proposedAction:
{
"decisionId": 6117,
"proposedAction": "OUTBOUND_CONTACT",
"channel": "PHONE",
"outcome": "ALLOWED",
"hardStop": false,
"rules": [{ "ruleCode": "CONTACT_WINDOW_CA", "regime": "REG_F", "outcome": "ALLOWED" }]
}
The AI-quality report projects retained output, grounding, runtime, and review state together — session, worker and adapter codes, autonomyLevel, runtimeVersion, policyVersion, workPacketVersion, confidence, groundingStatus, and the reviewer and review time. Because runtime and policy versions are rows rather than metadata, a quality regression can be attributed to the version that caused it instead of being averaged away.
The reconciliation report returns current servicing-to-core drift with its classification, priority, and the review task opened for it — the same row shape Reconciliation & drift works through in full.
This is the servicing-plane view. Money-movement exceptions between provider events, intents, and the ledger stay in the Lending Core catalog.
The investor report pack
Two routes serve a curated 18-report pack: GET /v1/servicing/reports/investor lists the catalog, and GET /v1/servicing/reports/investor/{reportKey} returns one report. Both accept READ_REPORT or READ_SERVICING_REPORTS.
Every response says where its numbers came from:
{
"provenance": {
"label": "Reporting snapshot",
"loadKey": "INVESTOR_V1:2027-05-05",
"sourceWatermark": "portfolio-v1:2027-05-05",
"generationMode": "SNAPSHOT_LOAD",
"nonAuthoritative": true
}
}
The pack is a snapshot load. It never reads live servicing or ledger tables, and the response says so in nonAuthoritative: true rather than in a footnote somebody might strip — reconcile against the authoritative source before publishing a figure externally.
A report renders as headline metrics, insights, a trend, a breakdown, a supporting table, and a methodology note. Metrics declare their own format (number, percent, currency) and tone, and delta/deltaLabel keys are omitted when no comparison period was supplied rather than returned as zero — a zero delta on a slide reads as no change, which is a claim about the business rather than about the absent comparison. The reportKey must come from the catalog, so an arbitrary key is rejected instead of returning an empty report that a reader would take for an empty quarter.
methodology before comparing two figures. In the collections pack, for example, promise kept-rate is count-based while dollar kept-rate is value-based, and promise dollars are never counted as collected until the cash is realized.