Rules Documentation
This page documents the individual rules available in the underwriting engine (located in pkg/rules). Each rule implements specific logic to evaluate a user’s eligibility for Floats or Installment Loans.
RuleAgeOfAccount
Checks if the user’s oldest transaction meets a minimum age requirement, establishing the age of the account.
-
Properties:
-
min_age(Integer): The minimum age of the account in days.
-
-
Overview: Iterates through user transactions to find the oldest date.
-
Pass Criteria: The oldest transaction date is older than
min_agedays ago. -
Fail Criteria: The account is younger than
min_agedays.
RuleAverageBalance
Checks if the user maintains a sufficient average available balance over time.
-
Properties:
-
available_threshold(Integer/int64): The minimum average available balance requirement (in cents).
-
-
Overview: Calculates the average of the
Availablebalance from the user’s account balance history. -
Pass Criteria:
Average Available Balance>=available_threshold. -
Fail Criteria: Average balance is below the threshold.
RuleBalanceBetweenBounds
Ensures that new users (low float count) do not have a balance that falls within a specific "deny range".
-
Properties:
-
max_float_rank(Integer): The float count threshold. Users below this count are subject to the check. -
min_balance(Integer/int64): The lower bound of the deny range (absolute value). -
max_balance(Integer/int64): The upper bound of the deny range (absolute value).
-
-
Overview: Checks if a user is "new" (completed floats <
max_float_rank) and if their current available balance falls within[min_balance, max_balance]. -
Pass Criteria: User has >=
max_float_rankfloats OR their balance is outside the deny range. -
Fail Criteria: User has <
max_float_rankfloats ANDmin_balance⇐ ABS(AvailableBalance) ⇐max_balance.
RuleBalanceRequirement
Checks if the user meets minimum balance requirements in either their Available or Current balance.
-
Properties:
-
min_available(Integer/int64): Minimum required available balance. -
min_current(Integer/int64): Minimum required current balance. -
min_num_of_floats(Integer, Optional): Minimum number of completed floats required to pass.
-
-
Overview: Verifies that the user has enough funds.
-
Pass Criteria:
-
(If
min_num_of_floatsis set) User must meet the float count requirement. -
AND (Available Balance >=
min_availableOR Current Balance >=min_current).
-
-
Fail Criteria: Both balances are below their respective thresholds, or the float count is insufficient.
RuleCashAdvanceScore
Evaluates the user based on their external Cash Advance Score (CAS) and optionally their float rank.
-
Properties:
-
min_cash_advance_score(Integer): The minimum passing CAS. -
loan_amount_window(Integer): The loan amount used to select the correct score interval. -
min_float_rank(Integer, Optional): Minimum float count. -
max_float_rank(Integer, Optional): Maximum float count. -
deny_for_float_rank(Boolean): If true, effectively enforces the float rank range.
-
-
Overview: First checks if the user’s float count makes them eligible/ineligible based on configuration. If eligible, it looks up the CAS corresponding to the
loan_amount_window. -
Pass Criteria:
-
Float rank is within acceptable bounds (or ignored).
-
CAS Score >=
min_cash_advance_score.
-
-
Fail Criteria: Float rank is unacceptable (if
deny_for_float_rankis true), or CAS Score <min_cash_advance_score.
RuleCollectionsErrors
Checks the ratio of failed Usio debits (collection errors) to completed floats.
-
Properties:
-
max_error_ratio(Float): The maximum allowed ratio of errors to completed floats.
-
-
Overview: Calculates
Error Count / Completed Floats(Completed floats defaults to 1 to avoid division by zero). -
Pass Criteria: Calculated ratio <
max_error_ratio. -
Fail Criteria: Ratio is >=
max_error_ratio.
RuleCompetitorEwa
Analyzes transaction history for interactions with competitor Early Wage Access (EWA) apps.
-
Properties:
-
number_of_days(Integer): How far back to look in days. -
min_advance_amount(Integer): Minimum amount to consider as a cash advance. -
min_inflows(Integer): Minimum count of competitor inflows (advances) required. -
min_repayments(Integer): Minimum count of competitor outflows (repayments) required. -
min_floats(Integer): Minimum completed floats required for this rule to apply.
-
-
Overview: Used to identify users who actively use other EWA services.
-
Pass Criteria: User has >=
min_inflowsadvances AND >=min_repaymentsrepayments from competitors. -
Fail Criteria: User does not meet the inflow/repayment counts. (Note: If user has <
min_floats, the rule returns a neutral result/does not approve).
RuleEssentialSpend
Checks if the user has a history of spending on "essential" categories (e.g., groceries, gas).
-
Properties:
-
required_float_rank(Integer): Minimum completed floats required. -
required_dollar_amount(Integer): Minimum amount for a transaction to count. -
required_number_of_transactions(Integer): Number of qualifying transactions required. -
essential_categories(List of Strings): List of Plaid categories considered essential. -
days_to_consider(Integer): Time window in days.
-
-
Overview: Encourages users who use their account for daily essentials.
-
Pass Criteria:
-
User meets
required_float_rank. -
User has >=
required_number_of_transactionsin essential categories above the dollar amount.
-
-
Fail Criteria: Float rank not met or not enough essential spend transactions.
RuleEWADollarAmount
Similar to RuleCompetitorEwa, but evaluates the total dollar amount borrowed and repaid to competitors.
-
Properties:
-
days_to_consider(Integer): Time window in days. -
required_min_borrow_amount(Integer): Minimum total amount borrowed. -
required_min_repayment_amount(Integer): Minimum total amount repaid. -
min_advance_amount(Integer): Minimum amount for a single transaction to count.
-
-
Overview: Verifies active and substantial usage of competitor services.
-
Pass Criteria: Total Borrowed >=
required_min_borrow_amountAND Total Repaid >=required_min_repayment_amount. -
Fail Criteria: Amounts are insufficient.
RuleFloatRank
Enforces a minimum and/or maximum number of completed floats.
-
Properties:
-
min_float_rank(Integer, Optional): Minimum required completed floats. -
max_float_rank(Integer, Optional): Maximum allowed completed floats.
-
-
Overview: strict check on the user’s float history depth.
-
Pass Criteria: Float count is within [min, max] (inclusive, respecting set/unset props).
-
Fail Criteria: Float count is outside the specified range.
RuleGoodStanding
Checks basic account health and outstanding loans.
-
Properties: None.
-
Overview: Ensures the user is an active customer and isn’t already indebted to FloatMe.
-
Pass Criteria:
-
User status is "ACTIVE".
-
No outstanding (Active/Pending) floats.
-
-
Fail Criteria: User is disabled or has an unpaid float.
RuleHighTransfer
Checks for excessive transfers relative to income immediately after payday.
-
Properties:
-
max_transfer_ratio(Float): Max ratio of (Transfers / Income). -
min_income(Integer): Minimum income amount to consider.
-
-
Overview: Detects if a user immediately transfers away a large portion of their paycheck (potentially effectively emptying the account). Checks payday and the day after.
-
Pass Criteria: User has 0 instances where
(Transfers on Payday + Next Day) > (Income * max_transfer_ratio). -
Fail Criteria: One or more "high transfer" instances found.
RuleInstitutionCheck
Applies special logic for specific banking institutions (e.g., Chime, Varo).
-
Properties:
-
institution_list(List of Strings): List of Institution IDs to target. -
min_balance(Integer/int64): Balance requirement for targeted institutions.
-
-
Overview: If a user belongs to a listed institution, they must meet a stricter balance check because these institutions often allow overdrafts or have delayed posting.
-
Pass Criteria:
-
User is NOT in the
institution_list(Auto-pass). -
OR User IS in the list AND maintains
min_balancein either Available or Current balance (while the other is non-negative).
-
-
Fail Criteria: User is in the list and fails the balance check.
RuleLowTransactions
Ensures the user uses the account actively.
-
Properties:
-
days_to_consider(Integer): Time window. -
average_transactions(Float): Minimum average transactions per day. -
float_rank(Integer): Float threshold for exemption. -
run_chime_varo_check(Boolean): Enable legacy logic for Chime/Varo.
-
-
Overview: Validates account activity level.
-
Pass Criteria:
-
Average txns/day >=
average_transactions. -
OR User has >
float_rankcompleted floats and no active float. -
OR (If enabled) Chime/Varo check passes.
-
-
Fail Criteria: Activity is too low.
RuleMLPaybackPrediction
Uses a Machine Learning model’s "Probability to Default" score.
-
Properties:
-
min_prediction_score(Float): The maximum allowed probability to default (Threshold). -
max_float_count(Integer, Optional): Max float count to apply this rule. -
deny_non_applicable(Boolean, Optional): Behavior if max float count is exceeded.
-
-
Overview: Checks the ML inference result. Note:
min_prediction_scoreis actually a threshold for the bad probability. -
Pass Criteria: Probability to default (class 1) ⇐
min_prediction_score. -
Fail Criteria: Probability to default >
min_prediction_score. (Also fails if float count exceeded anddeny_non_applicableis true).
RuleMultipleAccounts
Checks for duplicate accounts linked within the system.
-
Properties:
-
max_accounts(Integer): Maximum allowed linked accounts.
-
-
Overview: Prevents fraud/abuse via multiple linked accounts.
-
Pass Criteria:
-
User already has floats (grandfathered/trusted).
-
OR Unique linked accounts count ⇐
max_accounts.
-
-
Fail Criteria: Too many linked accounts.
RuleOnTimeFloatPayback
Checks valid payment history for recent floats.
-
Properties:
-
days_after_float_on_time(Integer): Grace period days (or definition of on-time). -
required_last_floats_on_time(Integer): How many recent floats must be on time. -
required_float_rank(Integer): Minimum total floats required.
-
-
Overview: Ensures the user has a recent habit of paying back on time.
-
Pass Criteria:
-
User meets
required_float_rank. -
The last
required_last_floats_on_timeconsecutive floats were paid back withindays_after_float_on_timeof their due date.
-
-
Fail Criteria: Float rank too low or recent payment history has late payments.
RuleRecentFloat
Checks if the user has paid back a float recently.
-
Properties:
-
max_days(Integer): Maximum days since last payback.
-
-
Overview: Ensures the user is an active borrower.
-
Pass Criteria: Last float payback date is within
max_daysago. -
Fail Criteria: Last float was paid back too long ago.
RuleRecurringDeposits
Checks for consistent payroll deposits.
-
Properties:
-
min_income(Integer): Minimum amount to count as payroll.
-
-
Overview: Verifies income stability.
-
Pass Criteria: User has at least 2 instances of payroll income in the lookback period, and at least one is "recent" (determined by pay frequency).
-
Fail Criteria: Not enough income instances or no recent income.
RuleRecurringDepositsAndHighTransfer
Combination rule ensuring income stability AND responsible transfer behavior.
-
Properties:
-
min_income(Integer): Minimum income amount. -
transfer_ratio(Float): Max allowed transfer ratio.
-
-
Overview: combines
RuleRecurringDepositsandRuleHighTransferlogic. -
Pass Criteria:
-
(At least one Payroll Income is recent AND No High Transfers found).
-
OR (At least one "Any Income" > min is recent AND No High Transfers found).
-
-
Fail Criteria: No recent income or High Transfers detected.
RuleSpendVelocity
Checks if the user spends their paycheck too quickly.
-
Properties:
-
spend_percentage(Float): Threshold percentage of income spent. -
min_income(Integer): Min income to consider. -
days_after_income(Integer): Window after payday to check spending. -
allowed_high_spend_instances(Integer): Max allowed bad instances.
-
-
Overview: Calculates spending within
days_after_incomeof receiving pay. -
Pass Criteria: Number of times user spent >
spend_percentageof their check is <allowed_high_spend_instances. -
Fail Criteria: Too many high-spend instances.
RuleSubscriptionRank
Checks for loyalty/tenure via subscription renewals.
-
Properties:
-
min_rank(Integer): Minimum number of subscription renewals. -
paid_within_days(Integer): Subscription must have been paid within this many days.
-
-
Overview: Uses subscription history as a proxy for user stability/loyalty.
-
Pass Criteria:
-
Current subscription rank >=
min_rank. -
AND (if
paid_within_dayscheck applies) a subscription payment occurred recently.
-
-
Fail Criteria: Rank too low or no recent payment.
RuleSuspiciousHighBalance
Flags new accounts with suspiciously high balances (potential fraud/money laundering risk).
-
Properties:
-
high_account_balance(Integer): Balance threshold (pennies). -
min_age_of_account(Integer): Age threshold (days).
-
-
Overview: Denies service to new accounts holding large sums.
-
Pass Criteria: User is NOT suspicious (Account is old enough OR Balance is low enough OR User already has floats).
-
Fail Criteria: Account is young (<
min_age_of_account) AND Balance is high (>high_account_balance) AND No existing floats.
RuleTransferRatio
Checks general transfer usage.
-
Properties:
-
days_to_consider(Integer): Lookback period. -
transfer_categories(List of Strings): Categories counting as transfers. -
required_number_of_transactions(Integer): Min txns to evaluate. -
max_transfer_percentage(Float): Max allowed % of txns that are transfers.
-
-
Overview: Users who primarily transfer money in and out may be riskier.
-
Pass Criteria:
(Transfer Txns / Total Txns) * 100 ⇐ max_transfer_percentage. -
Fail Criteria: Transfer percentage is too high.