> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zbx.boomfi.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Trading API Guide

> Accounts, Quick Trade, Sweep Trade, orders, discovery, and errors for partner trading.

All paths are relative to `https://mapi.zbx.boomfi.xyz/v1` (includes `/v1`). Send `X-API-KEY` on every request. Successful responses wrap payload in `{"data": …}`; failures use the [error envelope](/api/response-patterns). Amounts are decimal strings.

Request and response schemas for Instruments, Quotes, and Orders are in the API reference.

## Accounts and balances

### `GET /accounts/virtual`

Returns your virtual account and per-chain sub-accounts. Each sub-account's `address` is your **funding address** for that chain: deposit directly (for example from custody); credit lands after on-chain confirmation.

### `GET /accounts/virtual/balances`

Returns every non-zero balance across the virtual account hierarchy: crypto per chain plus fiat ledgers. `pending_amount` covers value locked or in flight (for example mid-trade), so funds are never invisible during a conversion. `amount_billing_currency` and `total_balance` are USD-equivalent when present.

Fiat settlement requires a registered fiat external account. Off-ramp proceeds in USD / EUR / GBP are delivered to the bank account you register for that currency.

### Fiat external accounts

Register a bank account **once per settlement currency** via:

```
POST https://mapi.zbx.boomfi.xyz/v1/bankAddressBook
```

New registrations start **Pending** and are disabled while details are verified: settlement only uses **enabled, verified** accounts.

| Field                 | Type   | Required | Description                                                                                                                      |
| --------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `name`                | string | yes      | Your label for the account                                                                                                       |
| `account_number`      | string | yes      | Bank account number / IBAN (encrypted at rest; responses return a masked hint)                                                   |
| `bank_name`           | string | yes      | Name of the bank                                                                                                                 |
| `account_holder_name` | string | yes      | Legal account holder (encrypted / masked in responses)                                                                           |
| `country`             | string | yes      | Bank country (ISO name or code)                                                                                                  |
| `currency`            | string | yes      | Settlement currency (`USD`, `EUR`, `GBP`). One account per currency: a second registration for the same currency returns **409** |

Manage registrations with `GET /bankAddressBook` and `GET` / `PATCH` / `DELETE /bankAddressBook/{id}`.

Once enabled, the account is used automatically for fiat settlement in its currency: or target it explicitly with `settlement_account_id` on a trade.

## Getting an estimate (dry run)

Add `"dry_run": true` on Quick Trade or Sweep Trade to receive a priced quote **without** execution. Dry runs do not require sufficient balance, do not reserve funds, and do not create an order: use them to display prices to end users.

```bash theme={null}
curl -X POST "https://mapi.zbx.boomfi.xyz/v1/trade/quicktrade" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "account_reference": "treasury-main",
    "currency": "USDC",
    "chain_id": 137,
    "amount": "25000",
    "to_currency": "USD",
    "dry_run": true
  }'
```

**All-in pricing.** The quoted receive amount is net: spread, network costs, and fees are already deducted. The `fees` object is an informational breakdown. Prefer the effective rate from the response (receive amount ÷ total sell amount). There is nothing to add on top.

## Quick Trade: `POST /trade/quicktrade`

Quotes and executes in one atomic call, funded from a balance you already hold. Covers crypto → crypto across chains and crypto → fiat (off-ramp). Fiat-funded trades use the same shape when enabled for your organisation.

| Field                   | Type   | Required | Description                                                                                                                                                                           |
| ----------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account_id`            | int    | one of   | Source-of-funds account. For crypto sells, pass the virtual (parent) account: the chain sub-account is resolved automatically. For fiat-funded trades, pass your fiat ledger account. |
| `account_reference`     | string | one of   | Same as `account_id`, by your reference                                                                                                                                               |
| `currency`              | string | yes      | Sell currency symbol (`USDC`, `ETH`, `USD`, …)                                                                                                                                        |
| `amount`                | string | yes      | Sell amount (decimal string). Must be covered by available balance on execute.                                                                                                        |
| `chain_id`              | int    | crypto   | Chain of the sell currency. Omit for fiat.                                                                                                                                            |
| `to_currency`           | string | yes      | Buy currency symbol                                                                                                                                                                   |
| `to_chain_id`           | int    | crypto   | Chain of the buy currency. Omit for fiat.                                                                                                                                             |
| `settlement_address`    | string | no       | External wallet for proceeds on the buy chain. Mutually exclusive with `settlement_account_id`.                                                                                       |
| `settlement_account_id` | int    | no       | Account to settle to (for example a verified fiat external account)                                                                                                                   |
| `reference`             | string | no       | Your free-form reference (echoed on the execute response)                                                                                                                             |
| `dry_run`               | bool   | no       | `true` = estimate only                                                                                                                                                                |

### Rules worth knowing

* If no settlement target is given, crypto proceeds settle back to your account on the buy chain; fiat buys go to your enabled fiat external account for that currency.
* Selling and buying the exact same currency + chain is rejected: use a payout for plain transfers.
* On Polygon (`137`), `POL` and `MATIC` are accepted as aliases.
* **Solana native SOL:** a sell must either take the balance to exactly zero or leave at least `0.00089088` SOL (rent-exemption). Amounts that would strand dust below that minimum are rejected with an explanatory error.
* Fiat-funded trades (`currency` as fiat, no `chain_id`) are enabled per organisation: ask your ZBX contact.

### Example requests

**Off-ramp:** sell 25,000 USDC (Polygon) → USD

```bash theme={null}
curl -X POST "https://mapi.zbx.boomfi.xyz/v1/trade/quicktrade" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "account_reference": "treasury-main",
    "currency": "USDC",
    "chain_id": 137,
    "amount": "25000",
    "to_currency": "USD",
    "reference": "offramp-user-001"
  }'
