🏦 Bank Wiki

The Bank application is a financial management sandbox simulating real-world banking operations. It supports account creation (checking and savings), balance-based transfers between accounts, bill payment scheduling, loan applications, and in-app message notifications.

All monetary values are stored in cents (integers) and returned as formatted dollar strings. This creates interesting edge cases around precision, rounding, and type handling that are valuable for QA testing.

Key Characteristics

Quick Start

Step 1
Create Account
CHECKING or SAVINGS, optional initial deposit
Step 2
Fund Account
Transfer from another account or use initial deposit
Step 3
Make Transfers / Pay Bills
Between accounts, schedule recurring bills
Step 4
Close Account
Withdraw balance first, then close
Authentication: All API calls require Authorization: qac_live_<your_api_key> in the request header. Get your key from the Profile page.
Amount format: All amount fields are in cents. Send 1000 to transfer $10.00. Responses format amounts as dollar strings: "$10.00".

Account Flow

Accounts are the root resource. All transfers, bills, and loans are associated with accounts.

Account Statuses

OPEN — active, usable CLOSED — balance was $0, then closed REMOVED — hidden from default list (history preserved)

Business Rules

Transfer Flow

Transfers move funds between two open accounts. Transfers are completed immediately and generate message notifications for both sender and recipient.

Transfer Rules

Bill Payment Flow

Bills represent scheduled or one-time payment obligations. Bills are associated with a pay-from account and can be set as recurring.

Bill Statuses

ACTIVE — scheduled, not yet paid PAUSED — temporarily suspended PAID — payment completed CANCELLED — removed from schedule

Bill Rules

Loan Application Flow

Users submit loan applications which go through a manually-controlled approval process. Loans do not automatically credit accounts.

Loan Statuses

PENDING — submitted, awaiting decision APPROVED — loan granted REJECTED — loan denied

Loan Rules

API – Accounts

Base path: /api/bank/accounts

POST /api/bank/accounts Create a new bank account
FieldTypeRequiredNotes
typestringrequiredCHECKING or SAVINGS
initial_depositintegeroptionalCents. 0–1,000,000 ($0–$10,000)

Returns: 201 with account object. 400 if max 5 open accounts reached or invalid type.

GET /api/bank/accounts List all accounts
Query ParamNotes
statusOPEN, CLOSED, REMOVED, or ALL. Default: shows OPEN only

Returns { accounts: [...] }. Balance shown as both formatted string and raw cents.

PATCH /api/bank/accounts/:id/close Close an account (requires $0 balance)

Sets status to CLOSED and records closed_at timestamp. Returns 400 if balance is non-zero or account already closed.

PATCH /api/bank/accounts/:id/remove Remove a closed account from the list

Sets status to REMOVED. Account history is preserved. Returns 400 if account is not CLOSED.

DELETE /api/bank/accounts/:id Permanently delete an account

Permanently removes account. Returns 400 if balance is non-zero. This is irreversible.

POST /api/bank/reset Reset all bank data to template state

Deletes all user's accounts, transactions, bills, loans, and messages. Repopulates from template. Returns counts of created resources.

API – Transfers

POST /api/bank/transfer Transfer money between accounts
FieldTypeRequiredNotes
from_account_iduuidrequiredMust be owned by user, must be OPEN
to_account_iduuidrequiredMust be OPEN, cannot be same as from
amountintegerrequiredPositive integer in cents

Returns: 201 with transaction object. 400 for same-account transfer, insufficient funds, or non-OPEN accounts.

GET /api/bank/transactions Get transaction history
Query ParamNotes
account_idFilter to one account
typeComma-separated: transfer, withdrawal
min_amountMinimum amount in cents
max_amountMaximum amount in cents

Returns combined transfers and paid bills, ordered by date DESC. Each item has a type field: transfer or withdrawal.

API – Bills

Base path: /api/bank/bills

POST /api/bank/bills Create a bill payment
FieldTypeRequiredNotes
payeestringrequiredRecipient name e.g. "Electric Co"
categorystringrequirede.g. "utilities", "rent"
amountintegerrequiredPositive cents value
next_due_datedaterequiredYYYY-MM-DD
from_account_iduuidrequiredMust be owned by user
is_recurringbooleanoptionalDefault: false
frequencystringoptionalRequired if is_recurring: true

