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

# Balances and Transfers

> Query a funding owner's per-currency balances (availableAmount and the authorization gate), and move funds between the company pool and dedicated-balance cards in a same-currency closed loop: submitting with transfer and polling the result with transfer-query.

## 📄 Guide

The balance is both the precondition for spending and the real-time authorization gate. This page covers two things: reading balances (`balance`), and moving funds between the company pool and dedicated-balance cards (`transfer` + `transfer-query`).

The funding model in one sentence: SHARED cards hold no balance and spend straight from the company pool; DEDICATED cards hold their own balance and stop when it runs out. Who holds the balance and who can be a transfer endpoint is in [Holders and the funding model](../basic-concepts/identity-and-funding); how money comes in is in [Deposits](./deposits).

## Query balances

`GET /open-api-corp/fund/v1/balance` returns a funding owner's balances per currency.

**Request parameters**

| Field         | Type   | Required | Description                                  |
| ------------- | ------ | -------- | -------------------------------------------- |
| `subjectType` | String | Yes      | `ORGANIZATION` / `CARD`                      |
| `subjectId`   | String | Yes      | ≤20; company ID or card ID                   |
| `currency`    | String | No       | `USD` / `HKD`; omit to return every currency |

**Response data** carries `subjectType`, `subjectId` and the per-currency list `balances`, one element per currency:

| Field             | Description                                       |
| ----------------- | ------------------------------------------------- |
| `currency`        | Currency: `USD` / `HKD`                           |
| `availableAmount` | Current available balance, paired with `currency` |

**Request example**

```http theme={null}
GET /open-api-corp/fund/v1/balance?subjectType=ORGANIZATION&subjectId=e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f
```

**Response example**

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "subjectType": "ORGANIZATION",
    "subjectId": "e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f",
    "balances": [
      { "currency": "USD", "availableAmount": "1000.00" },
      { "currency": "HKD", "availableAmount": "8000.00" }
    ]
  }
}
```

**Error codes**

| Code              | Description                                                     |
| ----------------- | --------------------------------------------------------------- |
| `SUBJECT_INVALID` | The funding owner (company / card) does not exist or is invalid |

<Note>
  **The balance acts as the real-time authorization gate**: a SHARED card spends straight from the company pool, a DEDICATED card from its own balance, stopping when it runs out. The authorization flow is in [Authorization and 3DS](./authorization-and-3ds).
</Note>

## Transfer funds

`POST /open-api-corp/fund/v1/transfer` moves funds between the company pool and dedicated-balance cards — same currency, no FX, closed loop within one company: COMPANY→CARD funds a card (allocates budget), CARD→COMPANY sweeps the balance back.

**Request parameters**

| Field              | Type       | Required | Description                                                                              |
| ------------------ | ---------- | -------- | ---------------------------------------------------------------------------------------- |
| `transferRef`      | String     | Yes      | ≤64; your unique transfer identifier (idempotency key), character set `^[A-Za-z0-9_-]+$` |
| `organizationId`   | String     | Yes      | ≤20; the owning company (the closed-loop boundary; both sides must belong to it)         |
| `from.subjectType` | String     | Yes      | Source subject type: `ORGANIZATION` / `CARD`                                             |
| `from.subjectId`   | String     | Yes      | ≤36; `ORGANIZATION`→`organizationId`, `CARD`→`cardId` (≤32)                              |
| `to.subjectType`   | String     | Yes      | Destination subject type: `ORGANIZATION` / `CARD` (must differ from `from.subjectType`)  |
| `to.subjectId`     | String     | Yes      | ≤36; same rules as `from.subjectId`                                                      |
| `amount`           | BigDecimal | Yes      | Greater than 0, at most 2 decimals                                                       |
| `currency`         | String     | Yes      | `USD` / `HKD`, must match both accounts' currency                                        |
| `remark`           | String     | No       | ≤256; remark                                                                             |

**Response data**

| Field          | Type   | Description                         |
| -------------- | ------ | ----------------------------------- |
| `transferId`   | String | External id of the transfer record  |
| `status`       | String | `SUCCESS` / `PROCESSING` / `FAILED` |
| `completeTime` | String | Completion time, ISO-8601           |

<Warning>
  **`PROCESSING` is not a final state**: you must poll `GET /open-api-corp/fund/v1/transfer-query` with the same `transferRef` until it returns `SUCCESS` or `FAILED` before acting on the result.
</Warning>

**Request example**

```json theme={null}
{
  "transferRef": "ext-transfer-0001",
  "organizationId": "e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f",
  "from": { "subjectType": "ORGANIZATION", "subjectId": "e7c9a1f0-3b52-4d8e-9a67-1f2b3c4d5e6f" },
  "to":   { "subjectType": "CARD", "subjectId": "5185740066240790530" },
  "amount": "1000.00",
  "currency": "USD",
  "remark": "monthly top-up"
}
```

**Response example**

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "transferId": "5185740066240790531",
    "status": "SUCCESS",
    "completeTime": "2026-08-19T10:30:00Z"
  }
}
```

**Error codes**

| Code                 | Description                                                                                                 |
| -------------------- | ----------------------------------------------------------------------------------------------------------- |
| `TRANSFER_DUPLICATE` | The `transferRef` was already submitted                                                                     |
| `SUBJECT_INVALID`    | The company / card does not exist, is not yours, or the two sides belong to different companies             |
| `CARD_NOT_DEDICATED` | The card is not a dedicated-balance card (a SHARED card holds no balance and cannot be a transfer endpoint) |
| `CARD_INVALID`       | The card is not ACTIVE                                                                                      |
| `CURRENCY_MISMATCH`  | The currency does not match the card                                                                        |
| `INSUFFICIENT_FUNDS` | The sender's balance is insufficient                                                                        |

<Tip>
  If a transfer request times out on the cardNetwork and you never see a response, retry with the **same** `transferRef`: if the first attempt was accepted you get `TRANSFER_DUPLICATE`, in which case switch to `transfer-query` for the result — the funds are never moved twice.
</Tip>

## Query a transfer result

`GET /open-api-corp/fund/v1/transfer-query` returns the final result of one transfer, looked up by `transferRef`.

**Request parameters**

| Field         | Type   | Required | Description                                            |
| ------------- | ------ | -------- | ------------------------------------------------------ |
| `transferRef` | String | Yes      | ≤64; the unique transfer identifier used at submission |

**Response data**

| Field          | Type   | Description                                       |
| -------------- | ------ | ------------------------------------------------- |
| `transferId`   | String | External id of the transfer record                |
| `status`       | String | `SUCCESS` / `PROCESSING` (in progress) / `FAILED` |
| `completeTime` | String | Completion time, ISO-8601                         |

**Request example**

```http theme={null}
GET /open-api-corp/fund/v1/transfer-query?transferRef=ext-transfer-0001
```

**Response example**

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "data": {
    "transferId": "5185740066240790531",
    "status": "SUCCESS",
    "completeTime": "2026-08-19T10:30:00Z"
  }
}
```

**Error codes**

| Code                 | Description                                                                              |
| -------------------- | ---------------------------------------------------------------------------------------- |
| `TRANSFER_NOT_FOUND` | The transfer cannot be found, or belongs to another partner (existence is not disclosed) |

## Next steps

* Fund the company pool or a dedicated-balance card: [Deposits](./deposits)
* How transfers and spending land on statements and in the records (internal allocations count into `totalDebitAmount`): [Statements and Transactions](./statements-and-transactions)