```

**Off-ramp:** sell 26,000 USDT (BNB Chain) → EUR

```bash theme={null}
curl -X POST "https://mapi.zbx.boomfi.xyz/v1/trade/quicktrade" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "account_reference": "treasury-main",
    "currency": "USDT",
    "chain_id": 56,
    "amount": "26000",
    "to_currency": "EUR"
  }'
```

**Cross-chain:** USDC (Polygon) → USDC (Ethereum), delivered to custody

```bash theme={null}
curl -X POST "https://mapi.zbx.boomfi.xyz/v1/trade/quicktrade" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "account_reference": "treasury-main",
    "currency": "USDC",
    "chain_id": 137,
    "amount": "10000",
    "to_currency": "USDC",
    "to_chain_id": 1,
    "settlement_address": "0xYourCustodyDepositAddress"
  }'
```

## Sweep Trade: `POST /trade/sweeptrade`

Sweeps every eligible balance under your virtual account into a single target asset in one basket order (for example end-of-day consolidation into USDC on Ethereum, or into USD). Same shape as Quick Trade **minus** `currency` / `amount` (sell side is discovered from balances), plus thresholds:

| Field             | Type   | Default | Description                                                             |
| ----------------- | ------ | ------- | ----------------------------------------------------------------------- |
| `min_amount_usd`  | number | `1`     | Skip balances whose USD value is below this                             |
| `max_amount_usd`  | number | none    | Cap / skip balances above this USD notional (as implemented on the API) |
| `keep_amount_usd` | number | none    | Leave this much USD value behind in each swept balance                  |

### Sweep behaviour

* The target balance itself (same currency + chain) is never swept.
* Native gas tokens worth under \$10 are left alone so sub-accounts keep gas.
* Native SOL sweeps automatically leave the rent-exempt minimum.
* When the target is fiat, existing fiat balances are excluded (no fiat→fiat conversion).
* The response is a single order whose sell currency / amount fields may be **comma-separated** lists: one entry per swept balance.

**Example:** consolidate everything ≥ \$25 into USDC on Ethereum

```bash theme={null}
curl -X POST "https://mapi.zbx.boomfi.xyz/v1/trade/sweeptrade" \
  -H "X-API-KEY: sk_test_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "account_reference": "treasury-main",
    "to_currency": "USDC",
    "to_chain_id": 1,
    "min_amount_usd": 25
  }'
```

## Orders: `GET /trade/order`

Paginated list of orders, newest first. Filter with `status` and standard paging parameters.

| Query            | Description                                  |
| ---------------- | -------------------------------------------- |
| `status`         | `Open` · `Closed` · `Rejected`               |
| `page`, `limit`  | Page number (from 1) and page size (max 100) |
| `since`, `until` | RFC3339 bounds on `created_at`               |
| `sort`           | `asc` or `desc`                              |

**Polling, not webhooks.** Trade orders do not emit webhook events: poll `GET /trade/order` (every 5–10 s while `Open`, backing off after a few minutes). Most balance-funded conversions complete within minutes; timing varies with networks and rails.

## Discovery

### `GET /trade/currencies`

Tradable currency universe: symbol, type (`Fiat` / `Digital`) and, for tokens, supported `chain_id`s with token contract addresses. Cached \~1 minute.

### `GET /trade/swap-targets`

Every currency + chain reachable from a starting asset, filtered to chains your account can settle on: useful for destination pickers.

| Query            | Required | Description                                                              |
| ---------------- | -------- | ------------------------------------------------------------------------ |
| `currency`       | yes      | Starting currency symbol                                                 |
| `chain_id`       | yes      | Starting chain                                                           |
| `amount`         | yes      | Intended size (routing can be size-dependent)                            |
| `check_currency` | no       | When true, also verifies fiat currency support on the settlement account |

## Errors

Standard envelope ([Response Patterns](/api/response-patterns)):

```json theme={null}
{
  "error": {
    "code": 400,
    "message": "…",
    "errors": [{ "domain": "…", "reason": "…" }]
  }
}
```

| HTTP | Message (examples)                                            | What to do                                                      |
| ---- | ------------------------------------------------------------- | --------------------------------------------------------------- |
| 400  | insufficient balance                                          | Top up the source account or lower the amount                   |
| 400  | chain\_id is required for digital currencies                  | Pass `chain_id` / `to_chain_id` for crypto legs                 |
| 400  | cannot trade same instrument…                                 | Source and target identical: use a payout instead               |
| 400  | Quote expired                                                 | 10-second validity lapsed: request a fresh quote                |
| 400  | amount would leave … SOL: below Solana's rent-exempt minimum… | Sell full SOL balance or leave ≥ 0.00089088 SOL                 |
| 404  | account not found / not found by reference                    | Check the account id/reference for your org                     |
| 409  | Trade not feasible: \<reason>                                 | Pre-trade liquidity check failed: wait and re-submit            |
| 502  | Trade pre-check failed                                        | Transient upstream: retry with backoff                          |
| 500  | n/a                                                           | Retry once; if persistent, contact support with request context |

## Next

* [Advanced RFQ](/trading/advanced-rfq)
* [Integration Playbook](/trading/integration-playbook)
