Exports And Integration Guide

Reference for the current oxide-banking integration surface.

Reference for the current oxide-banking integration surface.

Resource Names

Primary resource name (use this for all new integrations):

exports['oxide-banking']:<ExportName>(...)

Legacy compatibility surface (for older QB-era resources only):

exports['qb-banking']:<ExportName>(...)  -- works because the manifest declares provides { 'qb-banking' }

oxide-banking supports QBCore, QBX, and ESX through o-link. All exports below work identically on every framework.

For framework-agnostic use across many resources, prefer the o-link banking namespace, which wraps the most-used exports:

local olink = exports['o-link']:olink()
olink.banking.AddAccountMoney('police', 5000, 'Fine paid')

Server Exports

Signatures use Lua convention. ? after a type means optional/nilable. errorMessage? means the second return is a human-readable string only on failure.

Core / readiness

IsReady() -> boolean

Returns true once the banking system has finished its initial data load.

GetPlayerBankingData(citizenid) -> { account, creditScore, tier, loans, statements }

Aggregate banking profile for a citizen: player account row, credit score record, tier data, loans, and recent statements.

GetAccountData(accountName) -> table?

Returns a defensive shallow copy of a cached shared/job account (id, citizenid, account_name, account_balance, account_type, users). Returns nil if the account does not exist.

GetPlayerAccounts(citizenid) -> table[]

Every shared/job account the citizen owns or appears in the users list of, each decorated with an is_owner flag.

GetPlayerStatements(citizenid, limit = 50) -> table[]

Defensive copy of up to limit most recent statements (id, account_name, amount, reason, statement_type, date).

CanAfford(citizenid, amount, accountName) -> boolean

For checking (or nil) checks the player's bank balance via the o-link money bridge; for any other name checks the cached shared/job account balance.

Tiers

GetPlayerTier(citizenid) -> string

Current tier name (basic / premium / business), falling back to Config.DefaultTier.

UpgradePlayerTier(citizenid, newTier) -> boolean

Admin path. Force-sets the tier without checking requirements or charging fees.

GetAvailableTiers(citizenid) -> { [tierName] = table }

Every configured tier annotated with isCurrent, isUpgrade, meetsRequirements, requirementMessage, monthlyFee.

GetTierLevel(tierName) -> number

Numeric hierarchy level: basic=1, premium=2, business=3, unknown=1.

CheckTierRequirements(citizenid, tierName) -> boolean, errorMessage?

Validates minBalance, creditScore, and jobBoss requirements for the named tier.

UpgradeAccountTier(citizenid, newTier) -> boolean, tierLabel | errorMessage

Verifies it is an upgrade, requirements are met, and the player can afford the first monthly fee plus Config.Fees.services.accountUpgrade, then charges and persists.

DowngradeAccountTier(citizenid, newTier = 'basic') -> boolean, tierLabel | errorMessage

Drops the player to a lower tier, charging Config.Fees.services.accountDowngrade if affordable (downgrade still proceeds if not).

Credit score

GetCreditScore(citizenid) -> number

Current numeric credit score (300–850). Creates a default record if one does not exist.

UpdateCreditScore(citizenid, change, reason) -> number

Adjusts the score by change (clamped 300–850), persists, writes a credit history row, returns the new score.

RecalculateCreditScore(citizenid) -> number, { factors, weightedScore, finalScore, oldScore }

Re-evaluates all five FICO-style factors (payment history 35%, utilization 30%, account age 15%, credit mix 10%, new inquiries 10%) and persists.

GetCreditScoreBreakdown(citizenid) -> { score, rating, factors, suggestions, lastUpdated }

Runs RecalculateCreditScore and returns it with per-factor sub-scores plus improvement suggestions for any factor below 60.

GetCreditHistory(citizenid, limit = 50) -> table[]

Rows from bank_credit_history, most recent first.

RecordCreditEvent(citizenid, eventType, data) -> nil

Applies the predefined score delta for the event type (e.g. loan_payment_late = -25, loan_paid_off = +15) and inserts a history row. Unknown event types are still logged with a 0 delta.

Account freeze

FreezeAccount(citizenid, accountName, reason, frozenBy, frozenType = 'admin', duration?) -> boolean

Inserts a bank_frozen_accounts row keyed by citizenid or accountName with optional expiry (duration in seconds from now).

UnfreezeAccount(citizenid, accountName) -> boolean

Removes the freeze entry matching the citizenid or accountName.

SelfFreezeAccount(citizenid, duration, reason) -> boolean

Player-initiated freeze. duration accepts '1_hour', '24_hours', '7_days', 'indefinite'. Defaults invalid reasons to 'other'.

SelfUnfreezeAccount(citizenid) -> boolean, errorMessage?

Allows lifting a self-freeze only. Rejects admin-applied freezes.

GetFreezeStatus(citizenid) -> { frozen, reason, expiresAt, frozenType, canSelfUnfreeze }

Freeze state with details from cache.

IsAccountLocked(citizenid) -> boolean, secondsRemaining?

Returns true with seconds remaining when failed PIN attempts have triggered a Config.Security.LockoutDuration lockout. Auto-clears when expired.

Savings accounts

CreateSavingsAccount(citizenid, accountName, initialDeposit) -> boolean, { id, account_name, balance } | errorMessage

