OpenSylo's data ingestion API allows marketplaces to submit merchant performance data for credit scoring and loan eligibility calculation. When you submit data, OpenSylo processes it through its credit scoring engine and returns a score, risk tier, and lending cap in the response.
Endpoint: POST /api/marketplace/data/merchant
Required scope: data.share.sales
Required headers:
| Header | Description |
|---|---|
Authorization | Bearer <access_token> |
Content-Type | application/json |
The MerchantDataRequest payload contains eight sections:
| Section | Required | Description |
|---|---|---|
merchantIdentity | Yes | Business info, onboarding date, verification status |
salesPerformance | Yes | GMV (30/90/180 day), order counts, growth rate |
revenueConsistency | Yes | Monthly variance, zero-sales months, sales streaks |
fulfillmentMetrics | Yes | Fulfillment rate, cancellation/refund/dispute rates |
payoutCashFlow | Yes | Payout frequency, average payout value, failed payouts |
platformDependency | Yes | Top product and top customer concentration |
historicalCredit | No | Previous advances, repayment rate, defaults |
behavioralRisk | Yes | Suspensions, fraud flags, GMV spike rate |
monthlySalesHistory | No | 6-month GMV history for loan eligibility (see below) |
curl -X POST https://api.opensylo.com/api/marketplace/data/merchant \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"merchantIdentity": {
"merchantId": "merch_001",
"businessName": "Adaeze Fashion Store",
"businessType": "RETAIL",
"marketplaceOnboardingDate": "2024-06-15T00:00:00.000Z",
"verificationStatus": true,
"location": "Lagos, Nigeria",
"country": "NG",
"category": "clothing"
},
"salesPerformance": {
"gmv30Days": 1200000,
"gmv90Days": 3500000,
"gmv180Days": 6800000,
"avgMonthlySales": 1133333,
"orderCount": 450,
"avgOrderValue": 15111,
"salesGrowthRate": 12.5
},
"revenueConsistency": {
"monthlySalesVariance": 15,
"zeroSalesMonths": 0,
"longestSalesStreak": 18,
"revenueConcentration": 25
},
"fulfillmentMetrics": {
"fulfillmentRate": 96,
"cancellationRate": 2.5,
"refundRate": 1.8,
"refundAmount": 21600,
"disputeRate": 0.5,
"lateDeliveryRate": 3.0
},
"payoutCashFlow": {
"payoutFrequency": "WEEKLY",
"avgPayoutValue": 280000,
"failedPayouts": 0,
"walletBalanceUsage": 50000,
"settlementDelays": 0
},
"platformDependency": {
"topProductGmvPercentage": 18,
"topCustomerPercentage": 8
},
"historicalCredit": {
"previousAdvances": 1,
"repaymentRate": 100,
"daysPastDue": 0,
"hasDefaults": false,
"earlyRepayments": 1
},
"behavioralRisk": {
"accountSuspensions": 0,
"policyViolationsSeverity": null,
"hasFraudFlags": false,
"hasSuddenGmvSpikes": false,
"gmvSpikeMonthsPercent": 0,
"hasLinkedAccounts": false
},
"marketplaceId": "your_marketplace_uuid",
"dataTimestamp": "2026-01-29T10:00:00.000Z",
"correlationId": "corr_batch_20260129"
}'
const response = await fetch("https://api.opensylo.com/api/marketplace/data/merchant", {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
merchantIdentity: {
merchantId: "merch_001",
businessName: "Adaeze Fashion Store",
businessType: "RETAIL",
marketplaceOnboardingDate: "2024-06-15T00:00:00.000Z",
verificationStatus: true,
location: "Lagos, Nigeria",
country: "NG",
category: "clothing",
},
salesPerformance: {
gmv30Days: 1200000,
gmv90Days: 3500000,
gmv180Days: 6800000,
avgMonthlySales: 1133333,
orderCount: 450,
avgOrderValue: 15111,
salesGrowthRate: 12.5,
},
revenueConsistency: {
monthlySalesVariance: 15,
zeroSalesMonths: 0,
longestSalesStreak: 18,
revenueConcentration: 25,
},
fulfillmentMetrics: {
fulfillmentRate: 96,
cancellationRate: 2.5,
refundRate: 1.8,
refundAmount: 21600,
disputeRate: 0.5,
lateDeliveryRate: 3.0,
},
payoutCashFlow: {
payoutFrequency: "WEEKLY",
avgPayoutValue: 280000,
failedPayouts: 0,
},
platformDependency: {
topProductGmvPercentage: 18,
topCustomerPercentage: 8,
},
behavioralRisk: {
accountSuspensions: 0,
hasFraudFlags: false,
hasSuddenGmvSpikes: false,
gmvSpikeMonthsPercent: 0,
hasLinkedAccounts: false,
},
marketplaceId: "your_marketplace_uuid",
dataTimestamp: new Date().toISOString(),
correlationId: `corr_${Date.now()}`,
}),
});
const result = await response.json();
// result.creditScore contains the scoring result
// result.loanEligibility is present when monthlySalesHistory was provided
{
"success": true,
"message": "Merchant data processed successfully",
"transactionId": "txn_uuid",
"creditScore": {
"totalScore": 81,
"riskTier": "A",
"maxLendingCap": 906666,
"eligiblePercentage": 80,
"scoreBreakdown": {
"salesCount": 35,
"revenueConsistency": 9,
"fulfillmentOps": 7,
"stabilityTenure": 10,
"riskBehavior": 10,
"riskBonus": 10
},
"lendingImplication": "Highest cap, best pricing",
"calculatedAt": "2026-01-29T10:00:05.000Z",
"recommendations": "Excellent credit profile. Consider premium lending products."
},
"processedAt": "2026-01-29T10:00:05.000Z",
"nextRefreshDate": "2026-02-28T10:00:00.000Z"
}
When you include the optional monthlySalesHistory array, OpenSylo calculates a loan eligibility result in addition to the credit score. This determines the maximum loan amount the merchant qualifies for based on their recent revenue capacity.
gmv (monthly gross merchandise value in Naira) and orderCountmonthLabel (e.g., "2025-11") for reference{
"merchantIdentity": { "..." : "..." },
"salesPerformance": { "..." : "..." },
"revenueConsistency": { "..." : "..." },
"fulfillmentMetrics": { "..." : "..." },
"payoutCashFlow": { "..." : "..." },
"platformDependency": { "..." : "..." },
"behavioralRisk": { "..." : "..." },
"monthlySalesHistory": [
{ "gmv": 950000, "orderCount": 380, "monthLabel": "2025-08" },
{ "gmv": 1020000, "orderCount": 410, "monthLabel": "2025-09" },
{ "gmv": 1100000, "orderCount": 430, "monthLabel": "2025-10" },
{ "gmv": 1050000, "orderCount": 420, "monthLabel": "2025-11" },
{ "gmv": 1250000, "orderCount": 460, "monthLabel": "2025-12" },
{ "gmv": 1200000, "orderCount": 450, "monthLabel": "2026-01" }
],
"marketplaceId": "your_marketplace_uuid",
"dataTimestamp": "2026-01-29T10:00:00.000Z"
}
When monthlySalesHistory is provided, the response includes a loanEligibility object:
{
"success": true,
"creditScore": { "..." : "..." },
"loanEligibility": {
"avgMonthlyGmv": 1095000,
"avgMonthlyOrders": 425,
"aov": 2576.47,
"gmvTrendPercent": 26.32,
"gmvVolatilityCov": 0.0963,
"monthlyRepaymentCapacity": 273750,
"totalRepaymentCapacity": 1642500,
"maxEligibleLoan": 1265384.62,
"totalRepaymentForMaxLoan": 1645000,
"monthlyRepaymentForMaxLoan": 274166.67,
"policyParameters": {
"repaymentRate": 0.25,
"tenorMonths": 6,
"monthlyInterestRate": 0.05
},
"calculatedAt": "2026-01-29T10:00:05.000Z"
},
"processedAt": "2026-01-29T10:00:05.000Z"
}
| Field | Description |
|---|---|
avgMonthlyGmv | Average monthly GMV across the 6 months |
avgMonthlyOrders | Average monthly order count across the 6 months |
aov | Average order value (avgMonthlyGmv / avgMonthlyOrders) |
gmvTrendPercent | Percentage change from month 1 (oldest) to month 6 (newest). Positive = growth, negative = decline. |
gmvVolatilityCov | Coefficient of variation (sample std dev / mean). Lower values indicate more stable revenue. |
maxEligibleLoan | Maximum loan amount the merchant qualifies for, based on repayment capacity and policy parameters |
policyParameters.repaymentRate | Fraction of monthly GMV allocated to repayment (default: 0.25 = 25%) |
policyParameters.tenorMonths | Loan tenor in months (default: 6) |
policyParameters.monthlyInterestRate | Monthly interest rate (default: 0.05 = 5%) |
For submitting data for multiple merchants at once, use the async bulk endpoint.
Endpoint: POST /api/marketplace/data/merchants/bulk
Required scope: data.share.sales
This endpoint accepts an array of merchant data payloads and processes them asynchronously. It returns HTTP 202 Accepted with a batchId you can use to poll for status.
curl -X POST https://api.opensylo.com/api/marketplace/data/merchants/bulk \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"merchants": [
{ "merchantIdentity": { "..." : "..." }, "salesPerformance": { "..." : "..." }, "..." : "..." },
{ "merchantIdentity": { "..." : "..." }, "salesPerformance": { "..." : "..." }, "..." : "..." }
],
"marketplaceId": "your_marketplace_uuid",
"batchTimestamp": "2026-01-29T10:00:00.000Z",
"batchId": "batch_20260129_001"
}'
{
"success": true,
"message": "Batch accepted for processing",
"batchId": "batch_20260129_001",
"jobId": "job_uuid",
"totalMerchants": 50,
"status": "pending",
"statusUrl": "/api/marketplace/data/batch/batch_20260129_001/status",
"submittedAt": "2026-01-29T10:00:01.000Z"
}
Endpoint: GET /api/marketplace/data/batch/{batchId}/status
async function pollBatchStatus(
batchId: string,
accessToken: string
): Promise<BatchStatusResponse> {
const maxAttempts = 30;
const pollIntervalMs = 5000; // 5 seconds
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const response = await fetch(
`https://api.opensylo.com/api/marketplace/data/batch/${batchId}/status`,
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const status = await response.json();
if (status.status === "completed" || status.status === "failed") {
return status;
}
// Still processing -- wait before next poll
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
}
throw new Error(`Batch ${batchId} did not complete within timeout`);
}
// Usage
const result = await pollBatchStatus("batch_20260129_001", accessToken);
console.log(`Processed: ${result.successCount}, Failed: ${result.failedCount}`);
{
"batchId": "batch_20260129_001",
"status": "completed",
"totalMerchants": 50,
"submittedAt": "2026-01-29T10:00:01.000Z",
"completedAt": "2026-01-29T10:02:30.000Z",
"successCount": 48,
"failedCount": 2,
"results": [
{
"merchantId": "merch_049",
"status": "failed",
"error": "salesPerformance.gmv30Days must not be less than 0"
}
]
}
Maximum batch size: 1,000 merchants per request. For larger datasets, split into multiple batches.
The credit score is a composite score from 0 to 100. Each component has a maximum contribution:
| Component | Max Score | What It Measures |
|---|---|---|
salesCount | 60 | Sales growth rate and order volume |
revenueConsistency | 10 | Monthly variance, zero-sales months, sales streaks |
fulfillmentOps | 10 | Fulfillment rate, cancellation/refund/dispute rates |
stabilityTenure | 10 | Account age, verification status, industry |
riskBehavior | 10 | Suspensions, fraud flags, GMV spike rate, linked accounts |
| Perfect-record bonus | +10 | Added to the TOTAL when conduct is clean (see below) |
The five component caps sum to exactly 100. The perfect-record bonus is extra
headroom applied to the total before the 0-100 clamp, so a clean-record merchant
can reach 100 without maxing every component. There is no scored
payoutCashFlow component — that slot is reserved but deliberately unscored.
| Tier | Score Range | Risk Level | Lending Implication |
|---|---|---|---|
| A | 80 -- 100 | Low | Highest cap, best pricing |
| B | 65 -- 79 | Low | Standard cap |
| C | 50 -- 64 | Medium | Reduced cap, short tenor |
| D | 35 -- 49 | High | Pilot / small ticket only |
| E | 0 -- 34 | Very High | Not eligible |
The maxLendingCap is derived from the merchant's average monthly sales multiplied by the tier's eligible percentage:
| Tier | Eligible % | Example (NGN 1M avg monthly) |
|---|---|---|
| A | 40% | NGN 400,000 |
| B | 30% | NGN 300,000 |
| C | 20% | NGN 200,000 |
| D | 10% | NGN 100,000 |
| E | 0% | NGN 0 |
When monthlySalesHistory is provided and loan eligibility is calculated, the maxLendingCap is overwritten with the maxEligibleLoan value from the eligibility calculation (which factors in repayment capacity, tenor, and interest rates).
OpenSylo supports two data paths into the credit scoring engine. Both produce the same credit score and loan eligibility outputs.
The marketplace submits a complete, pre-aggregated data snapshot via POST /api/marketplace/data/merchant. The scoring engine processes it synchronously and returns the credit score in the response. This is ideal when the marketplace already computes aggregate metrics internally.
The marketplace sends individual events as they happen via the sales events, repayment events, and account flags endpoints. OpenSylo automatically aggregates these events and feeds the result into the same scoring engine. This happens asynchronously:
Minimum requirements for event-based scoring:
Submit individual sales transactions that feed into credit scoring.
Endpoint: POST /api/marketplace/sales-events
Required scope: sales.write
Each event type affects different components of the credit score:
SALE — Completed sale transactionThe primary driver of credit scoring. SALE events affect 4 of 6 score components:
| Score Component | Max Points | How SALE Events Are Used |
|---|---|---|
| Sales Count | 60 | gross_amount is summed over 30/90/180-day windows to compute GMV. Order volume and growth rate are derived. |
| Revenue Consistency | 10 | Monthly GMV variance (coefficient of variation), zero-sales months, and longest consecutive sales streak are computed from the monthly grouping of SALE events. |
| Loan Eligibility | — | Monthly GMV and order counts from SALE events form the 6-month history used to calculate maxEligibleLoan. |
Sales Count scoring thresholds:
| Metric | Points | Thresholds |
|---|---|---|
| Sales Growth Rate | 0–20 | >20%: 20, >10%: 15, >5%: 10, >0%: 5, >-5%: 1 |
| Order Volume | 0–40 | >1000: 40, >500: 30, >100: 20, >50: 10, >5: 5 |
Order volume prefers avgMonthlyOrders (trailing-6-month mean) and falls back to
orderCount only when that is absent or zero. avgMonthlySales and
avgOrderValue are not scored — they are still ingested and used for the
lending cap, but they contribute no points.
Revenue Consistency scoring thresholds:
| Metric | Points | Thresholds |
|---|---|---|
| Monthly Sales Variance | 0–5 | <10%: 5, <20%: 4, <30%: 2, <50%: 1 |
| Longest Sales Streak | 0–5 | ≥12mo: 5, ≥6mo: 4, ≥3mo: 3, ≥1mo: 1 |
| Zero-Sales Months | -0 to -3 | Penalty of 1 per zero month (max -3) |
REFUND — Refund issued to buyer| Score Component | Max Points | How REFUND Events Are Used |
|---|---|---|
| Fulfillment Ops | 10 | refundRate = (REFUND count / SALE count) × 100. Combined with disputeRate for a joint threshold check. refundAmount = sum of gross_amount from all REFUND events. |
| Risk Flags | — | If refundRate > 10%, the flag HIGH_REFUND_RATE is raised. |
CANCELLATION — Order cancelled before fulfillment| Score Component | Max Points | How CANCELLATION Events Are Used |
|---|---|---|
| Fulfillment Ops | 10 | cancellationRate = (CANCELLATION count / SALE count) × 100. Also used to compute fulfillmentRate = 100 - cancellationRate - refundRate. |
Fulfillment Ops scoring thresholds:
| Metric | Points | Thresholds |
|---|---|---|
| Fulfillment Rate | 0–6 | ≥98%: 6, ≥95%: 5, ≥90%: 4, ≥85%: 3, ≥80%: 2 |
| Cancellation Rate | 0–2 | <2%: 2, <5%: 1, <10%: 1, <15%: 1 |
| Refund + Dispute Rate | 0–2 | refund<1% & dispute<1%: 2, refund<3% & dispute<2%: 1, refund<5% & dispute<5%: 0 |
lateDeliveryRate is ingested but not scored.
CHARGEBACK — Payment dispute resolved in buyer's favor| Score Component | Max Points | How CHARGEBACK Events Are Used |
|---|---|---|
| Fulfillment Ops | 10 | disputeRate = (CHARGEBACK count / SALE count) × 100. Combined with refundRate for joint scoring. |
| Risk Flags | — | If disputeRate > 5%, the flag HIGH_DISPUTE_RATE is raised. |
ADJUSTMENT — Manual adjustmentStored for audit purposes. Does not currently affect credit scoring.
curl -X POST https://api.opensylo.com/api/marketplace/sales-events \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_id": "evt_sale_20260407_001",
"platform_merchant_id": "PLT_MERCH_001",
"event_type": "SALE",
"event_date": "2026-04-07T14:30:00.000Z",
"order_id": "ORD-2026-12345",
"customer_id": "CUST_001",
"gross_amount": 45000,
"net_amount": 42750,
"commission_amount": 2250,
"currency": "NGN",
"payment_method": "card",
"items": [{ "name": "Ankara Dress", "quantity": 1, "price": 45000 }],
"idempotency_key": "sale_evt_20260407_12345"
}'
The idempotency_key prevents duplicate processing. If you send the same key twice, the second request returns the original result without creating a duplicate event.
Report loan repayment collections from merchant sales.
Endpoint: POST /api/marketplace/repayment-events
Required scope: repayments.write
| Type | Description |
|---|---|
COLLECTION | A repayment amount collected from a sale |
DEDUCTION | A repayment deducted from merchant settlement |
REFUND | A repayment refunded back to the merchant |
REVERSAL | A previously collected repayment reversed |
Repayment events do not directly contribute points to the credit score. However, each repayment event triggers a credit score recalculation using the latest sales event data. This means:
curl -X POST https://api.opensylo.com/api/marketplace/repayment-events \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_id": "evt_repay_20260407_001",
"platform_merchant_id": "PLT_MERCH_001",
"event_type": "COLLECTION",
"collection_date": "2026-04-07",
"loan_id": "loan_f1e2d3c4-b5a6-7890-1234-567890abcdef",
"scheduled_amount": 5000,
"collected_amount": 5000,
"outstanding_amount": 1375000,
"currency": "NGN",
"collection_reference": "COL-20260407-001",
"payment_reference": "FLW-COL-20260407-001",
"collection_method": "sales_deduction",
"idempotency_key": "idem_repay_20260407_001"
}'
Report account-level risk events that directly affect a merchant's credit score.
Endpoint: POST /api/marketplace/account-flags
Required scope: account.flags.write
Account flags feed into the Risk Behavior score component (max 10 points). The risk behavior score starts at 10 and is reduced by penalties:
| Flag Type | Scoring Impact |
|---|---|
ACCOUNT_SUSPENDED | -2 points per suspension (max -5 total). Each active suspension flag directly reduces the score. |
FRAUD_SUSPECTED | -3 points. Any active fraud flag triggers this penalty. |
POLICY_VIOLATION | Stored as context. Does not directly reduce points (the calculator does not consume policyViolationsSeverity), but signals risk to human reviewers. |
HIGH_CHARGEBACK_RATE | Stored as context. The chargeback impact comes from CHARGEBACK sales events instead. |
HIGH_REFUND_RATE | Stored as context. The refund impact comes from REFUND sales events instead. |
ACCOUNT_CLOSED | Stored as context. |
PAYMENT_DELAY | Stored as context. |
UNDERPERFORMANCE | Stored as context. |
VERIFICATION_PENDING | Stored as context. |
VERIFICATION_FAILED | Stored as context. |
GOOD_STANDING | Stored as context (positive signal). |
TOP_PERFORMER | Stored as context (positive signal). |
Risk Behavior score calculation:
Start: 10 points
- accountSuspensions: -2 per suspension (max -5)
- hasFraudFlags: -3
- GMV spikes: -1 to -3, by SHARE of months that spiked
(>=30% -> -3, >=15% -> -2, any -> -1; see below)
- hasLinkedAccounts: -1 (detected from data ingestion, not derivable from events)
Minimum: 0 points
How GMV spikes are scored. A month is a spike when it is >= 3x the prior
month and fails to hold (the next month falls below 50% of it). A jump the
next month sustains is a step change - growth, not risk - and is not counted.
The deduction scales with gmvSpikeMonthsPercent, the share of observed months
that spiked, so one odd month in a long history is noise while spikes in a
third of the months are a pattern.
gmvSpikeMonthsPercent is optional. Omit it and the scorer falls back to a
flat -2 on hasSuddenGmvSpikes, exactly as before - no integration change is
required. Send it to get the graduated treatment.
GMV spikes do not affect the perfect-record bonus. Only suspensions, fraud
flags and linked accounts gate that.
Each account flag event also triggers a credit score recalculation, so the impact is reflected immediately (after the 5-minute debounce window).
| Severity | Description |
|---|---|
INFO | Informational only |
WARNING | May affect future credit decisions |
HIGH | Immediate review of active loans triggered |
CRITICAL | Loan disbursements frozen, escalation to risk team |
curl -X POST https://api.opensylo.com/api/marketplace/account-flags \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"platform_merchant_id": "PLT_MERCH_001",
"flag_type": "ACCOUNT_SUSPENDED",
"flag_severity": "HIGH",
"description": "Merchant refund rate exceeded 10% threshold for 3 consecutive months.",
"flagged_at": "2026-04-07T12:00:00.000Z",
"evidence": {
"refund_rate_3m": 12.5,
"refund_count": 45,
"total_orders": 360
},
"idempotency_key": "idem_flag_20260407_001"
}'
This component (max 10 points) is derived from the merchant's profile, not from events:
| Metric | Points | Thresholds |
|---|---|---|
| Account Age | 0–5 | ≥24mo: 5, ≥12mo: 4, ≥6mo: 3, ≥3mo: 2, ≥1mo: 1 |
| Verification Status | 0–3 | KYC Approved: 3, otherwise: 0 |
| Business Category | 1–2 | Low-risk categories (electronics, books, clothing, home & garden): 2, others: 1 |
Account age is computed from the marketplace connection date (when the merchant connected to OpenSylo via OAuth).
This component (max 15 points) behaves differently depending on the data path:
Direct data ingestion: The marketplace provides payoutCashFlow with actual payout metrics.
Event-based aggregation: Defaults are used since payout data cannot be derived from sales events:
payoutFrequency: MONTHLY (assumed)avgPayoutValue: Average monthly net sales (gross - refunds)failedPayouts: 0 (assumed)| Metric | Points | Thresholds |
|---|---|---|
| Failed Payouts | 0–9 | 0: 9, <2: 7, <5: 5, <10: 3 |
| Avg Payout Value | 0–6 | >₦100K: 6, >₦50K: 5, >₦25K: 4, >₦10K: 3, >₦5K: 2 |
Loan eligibility requires 6 months of monthly sales history. This is provided either directly via monthlySalesHistory in the data ingestion payload, or automatically derived from SALE events grouped by calendar month.
When derived from events, eligibility is only computed if at least 3 of the 6 months have non-zero GMV.
avgMonthlyGmv = sum(6 months GMV) / 6
monthlyRepaymentCap = avgMonthlyGmv × repaymentRate (default 25%)
totalRepaymentCap = monthlyRepaymentCap × tenorMonths (default 6)
interestMultiplier = 1 + (monthlyInterestRate × tenorMonths) (default 1.30)
maxEligibleLoan = totalRepaymentCap / interestMultiplier
Given 6 months of GMV: ₦950K, ₦1.02M, ₦1.1M, ₦1.05M, ₦1.25M, ₦1.2M
avgMonthlyGmv = ₦6,570,000 / 6 = ₦1,095,000
monthlyRepaymentCap = ₦1,095,000 × 0.25 = ₦273,750
totalRepaymentCap = ₦273,750 × 6 = ₦1,642,500
interestMultiplier = 1 + (0.05 × 6) = 1.30
maxEligibleLoan = ₦1,642,500 / 1.30 = ₦1,263,461.54
| Metric | Description |
|---|---|
gmvTrendPercent | (newest month GMV - oldest month GMV) / oldest month GMV × 100. Positive = growth. |
gmvVolatilityCov | Coefficient of variation (sample std dev / mean). Lower = more stable. |
aov | Average order value = avgMonthlyGmv / avgMonthlyOrders |
Loan eligibility uses policy parameters that can be configured per-marketplace or system-wide:
| Parameter | Default | Description |
|---|---|---|
repaymentRate | 0.25 (25%) | Fraction of monthly GMV allocated to loan repayment |
tenorMonths | 6 | Loan duration in months |
monthlyInterestRate | 0.05 (5%) | Monthly interest rate applied to the loan |
When monthlySalesHistory is provided and eligibility is calculated, the maxLendingCap on the credit score is overwritten with maxEligibleLoan (which is typically more accurate since it factors in repayment capacity, tenor, and interest).
| Score Component | Max | Data Sources | Event-Based Inputs |
|---|---|---|---|
| Sales Count | 60 | salesPerformance | SALE events (gross_amount, count) |
| Revenue Consistency | 10 | revenueConsistency | SALE events (monthly grouping) |
| Fulfillment Ops | 10 | fulfillmentMetrics | REFUND, CANCELLATION, CHARGEBACK events |
| Stability & Tenure | 10 | merchantIdentity | Merchant profile + connection date |
| Risk Behavior | 10 | behavioralRisk | Account flag events + GMV spike shape |
| Component total | 100 | ||
| Perfect-record bonus | +10 | behavioralRisk | Applied to the total, pre-clamp |
| Tier | Score | Eligible % of Avg Monthly Sales | Lending Decision |
|---|---|---|---|
| A | 80–100 | 80% | Highest cap, best pricing |
| B | 65–79 | 50% | Standard cap |
| C | 50–64 | 20% | Reduced cap, short tenor |
| D | 35–49 | 10% | Pilot / small ticket only |
| E | 0–34 | 0% | Not eligible |