Returns: 201 with bill object. Status defaults to ACTIVE.

GET /api/bank/bills List all bills

Returns all bills for the authenticated user. Ordered by created_at DESC.

PATCH /api/bank/bills/:id Update a bill (status, amount, due date)

Can update status to: ACTIVE, PAUSED, PAID, CANCELLED. Also updatable: payee, amount, next_due_date, frequency, is_recurring.

DELETE /api/bank/bills/:id Delete a bill

Permanently removes the bill. Returns 200 on success, 404 if not found.

API – Loans

Base path: /api/bank/loans

POST /api/bank/loans Submit a loan application
FieldTypeRequiredNotes
loan_reasonstringrequiredPurpose of loan
loan_amountintegerrequiredCents
term_monthsintegerrequiredLoan term in months
employment_statusstringrequired
annual_incomeintegerrequiredCents

Returns 201 with loan application. Status defaults to PENDING.

GET /api/bank/loans List all loan applications

Returns all loan applications for the authenticated user.

PATCH /api/bank/loans/:id/approve Approve a pending loan

Sets status to APPROVED. Only works on PENDING loans. Returns 400 if loan is not PENDING.

PATCH /api/bank/loans/:id/reject Reject a pending loan

Sets status to REJECTED. Only works on PENDING loans.

DELETE /api/bank/loans/:id Delete a loan application

Permanently removes the loan application. Allowed for any status.

API – Messages

Base path: /api/bank/messages

GET /api/bank/messages Get all messages / notifications

Returns all bank messages for the user. Includes is_read flag, message_type (e.g. TRANSFER_SENT, TRANSFER_RECEIVED), title, and description.

POST /api/bank/messages/create Manually create a message

Allows manual creation of a notification message for testing purposes.

PATCH /api/bank/messages/mark-read Mark messages as read

Marks one or all messages as read. Pass message IDs array or mark all at once.

Test Cases

Accounts

TC-ACC-001 Create sixth account when 5 are already OPEN Expected Fail
  1. Create 5 CHECKING accounts (each with unique account numbers)
  2. Attempt to create a 6th account
Response: 400 — Maximum of 5 open accounts allowed
TC-ACC-002 Create account with invalid type "MORTGAGE" Expected Fail
  1. POST /api/bank/accounts with { "type": "MORTGAGE" }
Response: 400 — Invalid account type. Must be CHECKING or SAVINGS.
TC-ACC-003 Create account with initial deposit of $10,001 (over limit) Expected Fail
  1. POST /api/bank/accounts with { "type": "CHECKING", "initial_deposit": 1000100 }
Response: 400 — Initial deposit must be between $0 and $10,000
TC-ACC-004 Close account with non-zero balance Expected Fail
  1. Create account with initial deposit of $100 (10000 cents)
  2. PATCH /api/bank/accounts/:id/close
Response: 400 — Account balance must be $0.00 to close. Response includes current_balance.
TC-ACC-005 Close account after transferring balance to zero Expected Pass
  1. Create account A with $200 (20000 cents)
  2. Create account B
  3. Transfer 20000 from A to B
  4. PATCH /api/bank/accounts/:accountA/close
Account A closes successfully. Status becomes CLOSED, closed_at is set.
TC-ACC-006 Remove an OPEN account directly (without closing first) Expected Fail
  1. Create an OPEN account
  2. PATCH /api/bank/accounts/:id/remove (skip close step)
Response: 400 — Only closed accounts can be removed

Transfers

TC-TXN-001 Transfer to same account Expected Fail
  1. POST /api/bank/transfer with from_account_id = to_account_id
Response: 400 — Cannot transfer to the same account
TC-TXN-002 Transfer with insufficient funds Expected Fail
  1. Create account with 1000 cents ($10.00)
  2. POST /api/bank/transfer with amount: 5000 ($50.00)
Response: 400 — Insufficient funds. Response includes current_balance and required amount.
TC-TXN-003 Transfer amount of 0 or negative Expected Fail
  1. POST /api/bank/transfer with amount: 0
  2. Repeat with amount: -100
