> ## Documentation Index
> Fetch the complete documentation index at: https://mythicframework.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Finance - Banking

> Bank account management, balance operations, and transaction logging

The Banking component manages player bank accounts, balance operations, and transaction history. It supports personal checking, savings, and organization accounts.

## Overview

Access via `Banking` (server-side only).

<CardGroup cols={2}>
  <Card title="Account Types" icon="wallet">
    Personal, Savings, Organization
  </Card>

  <Card title="Balance Operations" icon="money-bill-transfer">
    Deposit, Withdraw, Charge
  </Card>

  <Card title="Transaction Logs" icon="receipt">
    Full transaction history per account
  </Card>

  <Card title="Joint Accounts" icon="users">
    Savings accounts with joint owners
  </Card>
</CardGroup>

<Warning>
  **Server-Side Only:** All banking operations must be performed on the server. Never attempt to modify balances from the client.
</Warning>

***

## Account Management

### Banking.Accounts:Get

Get an account by its account number.

```lua theme={null}
Banking.Accounts:Get(accountNumber)
```

<ParamField path="accountNumber" type="string" required>
  The bank account number
</ParamField>

<ResponseField name="account" type="table|nil">
  Account data or `nil` if not found
</ResponseField>

**Example:**

```lua theme={null}
local account = Banking.Accounts:Get("1234567890")

if account then
    print('Account:', account.Account)
    print('Balance:', account.Balance)
    print('Type:', account.Type)
end
```

***

### Banking.Accounts:CreatePersonal

Creates or retrieves an existing personal checking account for a character. New accounts start with \$5,000.

```lua theme={null}
Banking.Accounts:CreatePersonal(ownerSID)
```

<ParamField path="ownerSID" type="number" required>
  Character State ID (SID)
</ParamField>

<ResponseField name="account" type="table">
  The personal checking account data
</ResponseField>

**Example:**

```lua theme={null}
-- During character creation
AddEventHandler('mythic-characters:server:CharacterCreated', function(source, character)
    local account = Banking.Accounts:CreatePersonal(character.SID)

    Logger:Info('Finance', 'Personal account created', {
        console = true,
        file = true
    }, {
        character = character.SID,
        account = account.Account
    })
end)
```

***

### Banking.Accounts:GetPersonal

Retrieves an existing personal checking account.

```lua theme={null}
Banking.Accounts:GetPersonal(ownerSID)
```

<ParamField path="ownerSID" type="number" required>
  Character State ID (SID)
</ParamField>

<ResponseField name="account" type="table|nil">
  Personal account or `nil` if none exists
</ResponseField>

**Example:**

```lua theme={null}
local player = Fetch:Source(source)
local char = player:GetData('Character')
local stateId = char:GetData('SID')

local account = Banking.Accounts:GetPersonal(stateId)

if account then
    print('Balance: $' .. account.Balance)
end
```

***

### Banking.Accounts:CreatePersonalSavings

Creates a personal savings account with optional joint owners.

```lua theme={null}
Banking.Accounts:CreatePersonalSavings(ownerSID, jointOwners)
```

<ParamField path="ownerSID" type="number" required>
  Character State ID
</ParamField>

<ParamField path="jointOwners" type="table" optional>
  Array of State IDs for joint owners
</ParamField>

**Example:**

```lua theme={null}
-- Create savings with a joint owner
local savings = Banking.Accounts:CreatePersonalSavings(char:GetData('SID'), { partnerSID })
```

***

### Banking.Accounts:GetPersonalSavings

Gets all savings accounts a character owns or has joint access to.

```lua theme={null}
Banking.Accounts:GetPersonalSavings(SID)
```

<ParamField path="SID" type="number" required>
  Character State ID
</ParamField>

<ResponseField name="accounts" type="table">
  Array of savings accounts (owned and joint)
</ResponseField>

***

### Banking.Accounts:AddPersonalSavingsJointOwner

Adds a joint owner to a savings account.

```lua theme={null}
Banking.Accounts:AddPersonalSavingsJointOwner(accountId, jointOwnerSID)
```

<ParamField path="accountId" type="string" required>
  Account number
</ParamField>

<ParamField path="jointOwnerSID" type="number" required>
  State ID of the new joint owner
</ParamField>

***

### Banking.Accounts:RemovePersonalSavingsJointOwner

Removes a joint owner from a savings account.

```lua theme={null}
Banking.Accounts:RemovePersonalSavingsJointOwner(accountId, jointOwnerSID)
```

***

### Banking.Accounts:CreateOrganization

Creates an organization (business/government) bank account.

```lua theme={null}
Banking.Accounts:CreateOrganization(accountId, accountName, startingBalance, jobAccess)
```

<ParamField path="accountId" type="string" required>
  Custom account number/ID
</ParamField>

<ParamField path="accountName" type="string" required>
  Display name for the account