Requires a tier with features.savings. Validates against maxAccounts/minimumBalance, deducts the deposit from checking.

GetSavingsAccounts(citizenid) -> table[]

Cached savings accounts decorated with the current effective annual interestRate.

DepositToSavings(citizenid, accountName, amount) -> boolean, newBalance | errorMessage

Moves amount from checking into the named savings account.

WithdrawFromSavings(citizenid, accountName, amount, applyPenalty = true) -> boolean, { withdrawn, penalty, netAmount, newBalance } | errorMessage

Pulls from savings to checking. Optionally applies Config.AccountTypes.savings.earlyWithdrawalPenalty as a percentage of the amount.

CloseSavingsAccount(citizenid, accountName) -> boolean, { finalAmount, refunded, penalty } | errorMessage

Refunds the remaining savings balance (minus penalty) to checking and deletes the savings row.

Savings goals

CreateSavingsGoal(citizenid, goalName, targetAmount, category, targetDate) -> boolean, { id, goal_name, target_amount, category } | errorMessage

Inserts a new active goal. Capped by Config.SavingsGoals.maxGoals. Falls back to 'other' for unknown categories.

GetSavingsGoals(citizenid) -> table[]

Active goals merged with up to 10 most recent completed goals, each with a progress percentage.

ContributeToGoal(citizenid, goalId, amount) -> boolean, { newAmount, progress, completed } | errorMessage

Transfers up to the goal's remaining amount from checking into the goal. Marks completed and notifies the player when reached.

WithdrawFromGoal(citizenid, goalId, amount) -> boolean, { newAmount, progress } | errorMessage

Withdraws from the goal back to checking. Flips completed back to false if the new amount drops below target.

DeleteSavingsGoal(citizenid, goalId) -> boolean, { refundedAmount } | errorMessage

Refunds the goal's current amount to checking and deletes the goal row.

Cards — issuance & lifecycle

IssueCardForAccount(source, accountName, pin) -> boolean, { cardNumber, cardNumberMasked, accountName } | errorKey

Validates PIN length, account access, card limits, and player funds; generates a unique card number, hashes the PIN, charges Config.Cards.OrderCost, adds a bank_card item to inventory.

OrderReplacementCard(source, oldCardNumber, newPin) -> boolean, { cardNumber, cardNumberMasked, accountName } | errorReason

Charges Config.Cards.ReplacementCost, cancels the old card, removes its inventory item, issues a new card for the same account.

FreezeCard(cardNumber) -> boolean, errorReason?

Sets the card's status to frozen (only from active).

UnfreezeCard(cardNumber) -> boolean, errorReason?

Sets the card's status back to active (only from frozen).

CancelCard(cardNumber) -> boolean, errorReason?

Permanently marks the card cancelled with cancelled_at timestamp. Not reactivatable.

RevokeCard(cardNumber, reason) -> boolean

Sets the card's DB status to revoked with cancelled_at timestamp. Used for non-user-initiated removals (e.g. account closure).

RevokeCardsForAccount(accountName, reason) -> nil

Revokes every card belonging to the citizen on the named account.

ChangeCardPIN(cardNumber, oldPin, newPin) -> boolean, errorReason?

Verifies the old PIN (auto-migrating legacy hashes), validates the new PIN is 4 digits, stores the new SHA-256 hash.

Cards — queries & validation

ValidateCardAccess(citizenid, cardNumber) -> boolean, card | errorString

Confirms the card exists, is active, and the citizen still has access to its account.

ValidateCardPIN(cardNumber, pin) -> boolean, card | errorString

Verifies the PIN against the stored SHA-256 salted hash (auto-migrates legacy plain-text entries on first successful verify).

GetPlayerCards(citizenid) -> table[]

All active/frozen cards owned by the citizen, with masked/formatted numbers and account metadata.

GetPlayerInventoryCards(source) -> table[]

Walks the player's inventory for bank_card items, validates each, returns enriched metadata (masked number, account, balance, daily limits, ownership).

GetCardsForAccount(accountName) -> string[]

Cached array of card numbers indexed by account name.

GetAccountCardCount(accountName) -> number

Count of active cards currently indexed under the account name.

CanIssueCardForAccount(citizenid, accountName) -> boolean, reason?

Checks the citizen's permission level against Config.Cards.SharedAccountMinPermission and ensures the account is below its MaxCardsPerAccountType limit.

HasAccountAccess(citizenid, accountName) -> boolean, permissionType

Returns true with 'owner' / 'user' / 'job' for personal checking, owned shared accounts, listed shared-account users, or jobs where the player works. Gangs always return false.

GetAccessibleAccounts(citizenid) -> table[]

Every account the player can access (personal checking + shared/job/gang) with account_type and permission.

MaskCardNumber(cardNumber) -> string

Formats a 16-digit number into the masked display form configured by Config.Cards.CardNumberMaskFormat (default **** **** **** XXXX).

FormatCardNumber(cardNumber) -> string

Formats a 16-digit number into four 4-digit groups separated by spaces.

Transactions — fees & previews

CalculateTransactionFee(citizenid, feeKey, amount) -> feeAmount, waiverReason?

Resolves the fee from Config.Fees (handling percentage-based fees for externalTransfer and latePayment), then applies tier/balance waivers.