Response: 400 — Amount must be a positive number (in cents)
TC-TXN-004 Transfer updates balances correctly Expected Pass
  1. Account A: 50000 cents ($500), Account B: 0 cents
  2. Transfer 10000 cents ($100) from A to B
  3. GET /api/bank/accounts for both
Account A balance: $400.00 (40000 cents). Account B balance: $100.00 (10000 cents).
TC-TXN-005 Transfer from CLOSED account Expected Fail
  1. Close an account (ensure $0 balance first)
  2. Attempt to use it as from_account_id in a transfer
Response: 400 — Cannot transfer from a closed or removed account

Bills

TC-BILL-001 Create recurring bill without frequency Expected Fail
  1. POST /api/bank/bills with is_recurring: true but no frequency field
Response: 400 — Frequency is required for recurring bills
TC-BILL-002 Mark bill as PAID and verify in transaction history Expected Pass
  1. Create an ACTIVE bill
  2. PATCH /api/bank/bills/:id with { "status": "PAID" }
  3. GET /api/bank/transactions
Paid bill appears in transactions with type: "withdrawal" and to_account_number showing "Payee: [name]"

Loans

TC-LOAN-001 Approve an APPROVED loan (double-approve) Expected Fail
  1. Submit loan, then PATCH approve it
  2. PATCH approve it again
Response: 400 — Transaction is not pending review (or similar — loan is not PENDING)
TC-LOAN-002 Full loan lifecycle: submit → approve Expected Pass
  1. POST /api/bank/loans with all required fields
  2. Verify status is PENDING
  3. PATCH /api/bank/loans/:id/approve
  4. GET /api/bank/loans — verify status is APPROVED
Loan status transitions correctly. Approval response includes updated loan object.

QA Tasks

Hands-on challenges for manual and automated testing of the Bank application.

#1 Account Limit Boundary Automation

Automate creation of exactly 5 accounts, then attempt a 6th. Verify the 5th succeeds and the 6th returns 400. Then close one account and verify a new 6th can be created.

#2 Cents Precision Testing Automation

Create an account with initial_deposit: 1 (1 cent = $0.01). Transfer 1 cent to another account. Verify both balances in cents and dollar format. Test transfer of 0 cents and a float value like 10.5 — document what happens.

#3 Full Closure Sequence Manual

Open 2 accounts. Move all funds from Account A to B. Close Account A → remove it → attempt to delete it (should fail: already removed). Verify Account A appears in the transaction history with status=REMOVED when queried with ?status=REMOVED.

#4 Cross-Account Transfer Notification Manual

Use two different API keys. Transfer from User A's account to User B's account. Check GET /api/bank/messages for both users. Verify User A gets TRANSFER_SENT and User B gets TRANSFER_RECEIVED messages.

#5 Recurring Bill Schedule Manual

Create a recurring bill (is_recurring: true, frequency: "monthly"). Verify it appears in GET /api/bank/bills. Then pause it, then cancel it. Verify status transitions are reflected correctly at each step.

#6 Loan Rejection and Re-Application Manual

Submit a loan. Reject it. Attempt to approve the rejected loan — document the response. Delete the rejected loan. Submit a new loan application and approve it. Confirm the entire REJECTED → deleted → new PENDING → APPROVED flow.

#7 Transaction History Filtering Automation

Create 3 transfers of different amounts. Mark one bill as PAID. Then: GET /api/bank/transactions?type=transfer (should return 3). GET ?type=withdrawal (should return 1). GET ?min_amount=500 (filter by minimum 500 cents). Verify filter combinations work correctly.

#8 Reset and Verify State Manual

Make several transfers and create bills. Then call POST /api/bank/reset. Verify the response includes counts for accounts, transactions, bills, loans, and messages. Check GET /api/bank/accounts and confirm template accounts are restored with expected balances.

#9 Delete Non-Zero Balance Account Automation

Create an account with a positive balance. Attempt DELETE /api/bank/accounts/:id. Verify it returns 400. Then transfer the full balance out, and DELETE again — verify 200 response. Document the exact error message and assertion.

#10 Concurrent Transfer Race Condition Automation

Fund an account with exactly 10000 cents ($100). Fire two simultaneous POST /api/bank/transfer requests: each for 7000 cents from the same account. Observe if both succeed (double spend) or one fails. Document the exact behavior — this is a concurrency edge case.