</ParamField>

<ParamField path="startingBalance" type="number" required>
  Initial balance
</ParamField>

<ParamField path="jobAccess" type="table" required>
  Array of job access definitions
</ParamField>

**Example:**

```lua theme={null}
-- Create police department account with default permissions
Banking.Accounts:CreateOrganization('police-lspd', 'LSPD Account', 100000, {
    {
        Job = 'police',
        Workplace = 'lspd',
        Permissions = {
            MANAGE = 'BANK_ACCOUNT_MANAGE',
            WITHDRAW = 'BANK_ACCOUNT_WITHDRAW',
            DEPOSIT = 'BANK_ACCOUNT_DEPOSIT',
            TRANSACTIONS = 'BANK_ACCOUNT_TRANSACTIONS',
            BILL = 'BANK_ACCOUNT_BILL',
            BALANCE = 'BANK_ACCOUNT_BALANCE',
        }
    }
})
```

<Note>
  Permission values are **job permission strings** (not grade numbers). The system checks if the player's job has the specified permission via `Jobs.Permissions:HasJob`. Use strings like `'BANK_ACCOUNT_WITHDRAW'` which map to job permission definitions.
</Note>

***

### Banking.Accounts:GetOrganization

Retrieves an organization account.

```lua theme={null}
Banking.Accounts:GetOrganization(accountId)
```

***

### Banking.Accounts:AddOrganizationAccessingJob

Adds job access to an existing organization account.

```lua theme={null}
Banking.Accounts:AddOrganizationAccessingJob(job, workplace, permissionSettings)
```

***

### Banking.Accounts:RemoveOrganizationAccessingJob

Removes job access from an organization account.

```lua theme={null}
Banking.Accounts:RemoveOrganizationAccessingJob(job, workplace)
```

***

## Balance Operations

### Banking.Balance:Get

Get the current balance of an account.

```lua theme={null}
Banking.Balance:Get(accountNumber)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ResponseField name="balance" type="number">
  Current balance
</ResponseField>

**Example:**

```lua theme={null}
local balance = Banking.Balance:Get("1234567890")
print('Current balance: $' .. balance)
```

***

### Banking.Balance:Has

Check if an account has sufficient funds.

```lua theme={null}
Banking.Balance:Has(accountNumber, amount)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ParamField path="amount" type="number" required>
  Amount to check against
</ParamField>

<ResponseField name="hasFunds" type="boolean">
  `true` if balance >= amount
</ResponseField>

**Example:**

```lua theme={null}
if Banking.Balance:Has(account.Account, 5000) then
    -- Player can afford it
else
    TriggerClientEvent('mythic-notifications:client:Send', source, {
        message = 'Insufficient funds',
        type = 'error'
    })
end
```

***

### Banking.Balance:Deposit

Deposit funds into an account.

```lua theme={null}
Banking.Balance:Deposit(accountNumber, amount, transactionLog, skipPhoneNoti)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ParamField path="amount" type="number" required>
  Amount to deposit
</ParamField>

<ParamField path="transactionLog" type="table" required>
  Transaction log entry (see Transaction Log Structure below)
</ParamField>

<ParamField path="skipPhoneNoti" type="boolean" optional>
  Skip sending phone notification
</ParamField>

<ResponseField name="newBalance" type="number">
  Updated balance after deposit
</ResponseField>

**Example:**

```lua theme={null}
local player = Fetch:Source(source)
local char = player:GetData('Character')
local account = Banking.Accounts:GetPersonal(char:GetData('SID'))

local newBalance = Banking.Balance:Deposit(account.Account, 5000, {
    type = 'deposit',
    title = 'Paycheck',
    description = 'Weekly salary payment',
    transactionAccount = false,
    data = {}
})
```

***

### Banking.Balance:Withdraw

Withdraw funds from an account.

```lua theme={null}
Banking.Balance:Withdraw(accountNumber, amount, transactionLog)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ParamField path="amount" type="number" required>
  Amount to withdraw
</ParamField>

<ParamField path="transactionLog" type="table" required>
  Transaction log entry
</ParamField>

<ResponseField name="newBalance" type="number">
  Updated balance after withdrawal
</ResponseField>

<Warning>
  `Withdraw` does NOT check if the account has sufficient funds. Use `Charge` if you need automatic validation, or check with `Has` first.
</Warning>

***

### Banking.Balance:Charge

Withdraw funds only if the account has sufficient balance.

```lua theme={null}
Banking.Balance:Charge(accountNumber, amount, transactionLog)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ParamField path="amount" type="number" required>
  Amount to charge
</ParamField>

<ParamField path="transactionLog" type="table" required>
  Transaction log entry
</ParamField>

<ResponseField name="result" type="number|boolean">
  New balance if successful, `false` if insufficient funds
</ResponseField>

**Example:**

```lua theme={null}
local result = Banking.Balance:Charge(account.Account, 2500, {
    type = 'withdraw',
    title = 'Vehicle Purchase',
    description = 'Bought Elegy RH8',
    transactionAccount = false,
    data = { vehicle = 'elegy' }
})