GetFeePreview(citizenid, feeKey, amount) -> { feeKey, feeDescription, amount, isWaived, waiverReason, transactionAmount, totalAmount }

UI-friendly fee preview including description and total.

CalculateATMFee(citizenid, atmType) -> feeAmount, waiverReason?

atmType is 'own', 'other', or 'outOfNetwork'.

CalculateWireTransferFee(citizenid, transferType = 'domestic') -> feeAmount, waiverReason?

Builds the fee key wireTransfer.<transferType> and resolves.

CheckDailyLimit(citizenid, limitType, amount) -> allowed, remaining

Checks whether adding amount would exceed the player's tier dailyWithdrawLimit or dailyTransferLimit.

GetExpeditedTransferFee() -> number

Configured expedited transfer fee (default 25) when Config.Fees.transactions.expeditedTransfer.enabled, else 0.

IsExpeditedTransferEnabled() -> boolean

Whether expedited transfers are enabled in config.

Transactions — wire & pending transfers

ProcessWireTransfer(fromCitizenId, toCitizenId, amount, transferType = 'domestic') -> boolean, message

Validates both parties, checks balance plus fee and daily limit, executes the transfer, applies the wire fee, updates daily transferred totals.

CreatePendingTransfer(fromCitizenId, toCitizenId, amount, transferType, reason, expedited) -> result, statusString

Returns nil, 'instant' if no delay configured or expedited == true. Otherwise inserts a bank_pending_transfers row with scheduledCompletion based on Config.TransferDelays.

GetPendingTransfers(citizenid) -> table[]

Pending transfers in either direction, ordered by scheduled completion.

CancelPendingTransfer(citizenid, transferId) -> boolean, message

Refunds the sender, marks the transfer cancelled, writes a refund statement.

Loans

ApplyForLoan(citizenid, loanType, amount, termDays, collateralType, collateralId) -> boolean, loanId | errorMessage, status?

Validates loan type/amount, checks daily loan cap, eligibility, calculates terms, inserts a pending loan, records a hard inquiry, then routes to auto-approval, pending_approval (admin review for amounts over the manual threshold), or processing (delayed approval).

CheckLoanEligibility(citizenid, loanType, amount) -> boolean, message, requirementsData

Validates min/max amount, active loan cap, credit score, account age, optional job-boss requirement, and optional minIncome (checked against bank balance).

CalculateLoanTerms(citizenid, loanType, amount, termDays) -> { principal, interestRate, rateModifier, termDays, totalInterest, totalAmount, paymentAmount, creditScore }

Picks the credit-score rate modifier, computes the effective interest rate (floored at Config.Loans.minimumInterestRate), prorates interest, divides into daily payments.

GetPlayerLoans(citizenid) -> table[]

All loans in valid statuses (pending, pending_approval, processing, approved, active, collections), decorated with product label/icon and an externalManaged flag.

GetLoanProducts(citizenid) -> { [productName] = { label, personalizedRate, requirements, meetsRequirements, ... } }

Every configured loan product with the player's personalized interest rate and per-requirement eligibility data.

MakeLoanPayment(citizenid, loanId, amount) -> boolean, { amount, principalPaid, lateFeesPaid, remainingBalance, status, isLate } | errorMessage

Allocates payment to late fees first, then principal. Refunds overpayment. Runs all DB updates inside a MySQL transaction. Marks the loan paid if fully repaid.

PayOffLoan(citizenid, loanId) -> boolean, paymentResult | errorMessage

Computes the full payoff amount via CalculatePayoffAmount and submits it through MakeLoanPayment.

CalculatePayoffAmount(loanId) -> { total, principal, lateFees }

Remaining principal plus any current late fees (higher of flat or percent fee, capped at maxLateFee).

GetLoanPaymentHistory(loanId) -> table[]

All bank_loan_payments rows for the loan, most recent first.

StartCollections(citizenid, loanId) -> boolean

Marks the loan collections, records a credit event, applies a direct Config.Loans.collections.creditScoreImpact deduction.

Vehicle financing

See Vehicle Financing Integration for the full integration contract.

RegisterVehicleLoan(data) -> boolean, loanId | errorMessage

data requires citizenid, plate, principal, totalAmount, paymentAmount, paymentsTotal. Guards against duplicate active loans on the same plate. Inserts an externalManaged vehicle loan in active status with the plate as collateral_id.

RecordVehicleLoanPayment(plate, amount) -> boolean, { loanId, amount, remainingBalance, status, paymentsMade } | errorMessage

Finds the active vehicle loan by plate, decrements remaining amount, updates payments_remaining, records the payment, marks paid if fully repaid.

CloseVehicleLoan(plate, reason = 'paid') -> boolean, errorMessage?

Marks the active vehicle loan paid or defaulted (when reason == 'repossessed'), zeros the remaining amount, records the appropriate credit event.

GetVehicleLoan(plate) -> loan?

Active/collections loan row for the plate from bank_loans, with notes JSON pre-decoded.

Interest

CalculateInterest(balance, dailyRate, days, method = 'compound') -> number

Returns 0 if interest disabled or balance below Config.Interest.minimumBalance. Otherwise computes simple (balance * rate * days) or compound (balance * ((1+rate)^days - 1)) interest, banker's-rounded.

