FH
FinHero Adapter: Social Media
SOCIAL-MEDIA INTEGRATION PLAYBOOK

Designing APIs for Business Verification Scoring

As a commerce aggregator, social profile directory, or engagement network, your public business metadata provides authenticity proof. This playbook helps you format APIs and build FinHero-compliant mappers for thin-file merchant underwriting.

Product Manager Focus

Package verified registration status, review counts, posting intervals, and sentiment scores for SME underwriting.

  • KYC Check: Cross-reference directory listings using Malaysian National ID/IC numbers.
  • Reputation factors: Map positive rating averages and account flag histories.
  • Use Case: Support business owners lacking traditional credit profiles with public verification data.

API Engineering Focus

Create the Javascript mapping script formatting public profiles into standard social variables.

  • Fetch Method: Secure directory lookups returning profile follower and review statistics.
  • Extract Method: Local script normalising negative feedback ratios and posting consistency.
  • Schema compliance: Verify output matches the `social-media` specification.

Integration & QA Focus

Test the adapter parsing correctness using lint tools and deterministic local test fixtures.

  • Validation: Schema-check configurations before integration.
  • Fixtures: Maintain local test outputs checking rating and flag mapping.
  • Sandbox: Test integrations locally alongside dockerized API instances.
๐Ÿ“ฑ

Understanding the "social-media" Category

This B2C-oriented schema validates that a business operates consistently. Follower counts are analyzed alongside engagement rates to detect invalid audiences and protect against fraudulent profiles.

๐Ÿ“Š

Data Extraction Pipeline

How social presence details convert to verification credentials. The process runs locally within the secure FinSys sandboxed execution environment.

1. FinHero Host Receives Application Identity: { IC, Name } 2. Adapter: fetch() Query Directory API POST /profiles/lookup 3. Adapter: extract() Calculate active ratios Engagement & Sentiment 4. Scoring Ingestion Canonical DB Storage ihs_alt_data_social_media
STEP 01
Trigger Application
FinHero identifies a finalized merchant profile and passes the director identity keys.
STEP 02
API Lookup Request
The adapter executes `fetch()`, querying your public directories for the business's followers and rating reviews.
STEP 03
Adapter Extract
The adapter's `extract()` method normalises negative mentions, rating averages, and active months.
STEP 04
Database Storage
Normalized fields are stored inside `ihs_alt_data_social_media` for underwriting.
๐Ÿ“‹

Canonical Social Media Fields

Your API doesn't need to match this structure directly. The adapter maps profile outputs into these 8 canonical fields.

Field Key Data Type Constraint / Range Credit Scoring Interpretation
accountTenureMonths number months [0 - 600] Age of oldest verified public profile. Proxy for merchant business continuity.
followerCount number count [0 - 100000000] Aggregate audience size. Checked alongside engagement to verify audience authenticity.
engagementRate90d number ratio [0.0 - 1.0] Average interactions per impression. Near-zero values flag bot-boosted accounts.
postingConsistency12m number ratio [0.0 - 1.0] Fraction of months with active posting. Distinguishes active companies from dormant profiles.
verifiedBusinessAccount boolean true / false Platform verification status. Confirms independent platform business verification.
customerRatingAvg number rating [0.0 - 5.0] Average customer review rating. Strong indicator for consumer-facing businesses.
negativeSentimentRatio90d number ratio [0.0 - 1.0] Fraction of negative public mentions. Elevated rates signal customer delivery issues.
accountFlags24m number count [0 - 100] Count of platform strikes/suspensions. Values ≥2 flag high risk.
๐Ÿงช

API Mapping Playground

Select a profile preset or customize values in the control panel to see live mapping calculations for public directory outputs.

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

Source Adapter Implementation

Complete template files for the Social Media mapping adapter. Implement `fetch` and `extract` methods conformant to the `social-media` category schema.

// manifest.json: Declares entrypoint & outputs metadata
{
  "manifestVersion": 1,
  "id": "social-media-adapter-v1",
  "displayName": "Social Verification Ingestion",
  "category": "social-media",
  "version": 1,
  "produces": [
    "accountTenureMonths",
    "followerCount",
    "engagementRate90d",
    "postingConsistency12m",
    "verifiedBusinessAccount",
    "customerRatingAvg",
    "negativeSentimentRatio90d",
    "accountFlags24m"
  ],
  "requiredIdentityFields": [],
  "implementation": {
    "type": "typescript",
    "entryPoint": "extract.mjs"
  }
}
// extract.mjs: Queries API, transforms metrics to canonical fields
const API_URL = process.env.FAKE_SOCIAL_API_URL ?? "http://fake-social-api:4400";
const API_KEY = process.env.FAKE_SOCIAL_API_KEY ?? "demo-key";

const round4 = (n) => Number(n.toFixed(4));
const ratio = (num, den) => (den > 0 ? round4(num / den) : 0);
const clamp01 = (n) => Math.max(0, Math.min(1, n));

const adapter = {
  id: "social-media-adapter-v1",
  category: "social-media",
  version: 1,
  produces: [
    "accountTenureMonths",
    "followerCount",
    "engagementRate90d",
    "postingConsistency12m",
    "verifiedBusinessAccount",
    "customerRatingAvg",
    "negativeSentimentRatio90d",
    "accountFlags24m"
  ],

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

  async extract(raw) {
    const profile = raw.profile ?? {};
    const posting = raw.posting12m ?? {};
    const sentiment = raw.sentiment90d ?? {};

    return [{
      instanceKey: "default",
      observedAt: new Date().toISOString(),
      values: {
        accountTenureMonths: Number(profile.accountAgeMonths ?? 0),
        followerCount: Number(profile.followers ?? 0),
        engagementRate90d: round4(Number(raw.engagement90d?.engagementRate ?? 0)),
        postingConsistency12m: clamp01(ratio(Number(posting.activeMonths ?? 0), 12)),
        verifiedBusinessAccount: Boolean(profile.verified),
        customerRatingAvg: round4(Number(raw.reviews?.avgRating ?? 0)),
        negativeSentimentRatio90d: ratio(
          Number(sentiment.negativeMentions ?? 0),
          Number(sentiment.totalMentions ?? 0)
        ),
        accountFlags24m: Number(raw.flags24m?.count ?? 0)
      }
    }];
  }
};

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

const fixtures = [
  {
    name: "aiman-hassan-social",
    identity: { ihsId: 1, ic: "850101015432", fullName: "Aiman bin Hassan" },
    expected: [
      {
        instanceKey: "default",
        values: {
          followerCount: 18500,
          verifiedBusinessAccount: true
        }
      }
    ]
  }
];

const results = await runFixtures(adapter, fixtures);
console.log(results);
if (results.some(r => !r.ok)) {
  console.error("โŒ Social Media verification failed");
  process.exit(1);
} else {
  console.log("โœ… Social Media validation 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-social-adapter
โœ“ Parsing manifest.json schema... โœ“ Resolved entry point extract.mjs โœ“ Validated categories mapping matches 'social-media' fields... โœ… Validation passed successfully!
bash โ€” run offline fixtures
$ node ./my-social-adapter/test.mjs
Running 1 fixture checks against adapter... [Fixture: aiman-hassan-social] - Followers check: 18500 - OK - Verified business check: true - OK โœ… All tests passed.
docker โ€” local sandbox deployment
$ docker compose -f examples/fake-social/docker-compose.yml up --build -d
Building fake-social-api... Creating fake-social-api-container ... done Attaching API endpoint to localhost:4400