FH
FinHero Adapter: Payments
PAYMENT-NETWORK INTEGRATION PLAYBOOK

Designing APIs for Alternative Credit Scoring

As a merchant-side payment processor, POS network, or checkout gateway, your transaction flow signals provide verifiable revenue indicators. This blueprint helps your team design lookup endpoints and write FinHero-compliant source adapters for merchant transactional scoring.

Product Manager Focus

Package transaction volume stability, dispute rates, and tenure metrics for business credit underwriting.

  • Merchant ID: Query using business registration keys or director IC numbers.
  • Underwriting signals: Expose monthly transaction averages and dispute rates.
  • Value Proposition: Help SME merchants secure faster capital based on payment history.

API Engineering Focus

Create the lightweight adapter mapping payment gateway responses into FinHero canonical types.

  • Fetch Method: Query merchant metrics from internal billing servers securely.
  • Extract Method: Local deterministic mapper for monthly volume ratios.
  • Compliance: Ensure output matches the `payment-network` schema.

Integration & QA Focus

Ensure correct payload mapping using local validation manifests and offline suite fixtures.

  • Compliance: Validate fields against core JSON-schema files.
  • Local Mocking: Run local compose suites mapping mock merchant credentials.
  • Continuous Integration: Hook validations into standard git commit workflows.
๐Ÿ’ณ

Understanding the "payment-network" Category

This schema measures POS or gateway settlement flows in Malaysian Ringgit (MYR). It establishes the actual merchant inbound capital velocity over 3-month and 12-month periods to assess loan affordability.

๐Ÿ“Š

Data Extraction Pipeline

How merchant identification maps to transaction velocity metrics. The process runs locally within the secure FinHero adapter orchestration layer.

1. FinHero Host Receives SME Request Identity: { IC, Name } 2. Adapter: fetch() Query Gateway API POST /merchants/lookup 3. Adapter: extract() Translate volume arrays Format metrics values 4. Ingestion Registry Canonical DB Storage ihs_alt_data_payments
STEP 01
Trigger Application
FinHero identifies a finalized merchant application and passes the primary identity fields (IC/Name).
STEP 02
API Lookup Request
The adapter executes `fetch()`, calling your secure merchant portal API to obtain raw monthly statements.
STEP 03
Adapter Extract
The adapter's `extract()` method normalizes ARPU stability coefficients, dispute percentages, and active months.
STEP 04
Database Storage
Normalized fields are stored inside `ihs_alt_data_payments` for evaluation by the risk assessment engine.
๐Ÿ“‹

Canonical Payment Fields

Your API does not need to expose a matching schema directly. However, your adapter must translate your raw API variables into a subset of these 6 fields.

Field Key Data Type Constraint / Range Credit Scoring Interpretation
monthlyVolume3m number MYR [0.0 - 100000000.0] Average monthly inbound volume in MYR over the trailing 3 months. Highlights recent trade trends.
monthlyVolume12m number MYR [0.0 - 100000000.0] Average monthly inbound volume in MYR over the trailing 12 months. Establishes long-term capacity.
arpuStability12m number ratio [0.0 - 1.0] Coefficient-of-variation inverse of monthly volume. Value close to 1 indicates stable, predictable sales.
disputeRate12m number ratio [0.0 - 1.0] Fraction of transactions disputed or refunded. Higher rates suggest chargeback and operational risks.
customerConcentrationTop5Pct number ratio [0.0 - 1.0] Revenue share of top 5 customers. Ratios above 0.70 flag elevated customer dependency risk.
activeTenureMonths number months [0 - 600] Months since the merchant's first processed transaction. Proxy for business maturity.
๐Ÿงช

API Mapping Playground

Select a preset merchant persona from the reference dataset, or adjust custom sliders in the control panel to see how raw payment responses map into canonical credit risk metrics.

Inputs Controls interactive
MERCHANT_API_PAYLOAD.JSON Upstream Raw
โž”
extract()
CANONICAL_EXTRACTION.JSON Adapter Output
๐Ÿ’ป

Source Adapter Implementation