GetEffectiveInterestRate(citizenid, accountType) -> number

Tier annual rate × Config.Interest.accountTypeRates[accountType], divided by Config.TimeSettings.DaysPerYear to yield a daily rate.

ProcessLoginInterest(source) -> number

Pays accrued interest on the player's checking and shared accounts on login (capped per banking day at Config.Interest.maxInterestPayout), updates last_interest_payout, notifies the player.

ProcessMonthlyFees(source) -> number

After 30 days since last_fee_date, charges the tier's monthlyFee × months due. Downgrades to basic if the player cannot pay.

Investments & CDs

CreateInvestment(citizenid, productType, amount) -> boolean, { id, product, maturityDate } | errorMessage

Enforces a 5-second per-product lock and DB duplicate check, validates tier/limits/funds, then inserts the investment and deducts funds.

GetPlayerInvestments(citizenid) -> table[]

All active investment rows for the citizen, most recent first.

WithdrawInvestment(citizenid, investmentId, early) -> boolean, { payout, penalty, gain } | errorMessage

Requires matured or early = true. Applies a dynamic early-withdrawal penalty that scales down as the investment approaches maturity. Atomically updates status to withdrawn.

PurchaseCD(citizenid, productType, amount) -> boolean, { id, maturityDate, maturityValue } | errorMessage

Requires Premium/Business tier with savings feature, validates min/max deposit, deducts funds, inserts a bank_certificates row with prorated interest baked into maturity_value.

GetPlayerCDs(citizenid) -> table[]

All active or matured certificates of deposit for the citizen.

RedeemCD(citizenid, cdId) -> boolean, { payout, interest } | errorMessage

Pays out the CD's full maturity_value if the maturity date has passed. Rejects pre-maturity redemption (use EarlyWithdrawCD).

EarlyWithdrawCD(citizenid, cdId) -> boolean, { payout, penalty } | errorMessage