if result then
    -- Purchase successful, new balance = result
    TriggerClientEvent('mythic-notifications:client:Send', source, {
        message = 'Purchase successful! Balance: $' .. result,
        type = 'success'
    })
else
    TriggerClientEvent('mythic-notifications:client:Send', source, {
        message = 'Insufficient funds',
        type = 'error'
    })
end
```

***

## Transaction Logs

### Banking.TransactionLogs:Add

Record a transaction in the account's history.

```lua theme={null}
Banking.TransactionLogs:Add(accountNumber, type, amount, title, description, transactionAccount, data)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ParamField path="type" type="string" required>
  Transaction type: `deposit`, `withdraw`, `transfer`, `paycheck`, `fine`, `fine_profit`, `bill`, `loan`
</ParamField>

<ParamField path="amount" type="number" required>
  Transaction amount
</ParamField>

<ParamField path="title" type="string" required>
  Human-readable title
</ParamField>

<ParamField path="description" type="string" required>
  Transaction details
</ParamField>

<ParamField path="transactionAccount" type="string|boolean" required>
  Related account number, or `false` if none
</ParamField>

<ParamField path="data" type="table" optional>
  Custom data dictionary
</ParamField>

***

### Banking.TransactionLogs:Get

Get transaction history for an account.

```lua theme={null}
Banking.TransactionLogs:Get(accountNumber)
```

<ParamField path="accountNumber" type="string" required>
  Bank account number
</ParamField>

<ResponseField name="transactions" type="table">
  Array of transaction records for the account
</ResponseField>

***

## Transaction Log Structure

```lua theme={null}
{
    type = "deposit",              -- Transaction type
    title = "Paycheck",            -- Display title
    description = "Weekly salary", -- Details
    transactionAccount = false,    -- Related account or false
    data = {}                      -- Custom metadata
}
```

**Transaction Types:**

| Type          | Description                        |
| ------------- | ---------------------------------- |
| `deposit`     | Funds deposited                    |
| `withdraw`    | Funds withdrawn                    |
| `transfer`    | Funds transferred between accounts |
| `paycheck`    | Salary payment                     |
| `fine`        | Government fine                    |
| `fine_profit` | Fine revenue share                 |
| `bill`        | Bill payment                       |
| `loan`        | Loan payment                       |

***

## Account Data Structure

```lua theme={null}
{
    Account = "1234567890",    -- Account number
    Name = "Personal Account", -- Display name
    Type = "personal",         -- Account type
    Owner = 123,               -- Owner SID
    Balance = 5000,            -- Current balance
    JointOwners = {},          -- Joint owner SIDs (savings only)
    JobAccess = {}             -- Job access rules (org only)
}
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Always Use Charge for Purchases" icon="shield-check">
    ```lua theme={null}
    -- ✅ Good: Charge checks balance automatically
    local result = Banking.Balance:Charge(account.Account, price, {
        type = 'withdraw',
        title = 'Shop Purchase',
        description = itemName,
        transactionAccount = false,
        data = {}
    })

    if not result then
        return -- Insufficient funds
    end

    -- ❌ Bad: Withdraw without checking
    Banking.Balance:Withdraw(account.Account, price, transactionLog)
    ```
  </Accordion>

  <Accordion title="Log All Transactions" icon="receipt">
    ```lua theme={null}
    -- Always provide meaningful transaction logs
    Banking.Balance:Deposit(account.Account, amount, {
        type = 'deposit',
        title = 'Job Payment',
        description = string.format('Payment for %s work', jobLabel),
        transactionAccount = false,
        data = {
            job = jobName,
            hours = hoursWorked
        }
    })
    ```
  </Accordion>

  <Accordion title="Get Account Safely" icon="magnifying-glass">
    ```lua theme={null}
    local player = Fetch:Source(source)
    if not player then return end

    local char = player:GetData('Character')
    if not char then return end

    local account = Banking.Accounts:GetPersonal(char:GetData('SID'))
    if not account then return end

    -- Safe to use account
    ```
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Finance - Payments" icon="money-bill-transfer" href="/api/finance/payments">
    Cash, bills, fines, and charges
  </Card>

  <Card title="Finance - Crypto" icon="bitcoin-sign" href="/api/finance/crypto">
    Cryptocurrency system
  </Card>

  <Card title="Finance - Loans" icon="hand-holding-dollar" href="/api/finance/loans">
    Loan and credit system
  </Card>

  <Card title="Characters API" icon="user" href="/api/characters/exports">
    Character data access
  </Card>
</CardGroup>
