Skip to content

Fee Rules CRUD

Fee rule management: creation, querying, updates, and the specificity-based matching algorithm.


Overview

AttributeValue
Servicesrc/service/FeeRulesService.ts
Calculatorsrc/service/FeesCalculatorService.ts
StorageMongoDB financesFeeRules collection
Schemassrc/schema/fee_rule.json, fee_rule_request.json

Fee Rule Model

Common Fields (all rule types)

FieldTypeDescription
_idObjectIdMongoDB document ID
fee_rule_keystringUnique key for deduplication
rule_typestringPAYIN or WITHDRAWAL
fee_typestringIN (acquirer-side) or OUT (business-side). Unified format nests these under in/out.
statusstringactive or inactive
descriptionstringHuman-readable description

Match Criteria

These fields determine which transactions a rule applies to. null means "matches all" (generic rule).

FieldTypeDescription
business_idstring[]?Specific business IDs, or null for all businesses
acquirerstring[]?Acquirer names (e.g., ["kushki", "unlimit"])
currency_codestring?ISO currency code
country_codestring[]?Merchant country codes
payment_method_idnumber[]?Payment method IDs
card_brandstring[]?Card brands (Visa, Mastercard, etc.)
risk_levelstring[]?Risk classifications

Fee Fields — PAYIN

FieldDescription
intra_transaction_rateDomestic transaction fee percentage
intra_transaction_feeDomestic fixed fee per transaction
inter_transaction_rateInternational transaction fee percentage
inter_transaction_feeInternational fixed fee per transaction
minimum_feeMinimum fee floor (applied when calculated fee is lower)
iva_rateIVA/VAT rate percentage
hold_reserve_percentageRolling reserve hold percentage
hold_reserve_periodRolling reserve hold period in days
chargeback_feeFixed fee per chargeback/dispute
refund_feeFixed fee per refund

Fee Fields — WITHDRAWAL

FieldDescription
intra_transaction_rateWithdrawal fee percentage
intra_transaction_feeFixed fee per withdrawal
minimum_feeMinimum fee floor
iva_rateIVA/VAT rate percentage
methodWithdrawal method
transaction_typeWITHDRAWAL or TOPUP

Settlement Policy (nested)

FieldDescription
settlement_policy.typefixed_days_delay or windows
settlement_policy.fixed_days_delay.daysNumber of days delay
settlement_policy.settlement_hourHour of day for settlement (UTC)
settlement_policy.settlement_periodsArray of settlement period configurations

Rule Formats

Groups IN and OUT sides under a single document:

json
{
  "rule_type": "PAYIN",
  "in": { "intra_transaction_rate": 2.9, "intra_transaction_fee": 3.0, ... },
  "out": { "intra_transaction_rate": 1.5, "intra_transaction_fee": 1.0, ... },
  "acquirer": ["kushki"],
  "currency_code": "MXN",
  ...
}

Legacy Flat Format

Separate documents per fee_type:

json
{
  "rule_type": "PAYIN",
  "fee_type": "IN",
  "intra_transaction_rate": 2.9,
  "intra_transaction_fee": 3.0,
  ...
}

Both formats are supported. The unified format is preferred for new rules.


Endpoints

MethodPathDescription
POST/v1/fee-rulesCreate a new fee rule
GET/v1/fee-rulesList fee rules with filters
GET/v1/fee-rules/{id}Get fee rule by ID
PATCH/v1/fee-rules/{id}Update fee rule fields
DELETE/v1/fee-rules/{id}Delete fee rule

Specificity Ranking Algorithm

When calculating fees for a transaction, the system finds the most specific matching rule using a MongoDB aggregation pipeline:

  1. Filter: Match by rule_type, status: active, fee_type (or unified format), and all applicable criteria fields
  2. Rank: Calculate _rank score — lower is more specific:
    • business_id match = 0, null = 1
    • risk_level match = 0, null = 1
    • card_brand match = 0, null = 1
  3. Sort: Ascending by _rank (most specific first)
  4. Limit: Take the first result (most specific rule wins)

Example: A rule with business_id: ["abc"] + card_brand: ["Visa"] (rank 0+0=0) beats a generic rule with business_id: null + card_brand: null (rank 1+1=2).

NULL handling: Fields set to null match any value (generic). The $or conditions check both $exists: false and explicit null.


Fee Calculation Formulas

See Fee Calculation Flow for detailed formulas per detail type (PAYMENT, REFUND, DISPUTE, VOID, WITHDRAWAL).

Summary:

  • PAYMENT/APMS: fee = max(amount × rate/100 + fixed_fee, minimum_fee), net = amount - fee - iva - rolling_reserve
  • REFUND: fee = refund_fee, net = amount + fee + iva
  • DISPUTE: fee = chargeback_fee, net = amount + fee + iva (or just fee + iva if merchant won)
  • VOID: All fees = 0, net = amount
  • WITHDRAWAL/TOPUP: fee = max(amount × rate/100 + fixed_fee, minimum_fee), net = amount

Vecnet — Build Spec v0.2 · Obsidian Terminal