Reference configurations for the Payments mapping adapter. Implement `fetch` and `extract` methods conformant to the `payment-network` schema specifications.

// manifest.json: Declares entrypoint & outputs metadata
{
  "manifestVersion": 1,
  "id": "payments-network-adapter-v1",
  "displayName": "Gateway Transaction Ingestion",
  "category": "payment-network",
  "version": 1,
  "produces": [
    "monthlyVolume3m",
    "monthlyVolume12m",
    "arpuStability12m",
    "disputeRate12m",
    "customerConcentrationTop5Pct",
    "activeTenureMonths"
  ],
  "requiredIdentityFields": [],
  "implementation": {
    "type": "typescript",
    "entryPoint": "extract.mjs"
  }
}
// extract.mjs: Queries API, transforms metrics to canonical fields
const API_URL = process.env.FAKE_PAYMENTS_API_URL ?? "http://fake-payments-api:4200";
const API_KEY = process.env.FAKE_PAYMENTS_API_KEY ?? "demo-key";

const adapter = {
  id: "payments-network-adapter-v1",
  category: "payment-network",
  version: 1,
  produces: [
    "monthlyVolume3m",
    "monthlyVolume12m",
    "arpuStability12m",
    "disputeRate12m",
    "customerConcentrationTop5Pct",
    "activeTenureMonths"
  ],

  async fetch(identity) {
    if (!identity?.ic || !identity?.fullName) {
      throw new Error("fake-payments-v1: identity.ic and identity.fullName are required");
    }
    const res = await fetch(`${API_URL}/v1/merchants/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(`fake-payments-v1 fetch failed: HTTP ${res.status}`);
    }
    return res.json();
  },

  async extract(raw) {
    const metrics = raw.paymentsMetrics ?? {};
    return [{
      instanceKey: "default",
      observedAt: new Date().toISOString(),
      values: {
        monthlyVolume3m: Number(metrics.monthlyVolumeMyrT3 ?? 0),
        monthlyVolume12m: Number(metrics.monthlyVolumeMyrT12 ?? 0),
        arpuStability12m: Number(metrics.arpuStability12m ?? 0),
        disputeRate12m: Number(metrics.disputeRate12m ?? 0),
        customerConcentrationTop5Pct: Number(metrics.customerConcentrationTop5Pct ?? 0),
        activeTenureMonths: Number(metrics.activeTenureMonths ?? 0)
      }
    }];
  }
};

export default adapter;
// test.mjs: Offline verification tests
import { runFixtures } from "@finsys/adapter-toolkit";
import adapter from "./extract.mjs";

const fixtures = [
  {
    name: "hassan-trading",
    identity: { ihsId: 1, ic: "850101015432", fullName: "Aiman bin Hassan" },
    expected: [
      {
        instanceKey: "default",
        values: {
          activeTenureMonths: 38,
          monthlyVolume3m: 285000
        }
      }
    ]
  }
];

const results = await runFixtures(adapter, fixtures);
console.log(results);
if (results.some(r => !r.ok)) {
  console.error("โŒ Payments test suite failed");
  process.exit(1);
} else {
  console.log("โœ… Payments metrics verification passed!");
}
๐Ÿ› ๏ธ

Testing & Validation Run Commands

Validate manifest schemas and test mapping logic locally using the CLI or docker configurations.

bash โ€” manifest validation
$ npx finsys-adapter-toolkit validate ./my-payments-adapter
โœ“ Parsing manifest.json schema... โœ“ Resolved entry point extract.mjs โœ“ Validated categories mapping matches 'payment-network' fields... โœ… Validation passed successfully!
bash โ€” run offline fixtures
$ node ./my-payments-adapter/test.mjs
Running 1 fixture checks against adapter... [Fixture: hassan-trading] - Tenure check: 38 - OK - Volume T3 check: 285000 - OK โœ… All tests passed.
docker โ€” local sandbox deployment
$ docker compose -f examples/fake-payments/docker-compose.yml up --build -d
Building fake-payments-api... Creating fake-payments-api-container ... done Attaching API endpoint to localhost:4200