As a major telecom provider, your account history acts as a rich alternative credit signal. This blueprint helps your engineering and product teams design matching lookup endpoints and build FinHero-compatible source adapters to safely ingest alternative financial data.
Design a secure, low-latency subscriber payment query API. Leverage existing national-ID attributes for KYC.
Implement the lightweight mapping layer (source adapter) matching FinHero's JS/TS engine interfaces.
Ensure correctness and consistency of exported signals in local mock sandbox environments before deployment.
You don't need to install or run the full FinHero server stack to build the integration. The toolkit provides a fully offline validation suite. You implement a manifest file and mapping scripts which FinHero dynamically imports.
How subscriber identity converts to credit underwriting metrics. The mapping runs entirely inside the sandboxed FinSys execution environment using your custom mapping rules.
Your API does not need to expose a matching database scheme directly. However, your adapter must map
what your API produces into a subset of these 7 fields expected by FinHero's telco-carrier registry.
| Field Key | Data Type | Constraint / Range | Credit Scoring Interpretation |
|---|---|---|---|
| onTimePaymentRatio24m | number | ratio [0.0 - 1.0] | Fraction of bills paid on time over the last 24 months. Primary risk predictor. Values ≥0.95 signal strong history. |
| tenureMonths | number | months [0 - 600] | Account age in months. Values ≥48 months trigger scoring boosts to offset thin formal credit files. |
| suspensionsCount24m | number | count [0 - 100] | Number of suspensions triggered by non-payment in the last 24 months. Values ≥3 flag potential financial distress. |
| lateDays24m | number | days [0 - 800] | Cumulative count of days overdue across all bill cycles in the trailing 24-month window. |
| arpu | number | MYR [0 - 10000] | Average monthly bill revenue (RM). Acts as a proxy for consumer disposable spending capacity. |
| handsetFinancingActive | boolean | true / false | Indicates whether the user has an active handset installment payment plan (device EMI active). |
| handsetFinancingDelinquent | boolean | true / false | Indicates if there is an active device payment default. Flags high risk even if standard service bills are paid. |
Select a canned user persona from our fake database mockup, or customize the values in the control panel to see live calculations demonstrating how the raw API parameters translate into canonical scoring fields.
Complete reference setup code for your custom adapter module. The files must reside in the same folder and follow directory export bindings. Click on the tabs below to copy the boilerplate templates.
// manifest.json: Declares entrypoint & outputs metadata
{
"manifestVersion": 1,
"id": "telco-carrier-adapter-v1",
"displayName": "Carrier Alternative Data Integration",
"category": "telco-carrier",
"version": 1,
"produces": [
"tenureMonths",
"onTimePaymentRatio24m",
"lateDays24m",
"suspensionsCount24m",
"arpu",
"handsetFinancingActive",
"handsetFinancingDelinquent"
],
"requiredIdentityFields": [],
"implementation": {
"type": "typescript",
"entryPoint": "extract.mjs"
}
}
// extract.mjs: Queries API, transforms metrics to canonical fields
const API_URL = process.env.TELCO_UPSTREAM_URL ?? "http://api-internal.telco:4100";
const API_KEY = process.env.TELCO_API_TOKEN ?? "prod-key-token";
const adapter = {
id: "telco-carrier-adapter-v1",
category: "telco-carrier",
version: 1,
produces: [
"tenureMonths",
"onTimePaymentRatio24m",
"lateDays24m",
"suspensionsCount24m",
"arpu",
"handsetFinancingActive",
"handsetFinancingDelinquent"
],
async fetch(identity) {
if (!identity?.ic || !identity?.fullName) {
throw new Error("Missing candidate identification details: ic/fullName");
}
const res = await fetch(`${API_URL}/v1/subscribers/lookup`, {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": API_KEY
},
body: JSON.stringify({ ic: identity.ic, fullName: identity.fullName })
});
if (!res.ok) {
throw new Error(`Telco lookup connection error: HTTP ${res.status}`);
}
return res.json();
},
async extract(raw) {
const since = new Date(raw.subscriberSince);
const now = new Date();
const tenureMonths = Math.max(0, (now.getFullYear() - since.getFullYear()) * 12 + (now.getMonth() - since.getMonth()));
const history = raw.paymentHistory ?? {};
const onTime = Number(history.billsPaidOnTime ?? 0);
const late = Number(history.billsPaidLate ?? 0);
const unpaid = Number(history.billsUnpaid ?? 0);
const total = onTime + late + unpaid;
const onTimeRatio = total > 0 ? Number((onTime / total).toFixed(4)) : 0;
// Assume an average of 15 late days per late bill instance
const lateDays = late * 15;
const suspensions = Number(history.suspensions ?? (unpaid > 0 ? 1 : 0));
const handsetActive = Boolean(raw.handsetFinancing?.active ?? false);
const handsetDelinquent = Boolean(raw.handsetFinancing?.delinquent ?? false);
return [{
instanceKey: "default",
observedAt: new Date().toISOString(),
values: {
tenureMonths: tenureMonths,
onTimePaymentRatio24m: onTimeRatio,
lateDays24m: lateDays,
suspensionsCount24m: suspensions,
arpu: Number(raw.averageMonthlyArpuMyr ?? 0),
handsetFinancingActive: handsetActive,
handsetFinancingDelinquent: handsetDelinquent
}
}];
}
};
export default adapter;
// test.mjs: Standard offline verification test block
import { runFixtures } from "@finsys/adapter-toolkit";
import adapter from "./extract.mjs";
const fixtures = [
{
name: "strong-subscriber",
identity: { ihsId: 1, ic: "850101015432", fullName: "Aiman bin Hassan" },
expected: [
{
instanceKey: "default",
values: {
onTimePaymentRatio24m: 1.0,
suspensionsCount24m: 0
}
}
]
}
];
const results = await runFixtures(adapter, fixtures);
console.log(results);
if (results.some(r => !r.ok)) {
console.error("โ Offline verification suite failed");
process.exit(1);
} else {
console.log("โ
All integration fixtures passed successfully");
}
Validate your manifest mapping format and run execution simulation tests locally. Use these command recipes in your terminal console or CI/CD pipelines to ensure compliance before submission.