Documentation

Banking overview

Banking-as-a-Service — accounts, transfers, cards, compliance, and the ledger.

The Banking module is a banking-as-a-service stack. It holds real funds in real accounts at a partner sponsor bank, moves money over ACH, Wire, and RTP rails, issues virtual and physical cards, runs KYC/KYB/AML compliance flows, and posts every movement to a double-entry ledger. Where Finance tracks logical balances on top of someone else's payment system, Banking is the payment system.

Sponsor bank required

Banking is not a chartered bank. All money-holding and rail access flows through a partner sponsor bank, abstracted behind SponsorBankProvider. You configure the provider per-org. The platform itself does not hold customer deposits, run ACH, or print cards on its own — it orchestrates the partner.

What Banking owns

DomainSurface
AccountsAccount holders (individual/business), bank accounts (checking/savings), balances, statements, freeze/close lifecycle.
TransfersACH, Wire (Fedwire), RTP, internal book transfers.
CardsVirtual + physical card issuance, spend limits, controls (ATM/online/international/contactless), freeze/replace.
ComplianceKYC for individuals, KYB for businesses (incl. beneficial owners), AML screening for entities and transactions.
LendingLoan applications, decisioning, origination, amortization schedules, payments.
Savings & money marketMoney-market accounts, interest accrual, auto-sweep, rate tiers.
InvestmentsTreasury securities (Bills, Notes, Bonds), Certificates of Deposit.
Merchant servicesHosted checkout, payment links, embedded payment buttons, subscriptions, invoicing.
LedgerChart of accounts, journal entries, trial balance, reconciliation.

Every domain is a sub-controller under /banking/*.

SponsorBankProvider

The provider abstracts the partner bank. Different orgs can be backed by different sponsors; some rails (ACH, Wire) need the partner's connectivity, while internal book transfers stay on AppEngine's own ledger. The provider implementation lives in src/banking/services/providers/sponsor-bank.provider.ts. Operations the provider handles include:

  • Open/close accounts at the partner.
  • Submit ACH/Wire/RTP files.
  • Issue cards via the partner's card-issuing program.
  • Pull statements and reconciliation files.

If your sponsor doesn't support a feature (e.g., a bank that runs ACH but not RTP), the corresponding endpoint will return an error when called for that org.

Onboarding flow

A new banking customer is brought online in five steps. The convenience endpoints POST /banking/onboard and POST /banking/relationship chain them.

  1. 1

    Create account holder

    POST /banking/accounts/holders with holderType: "individual" | "business" and identity fields.

  2. 2

    Run KYC or KYB

    POST /banking/compliance/kyc (individual) or POST /banking/compliance/kyb (business). Submit documents, await decision.

  3. 3

    Bootstrap ledger accounts

    The system creates the asset+liability pair on the platform's own books for the new holder.

  4. 4

    Create the bank account

    POST /banking/accounts with holderId and accountType. Account starts in pending.

  5. 5

    Activate post-KYC

    POST /banking/accounts/:id/activate. Account transitions to active. Optionally issue a card with POST /banking/cards.

For a one-shot setup, POST /banking/relationship does steps 1, 4, and (optionally) card issuance in a single call — KYC still happens out of band.

Status across the module

Most Banking entities follow a common status machine:

pending → active → frozen ↔ active
                  ↓
                closed (terminal)

KYC/KYB use pending → in_progress → approved | rejected | review_required. Transfers and payouts have their own machines documented per page.

Auth and tenancy

Banking is staff-only by default. There is no /client/banking surface — customers don't call Banking directly; your application proxies on their behalf. Every endpoint requires orgid. Most require JWT with appropriate role; compliance-sensitive endpoints expect admin roles.

Idempotency

All payment endpoints accept an idempotencyKey in the body. Pass a stable key (e.g., <orderId>-payout) on retry-prone code paths to avoid double-submitting an ACH or wire.

Health and stats

GET/banking/healthJWT

Returns platform health, sponsor connection status, and aggregate counts (accounts, transfers, cards, ledger balance). Useful for ops dashboards and synthetic monitoring.

The next pages cover each domain. Start with Accounts — every other surface depends on it.