# Concepts

> Core concepts for Alpha Ladder AgentX — account model, currency typing, fees, minor units, verification codes, module permissions, and error shapes.

This page defines the data model and conventions shared across all AgentX MCP tools. Read this before working with any AgentX tool.

---

## Account model

A Alpha Ladder account is partitioned into named sub-accounts called **product accounts**, each identified by a `productCode` enum value:

| `productCode` | Description |
|---|---|
| `fiat` | Fiat currency account (USD, HKD, EUR, etc.) |
| `investment_fiat` | Fiat funds currently locked in an investment product |
| `quarantine_portfolio` | Assets frozen under compliance review |
| `investment_product` | Balance held in investment products such as FIP |
| `named_account` | Same-name account balance — funds held in accounts registered under the holder's own name |

Use [`get_account_summary`](/developers/financial-services/accounts) to see USD-equivalent totals across all categories. Use [`get_account_detail`](/developers/financial-services/accounts) with a specific `productCode` to drill into individual currency balances.

The `investment_product` account returns an empty `instrumentInfoMap` (`{}`); it has no per-currency breakdown.

---

## First-party vs third-party (COBO)

Many deposit and withdrawal tools accept a `withdrawalParty` parameter that distinguishes between two counterparty modes:

| Value | Meaning |
|---|---|
| `1` (integer) or `'first_party'` (string enum) | The account owner is the counterparty — own bank account |
| `2` (integer) or `'third_party'` (string enum) | A COBO third-party counterparty — someone else's bank account |

The exact type (integer `1`/`2` vs string `'first_party'`/`'third_party'`) varies per tool — see the individual tool parameter tables in [MCP Tools](/developers/financial-services/tools).

**Third-party requirements:**

- `purposeOfTransaction` (free text) is always required when `withdrawalParty = 2` on execute calls.

---

## Fees and charge types

**`chargeType`** (integer, used in `execute_fiat_withdrawal`) specifies who bears the bank transfer charge:

| `chargeType` | Meaning |
|---|---|
| `1` | Fee borne by beneficiary |
| `2` | Fee borne by sender |
| `3` | Shared between both parties |

**`feePayer`** (string enum, used in deposit estimate tools) controls service fee allocation:

| `feePayer` | Meaning |
|---|---|
| `'paid_by_me'` | Fee deducted from the deposit amount — the user's net received amount is shown |
| `'paid_by_third_party'` | Fee added on top — the payor's gross send amount is shown |

Use `get_withdrawal_quote` before executing a withdrawal to retrieve both the service fee (`fee.serviceFee`) and the minimum allowed amount (`minimumAmount.minimumAmount`) in a single call.

---

## Minor units

The history list endpoints — `get_deposit_list` and `get_withdrawal_list` — return monetary amounts as **integers in minor units** (e.g. cents for USD):

- `totalAmount`, `receiveAmount`, `chargeAmount` — all minor units.
- Divide by `10^decimals` before displaying. The decimal precision per currency is determined by the product base list.

<Callout type="info">**Example:** a USD amount of `150025` represents `$1,500.25` (USD has 2 decimal places). The execute tool (`execute_fiat_withdrawal`) and account tools use decimal strings (`"1500.25"`) — no conversion needed.</Callout>

---

## Verification codes

<Callout type="info">The execute-level withdrawal tool (`execute_fiat_withdrawal`) requires a `verificationCode` parameter. This is a time-limited one-time code issued by Alpha Ladder's security verification flow. MCP does not generate this code for you.</Callout>

Before calling the execute-level withdrawal tool:

- Ensure the user has already obtained a currently valid verification code from Alpha Ladder.
- Treat the code as user-held input, not as a value that can be derived from another MCP tool call.
- Do not cache or reuse an old code across sessions or after a failed attempt.
- If the code is missing, invalid, or expired, stop the flow and ask the user to obtain a new one before retrying.

Passing an invalid or expired code results in a server-side validation error.

---

## Module permissions

Before attempting any operation, call `get_module_permissions` to verify the current user has access to the relevant module:

| Module | Controls |
|---|---|
| `deposit` | `get_fiat_deposit_*`, `get_deposit_bank_account`, deposit estimate/submit tools |
| `otc` | `get_available_currency_pairs`, `get_exchange_quote`, `get_otc_quote`, `confirm_otc_trade`, `get_otc_trade_detail` |
| `withdrawal` | `get_withdrawal_*`, `get_fiat_withdrawal_bank_accounts`, `execute_fiat_withdrawal` |
| `wealth` | `get_fip_products`, `get_fip_agreement`, `investor_precheck`, `fip_subscribe` |

The tool returns an array of `{ module, hasPermission }` objects. Attempting a module operation without the corresponding permission will be rejected.

In guided agent flows, check module permissions before offering destructive actions to the user. This avoids walking the user through a flow that their account cannot complete.

---

## Error and re-authentication shape

All AgentX tools may return an error object instead of the normal success payload when the session is invalid or an operation fails:

```json
{
  "error": true,
  "message": "Session expired",
  "authUrl": "https://www.alphaladder.hk/..."
}
```

| Field | Type | Description |
|---|---|---|
| `error` | `true` | Literal — always present on error responses |
| `message` | string | Human-readable error description |
| `authUrl` | string (optional) | Re-authentication URL; present when the session has expired and the user must log in again |

When `authUrl` is present, direct the user to that URL to re-authenticate, then retry the operation.

For OTC-specific errors (HTTP 410 / 409), see the [Response Reference](/developers/financial-services/responses).