Returns principal minus penalty (product's earlyWithdrawalPenalty × expected interest) for active CDs only. Minimum payout is 0.

GetMarketState() -> { trend, modifier, trendDaysRemaining, lastUpdate, previousDayChange, momentum }

Current market simulation state.

GetMarketHistory(days = Config.TimeSettings.DaysPerYear) -> table[]

Up to days records from bank_market_history (trend, modifier, day_number, recorded_at) in chronological order.

Security — 2FA

Enable2FA(citizenid, securityPin) -> boolean, backupCodes | errorMessage

Hashes the 6-digit PIN with SHA-256+salt, generates 8 single-use backup codes, persists to bank_security_2fa. Returns the plaintext backup codes for the player to save (only returned this once).

Disable2FA(citizenid, verificationCode) -> boolean, errorMessage?

Requires a successful Verify2FA call first, then clears the secret and backup codes.

Verify2FA(citizenid, code) -> boolean, errorMessage?

Accepts either the 6-digit PIN (verified against the salted SHA-256 hash, with legacy-format migration) or one of the unused 8-character backup codes. Tracks failed attempts and locks out after 5 failures for 5 minutes.

Requires2FA(citizenid, amount) -> boolean

True when Config.Security.Enable2FA, amount >= Config.Security.TwoFactorThreshold, and the player has 2FA enabled.

Get2FAStatus(citizenid) -> { enabled, backupCodesRemaining, threshold }

Enable state, count of unused backup codes, configured threshold.

GenerateBackupCodes(citizenid) -> boolean, codes | errorMessage

Replaces existing backup codes with 8 fresh single-use codes (invalidating the old set).

Security — fraud & alerts

TrackPlayerLogin(source, citizenid) -> nil

Captures the player's license: identifier and compares against bank_player_accounts.last_license. Alerts the player and logs a security event when a different device is detected.

CheckForFraud(citizenid, transactionType, amount, targetCitizenId) -> flagged, flags

Records the transaction for velocity tracking and emits flags for large_amount, rapid_transactions (≥5 in 60s), and new_recipient. Calls FlagSuspiciousActivity when any flag fires.

FlagSuspiciousActivity(citizenid, reason, data) -> nil

Writes a security log entry, notifies all online admins, prints to console, logs via the banking logger with priority = 'high'.

SendTransactionAlert(citizenid, transactionType, amount, details) -> nil

If alerts are enabled and amount is at or above the player's threshold and the type is enabled in preferences, fires a qb-banking:client:transactionAlert event to the player.

GetAlertPreferences(citizenid) -> { enabled, threshold, types }

Cached alert preferences, initializing with defaults from Config.Security.AlertThreshold if not present.

SetAlertPreferences(citizenid, prefs) -> boolean

Stores enabled, threshold, and types (deposit/withdraw/transfer/received) in the in-memory cache.

Business — invoices

CreateInvoice(fromCitizenId, fromJob, toCitizenId, amount, description, dueDate) -> boolean, { invoiceId, invoiceNumber, dueDate } | errorMessage

Generates a unique invoice number (job-prefixed), defaults dueDate to Config.Business.InvoiceDueDays from now, inserts into bank_invoices, notifies the recipient if online.

PayInvoice(citizenid, invoiceId) -> boolean, { invoiceNumber, amountPaid } | errorMessage

Deducts the invoice total (plus late fee if status is overdue and Config.Business.InvoiceLateFeeEnabled) from the payer's bank and credits the job account or creator player.

CancelInvoice(citizenid, invoiceId) -> boolean, message | errorMessage

Sets the invoice status to cancelled if the caller is the sender and it is still pending. Notifies the recipient.

GetInvoices(citizenid, jobName, filter) -> table[]

Up to 50 invoices filtered by 'sent'/'received'/'pending'/'overdue' (default: all involving the citizen), enriched with from_name, to_name, is_sender.

Business — expenses & reports

RecordExpense(jobName, category, amount, description, recordedBy) -> boolean, { expenseId } | errorMessage

Validates category against Config.Business.ExpenseCategories, deducts from the job account, reimburses the recorder's bank, logs to bank_expenses.

GetExpenses(jobName, filters) -> table[]

Expense rows filtered by startDate, endDate, category, with pagination (limit, offset), enriched with recorded_by_name.

GetExpenseSummary(jobName, dateRange) -> { categories, grandTotal, startDate, endDate }

Groups expenses by category over a date range (defaults to current month). Adds percentage, label, icon from config.

GenerateIncomeStatement(jobName, startDate, endDate) -> { totalIncome, operatingExpenses, expenseBreakdown, netIncome, profitMargin, ... }

Sums job-account deposits (income) and expenses for the period. Defaults to current month.

GenerateBalanceReport(jobName) -> { balance, receivables, payables, netPosition, receivableCount }

Current job-account balance, sum of outstanding sent invoices (receivables), net position. Payables always 0.

GenerateCashFlowReport(jobName, startDate, endDate) -> { totalInflows, totalOutflows, netCashFlow, byMonth, startDate, endDate }

Sums statement deposits and withdrawals for the job account over the period, broken down by month.


Legacy qb-banking Compatibility Exports

These exist only for older resources that were built against qb-banking. New integrations should use the primary exports above regardless of framework.

CreatePlayerAccount(playerId, accountName, accountBalance, accountUsers) -> boolean, errorMessage?

Creates a shared bank account owned by the player after validating the name and checking tier-imposed maxSharedAccounts. Persists to bank_accounts and caches.

CreateJobAccount(accountName, accountBalance) -> boolean

Creates a job-type bank account if it does not already exist (rehydrates cache if the DB row exists).

CreateGangAccount(accountName, accountBalance) -> boolean

Always returns false — gang accounts are not supported in oxide-banking. Use shared accounts instead.

CreateBankStatement(playerId, account, amount, reason, statementType, accountType) -> boolean

Accepts a server id (number) or citizenid (string). Title-cases the reason. Inserts a bank_statements row and prepends to the cached statements list (capped at 100).

AddMoney(accountName, amount, reason) -> boolean

Atomic UPDATE adding to the shared/job account balance, syncs cache, auto-creates a deposit statement. Delegates to ESXBridge for ESX job accounts when applicable.

RemoveMoney(accountName, amount, reason) -> boolean

Atomic UPDATE with account_balance >= ? guard preventing overdrafts. Syncs cache and creates a withdraw statement on success.

GetAccount(accountName) -> table?

Returns the cached account table directly (raw reference — do not mutate).

GetAccountBalance(accountName) -> number

Cached balance for the shared/job account, or 0 if missing.

AddGangMoney(accountName, amount, reason) -> boolean

Alias for AddMoney.

RemoveGangMoney(accountName, amount, reason) -> boolean

Alias for RemoveMoney.

GetGangAccount(accountName) -> table?

Alias for GetAccount.

GetGangAccountBalance(accountName) -> number

Alias for GetAccountBalance.


Client Exports

OpenBank() -> nil

Requests banking data via qb-banking:server:openBank, opens the NUI bank UI, starts the ESC close handler. Aborts if any UI is already open.

CloseBank() -> nil

Resets all UI state flags (bank/ATM/card-selector/session), releases NUI focus, sends closeApp to the UI.

OpenATM() -> nil

Verifies the player has a bank_card item, enters the card-selector flow (OpenCardSelector).

OpenCardSelector() -> nil

Fetches the player's inventory cards from the server. Auto-selects if only one card exists, otherwise shows the multi-card NUI selector.

CloseCardSelector() -> nil

Clears card selector state, releases NUI focus, sends closeCardSelector to the UI.

IsBankOpen() -> boolean

Bank UI open state.

IsATMOpen() -> boolean

ATM UI open state.

IsCardSelectorOpen() -> boolean

Card selector open state.

GetActiveATMSession() -> { cardNumber, accountName, accountType, dailyLimit, dailyUsed, dailyRemaining } | nil

Active ATM session populated when an ATM is opened with a selected card.

GetSelectedCard() -> card | nil

Card currently selected for an ATM session.

IsInBankZone() -> boolean

Cached bank-zone proximity flag. Always returns false when Config.UseTarget is enabled (zone tracking is bypassed).

IsNearATM() -> boolean, atmHandle?

Iterates Config.ATMModels and returns true with the entity handle if any ATM prop is within 1.5m of the player.


Callback Surface

Legacy lib.callback names still registered by the resource. New integrations should call exports directly instead of using these callbacks.

Bank, ATM, transfers, and tiers

  • qb-banking:server:openBank
  • qb-banking:server:openATM
  • qb-banking:server:withdraw
  • qb-banking:server:deposit
  • qb-banking:server:internalTransfer
  • qb-banking:server:externalTransfer
  • qb-banking:server:wireTransfer
  • qb-banking:server:orderCard
  • qb-banking:server:openAccount
  • qb-banking:server:renameAccount
  • qb-banking:server:deleteAccount
  • qb-banking:server:addUser
  • qb-banking:server:removeUser
  • qb-banking:server:getTierInfo
  • qb-banking:server:upgradeTier
  • qb-banking:server:downgradeTier
  • qb-banking:server:getPlayerTier
  • qb-banking:server:getFeePreview
  • qb-banking:server:getMultipleFeePreview
  • qb-banking:server:checkDailyLimits
  • qb-banking:server:getBalanceHistory

Cards

  • qb-banking:server:getInventoryCards
  • qb-banking:server:validateCardAndOpenATM
  • qb-banking:server:getCardableAccounts
  • qb-banking:server:orderCardForAccount
  • qb-banking:server:selectCardForATM
  • qb-banking:server:verifyCardPIN
  • qb-banking:server:getPlayerCards
  • qb-banking:server:freezeCard
  • qb-banking:server:unfreezeCard
  • qb-banking:server:changeCardPIN
  • qb-banking:server:cancelCard
  • qb-banking:server:orderReplacementCard

Savings and recurring payments

  • qb-banking:server:createSavingsAccount
  • qb-banking:server:getSavingsAccounts
  • qb-banking:server:depositToSavings
  • qb-banking:server:withdrawFromSavings
  • qb-banking:server:closeSavingsAccount
  • qb-banking:server:createSavingsGoal
  • qb-banking:server:getSavingsGoals
  • qb-banking:server:contributeToGoal
  • qb-banking:server:withdrawFromGoal
  • qb-banking:server:deleteSavingsGoal
  • qb-banking:server:createRecurringPayment
  • qb-banking:server:getRecurringPayments
  • qb-banking:server:cancelRecurringPayment
  • qb-banking:server:toggleRecurringPayment
  • qb-banking:server:updateRecurringPayment
  • qb-banking:server:getPendingTransfers
  • qb-banking:server:cancelPendingTransfer
  • qb-banking:server:getTransferSettings
  • qb-banking:server:getTransferDelayInfo

Loans, credit, investments, and security

  • qb-banking:server:getLoans
  • qb-banking:server:getLoanProducts
  • qb-banking:server:checkLoanEligibility
  • qb-banking:server:getLoanTerms
  • qb-banking:server:applyForLoan
  • qb-banking:server:payLoan
  • qb-banking:server:payOffLoan
  • qb-banking:server:getLoanPayments
  • qb-banking:server:getLoanPayoffAmount
  • qb-banking:server:getCreditBreakdown
  • qb-banking:server:getCreditHistory
  • qb-banking:server:recalculateCreditScore
  • qb-banking:server:getInvestments
  • qb-banking:server:createInvestment
  • qb-banking:server:withdrawInvestment
  • qb-banking:server:getCDs
  • qb-banking:server:purchaseCD
  • qb-banking:server:redeemCD
  • qb-banking:server:earlyWithdrawCD
  • qb-banking:server:getMarketState
  • qb-banking:server:getMarketHistory
  • qb-banking:server:enable2FA
  • qb-banking:server:disable2FA
  • qb-banking:server:verify2FA
  • qb-banking:server:get2FAStatus
  • qb-banking:server:getBackupCodes
  • qb-banking:server:regenerateBackupCodes
  • qb-banking:server:getSecuritySettings
  • qb-banking:server:getSecurityLog
  • qb-banking:server:getAlertPreferences
  • qb-banking:server:setAlertPreferences
  • qb-banking:server:selfFreezeAccount
  • qb-banking:server:selfUnfreezeAccount
  • qb-banking:server:getFreezeStatus

Business

  • qb-banking:server:recordExpense
  • qb-banking:server:getExpenses
  • qb-banking:server:getExpenseSummary
  • qb-banking:server:createInvoice
  • qb-banking:server:payInvoice
  • qb-banking:server:cancelInvoice
  • qb-banking:server:getInvoices
  • qb-banking:server:getIncomeStatement
  • qb-banking:server:getBalanceReport
  • qb-banking:server:getCashFlowReport
  • qb-banking:server:getExpenseCategories
  • qb-banking:server:getJobActivity

Recommendation

Use exports['oxide-banking'] for new integration work.

Reserve exports['qb-banking'] and qb-banking:server:* callback names for legacy resources that still need them.

On this page

Resource NamesServer ExportsCore / readinessIsReady() -> booleanGetPlayerBankingData(citizenid) -> { account, creditScore, tier, loans, statements }GetAccountData(accountName) -> table?GetPlayerAccounts(citizenid) -> table[]GetPlayerStatements(citizenid, limit = 50) -> table[]CanAfford(citizenid, amount, accountName) -> booleanTiersGetPlayerTier(citizenid) -> stringUpgradePlayerTier(citizenid, newTier) -> booleanGetAvailableTiers(citizenid) -> { [tierName] = table }GetTierLevel(tierName) -> numberCheckTierRequirements(citizenid, tierName) -> boolean, errorMessage?UpgradeAccountTier(citizenid, newTier) -> boolean, tierLabel | errorMessageDowngradeAccountTier(citizenid, newTier = 'basic') -> boolean, tierLabel | errorMessageCredit scoreGetCreditScore(citizenid) -> numberUpdateCreditScore(citizenid, change, reason) -> numberRecalculateCreditScore(citizenid) -> number, { factors, weightedScore, finalScore, oldScore }GetCreditScoreBreakdown(citizenid) -> { score, rating, factors, suggestions, lastUpdated }GetCreditHistory(citizenid, limit = 50) -> table[]RecordCreditEvent(citizenid, eventType, data) -> nilAccount freezeFreezeAccount(citizenid, accountName, reason, frozenBy, frozenType = 'admin', duration?) -> booleanUnfreezeAccount(citizenid, accountName) -> booleanSelfFreezeAccount(citizenid, duration, reason) -> booleanSelfUnfreezeAccount(citizenid) -> boolean, errorMessage?GetFreezeStatus(citizenid) -> { frozen, reason, expiresAt, frozenType, canSelfUnfreeze }IsAccountLocked(citizenid) -> boolean, secondsRemaining?Savings accountsCreateSavingsAccount(citizenid, accountName, initialDeposit) -> boolean, { id, account_name, balance } | errorMessageGetSavingsAccounts(citizenid) -> table[]DepositToSavings(citizenid, accountName, amount) -> boolean, newBalance | errorMessageWithdrawFromSavings(citizenid, accountName, amount, applyPenalty = true) -> boolean, { withdrawn, penalty, netAmount, newBalance } | errorMessageCloseSavingsAccount(citizenid, accountName) -> boolean, { finalAmount, refunded, penalty } | errorMessageSavings goalsCreateSavingsGoal(citizenid, goalName, targetAmount, category, targetDate) -> boolean, { id, goal_name, target_amount, category } | errorMessageGetSavingsGoals(citizenid) -> table[]ContributeToGoal(citizenid, goalId, amount) -> boolean, { newAmount, progress, completed } | errorMessageWithdrawFromGoal(citizenid, goalId, amount) -> boolean, { newAmount, progress } | errorMessageDeleteSavingsGoal(citizenid, goalId) -> boolean, { refundedAmount } | errorMessageCards — issuance & lifecycleIssueCardForAccount(source, accountName, pin) -> boolean, { cardNumber, cardNumberMasked, accountName } | errorKeyOrderReplacementCard(source, oldCardNumber, newPin) -> boolean, { cardNumber, cardNumberMasked, accountName } | errorReasonFreezeCard(cardNumber) -> boolean, errorReason?UnfreezeCard(cardNumber) -> boolean, errorReason?CancelCard(cardNumber) -> boolean, errorReason?RevokeCard(cardNumber, reason) -> booleanRevokeCardsForAccount(accountName, reason) -> nilChangeCardPIN(cardNumber, oldPin, newPin) -> boolean, errorReason?Cards — queries & validationValidateCardAccess(citizenid, cardNumber) -> boolean, card | errorStringValidateCardPIN(cardNumber, pin) -> boolean, card | errorStringGetPlayerCards(citizenid) -> table[]GetPlayerInventoryCards(source) -> table[]GetCardsForAccount(accountName) -> string[]GetAccountCardCount(accountName) -> numberCanIssueCardForAccount(citizenid, accountName) -> boolean, reason?HasAccountAccess(citizenid, accountName) -> boolean, permissionTypeGetAccessibleAccounts(citizenid) -> table[]MaskCardNumber(cardNumber) -> stringFormatCardNumber(cardNumber) -> stringTransactions — fees & previewsCalculateTransactionFee(citizenid, feeKey, amount) -> feeAmount, waiverReason?GetFeePreview(citizenid, feeKey, amount) -> { feeKey, feeDescription, amount, isWaived, waiverReason, transactionAmount, totalAmount }CalculateATMFee(citizenid, atmType) -> feeAmount, waiverReason?CalculateWireTransferFee(citizenid, transferType = 'domestic') -> feeAmount, waiverReason?CheckDailyLimit(citizenid, limitType, amount) -> allowed, remainingGetExpeditedTransferFee() -> numberIsExpeditedTransferEnabled() -> booleanTransactions — wire & pending transfersProcessWireTransfer(fromCitizenId, toCitizenId, amount, transferType = 'domestic') -> boolean, messageCreatePendingTransfer(fromCitizenId, toCitizenId, amount, transferType, reason, expedited) -> result, statusStringGetPendingTransfers(citizenid) -> table[]CancelPendingTransfer(citizenid, transferId) -> boolean, messageLoansApplyForLoan(citizenid, loanType, amount, termDays, collateralType, collateralId) -> boolean, loanId | errorMessage, status?CheckLoanEligibility(citizenid, loanType, amount) -> boolean, message, requirementsDataCalculateLoanTerms(citizenid, loanType, amount, termDays) -> { principal, interestRate, rateModifier, termDays, totalInterest, totalAmount, paymentAmount, creditScore }GetPlayerLoans(citizenid) -> table[]GetLoanProducts(citizenid) -> { [productName] = { label, personalizedRate, requirements, meetsRequirements, ... } }MakeLoanPayment(citizenid, loanId, amount) -> boolean, { amount, principalPaid, lateFeesPaid, remainingBalance, status, isLate } | errorMessagePayOffLoan(citizenid, loanId) -> boolean, paymentResult | errorMessageCalculatePayoffAmount(loanId) -> { total, principal, lateFees }GetLoanPaymentHistory(loanId) -> table[]StartCollections(citizenid, loanId) -> booleanVehicle financingRegisterVehicleLoan(data) -> boolean, loanId | errorMessageRecordVehicleLoanPayment(plate, amount) -> boolean, { loanId, amount, remainingBalance, status, paymentsMade } | errorMessageCloseVehicleLoan(plate, reason = 'paid') -> boolean, errorMessage?GetVehicleLoan(plate) -> loan?InterestCalculateInterest(balance, dailyRate, days, method = 'compound') -> numberGetEffectiveInterestRate(citizenid, accountType) -> numberProcessLoginInterest(source) -> numberProcessMonthlyFees(source) -> numberInvestments & CDsCreateInvestment(citizenid, productType, amount) -> boolean, { id, product, maturityDate } | errorMessageGetPlayerInvestments(citizenid) -> table[]WithdrawInvestment(citizenid, investmentId, early) -> boolean, { payout, penalty, gain } | errorMessagePurchaseCD(citizenid, productType, amount) -> boolean, { id, maturityDate, maturityValue } | errorMessageGetPlayerCDs(citizenid) -> table[]RedeemCD(citizenid, cdId) -> boolean, { payout, interest } | errorMessageEarlyWithdrawCD(citizenid, cdId) -> boolean, { payout, penalty } | errorMessageGetMarketState() -> { trend, modifier, trendDaysRemaining, lastUpdate, previousDayChange, momentum }GetMarketHistory(days = Config.TimeSettings.DaysPerYear) -> table[]Security — 2FAEnable2FA(citizenid, securityPin) -> boolean, backupCodes | errorMessageDisable2FA(citizenid, verificationCode) -> boolean, errorMessage?Verify2FA(citizenid, code) -> boolean, errorMessage?Requires2FA(citizenid, amount) -> booleanGet2FAStatus(citizenid) -> { enabled, backupCodesRemaining, threshold }GenerateBackupCodes(citizenid) -> boolean, codes | errorMessageSecurity — fraud & alertsTrackPlayerLogin(source, citizenid) -> nilCheckForFraud(citizenid, transactionType, amount, targetCitizenId) -> flagged, flagsFlagSuspiciousActivity(citizenid, reason, data) -> nilSendTransactionAlert(citizenid, transactionType, amount, details) -> nilGetAlertPreferences(citizenid) -> { enabled, threshold, types }SetAlertPreferences(citizenid, prefs) -> booleanBusiness — invoicesCreateInvoice(fromCitizenId, fromJob, toCitizenId, amount, description, dueDate) -> boolean, { invoiceId, invoiceNumber, dueDate } | errorMessagePayInvoice(citizenid, invoiceId) -> boolean, { invoiceNumber, amountPaid } | errorMessageCancelInvoice(citizenid, invoiceId) -> boolean, message | errorMessageGetInvoices(citizenid, jobName, filter) -> table[]Business — expenses & reportsRecordExpense(jobName, category, amount, description, recordedBy) -> boolean, { expenseId } | errorMessageGetExpenses(jobName, filters) -> table[]GetExpenseSummary(jobName, dateRange) -> { categories, grandTotal, startDate, endDate }GenerateIncomeStatement(jobName, startDate, endDate) -> { totalIncome, operatingExpenses, expenseBreakdown, netIncome, profitMargin, ... }GenerateBalanceReport(jobName) -> { balance, receivables, payables, netPosition, receivableCount }GenerateCashFlowReport(jobName, startDate, endDate) -> { totalInflows, totalOutflows, netCashFlow, byMonth, startDate, endDate }Legacy qb-banking Compatibility ExportsCreatePlayerAccount(playerId, accountName, accountBalance, accountUsers) -> boolean, errorMessage?CreateJobAccount(accountName, accountBalance) -> booleanCreateGangAccount(accountName, accountBalance) -> booleanCreateBankStatement(playerId, account, amount, reason, statementType, accountType) -> booleanAddMoney(accountName, amount, reason) -> booleanRemoveMoney(accountName, amount, reason) -> booleanGetAccount(accountName) -> table?GetAccountBalance(accountName) -> numberAddGangMoney(accountName, amount, reason) -> booleanRemoveGangMoney(accountName, amount, reason) -> booleanGetGangAccount(accountName) -> table?GetGangAccountBalance(accountName) -> numberClient ExportsOpenBank() -> nilCloseBank() -> nilOpenATM() -> nilOpenCardSelector() -> nilCloseCardSelector() -> nilIsBankOpen() -> booleanIsATMOpen() -> booleanIsCardSelectorOpen() -> booleanGetActiveATMSession() -> { cardNumber, accountName, accountType, dailyLimit, dailyUsed, dailyRemaining } | nilGetSelectedCard() -> card | nilIsInBankZone() -> booleanIsNearATM() -> boolean, atmHandle?Callback SurfaceBank, ATM, transfers, and tiersCardsSavings and recurring paymentsLoans, credit, investments, and securityBusinessRecommendation