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

# 交易概览

> 账户上每一笔资金变动的统一账本：该使用哪个查询、交易记录包含哪些内容，以及如何与你自己的系统对账。

Fluz 账户上每一笔资金变动都会产生一条交易记录：礼品卡购买、虚拟卡授权、存款、取款、内部转账、钱包间转账、账单支付以及返现。一个信息流、一种结构、一个查询。

记录是**账户级别**的。不存在用户级别的过滤：一次查询会返回你的令牌所限定账户上的所有内容。

***

## 我应该使用哪个查询？

| 你想要什么 | 使用 | 页面 |
| :- | :- | :- |
| 所有数据，可按任意方式过滤 | `getTransactions` | [获取所有交易](/features/get-all-transactions) |
| 仅被拒绝的授权 | `getDeclinedTransactions` | [获取被拒绝的交易](/features/get-decline-transactions) |
| 特定虚拟卡上的活动 | `getVirtualCardTransactions` | [获取虚拟卡交易](/features/get-virtual-card-transactions) |
| 以购买形式呈现的礼品卡订单 | `getUserPurchases` | [获取礼品卡购买记录](/features/get-gift-card-purchases) |
| 以资产形式呈现的礼品卡及其剩余价值 | `getGiftCards` | [查看礼品卡](/view-gift-card) |

<Note>
  **拒绝不是一种交易状态。** `status` 只会是 `PENDING` 或 `SETTLED`：被拒绝的授权永远不会变成已结算的交易，因此它根本不会出现在 `getTransactions` 中。如果你要排查“扣款没有成功”的问题，应该使用 `getDeclinedTransactions` 和[拒绝代码](/features/decline-codes)，而不是这个信息流。
</Note>

***

<Warning>
  **字段命名并不统一，你必须精确匹配。**

  `Transaction` 类型上的大多数字段使用 snake\_case：`record_id`、`transaction_type`、`created_at`、`cash_balance_available_balance`。但较新添加的字段使用 camelCase：`memo`、`transactionCategory`、`attachmentUrl`、`connectedAppId`、`connectedAppName`、`expectedClearedDate`。

  记录周围的一切都是 camelCase：过滤输入（`createdGte`、`amountGte`、`virtualCardProgram`）以及连接字段（`totalCount`、`hasNextPage`）。

  在编写查询之前先内省 schema，而不要假设某种约定。→ [GraphQL API 的工作原理](/concepts/graphql)
</Warning>

***

## 记录包含哪些内容

大约五十个字段，分为六组。只请求你需要的字段：如果请求全部字段，响应会非常庞大。

<AccordionGroup>
  <Accordion title="身份与路由">
    `record_id`、`account_id`、`user_id`、`user`、`transaction_type`、`channel`（`WEB`、`MOBILE`、`API`）、`connectedAppId` 和 `connectedAppName`：由你的哪个应用发起。
  </Accordion>

  <Accordion title="金额相关">
    `amount`、`fee`、`cashback`、`cashback_rate`、`bonus_cashback_rate`，再加上两个值得了解的方向性字段：

    * `external_funding_source_activity`：外部资金来源（银行卡和账户）的变动
    * `fluz_balance_activity`：Fluz 内部余额的变动

    这两个字段合在一起可以告诉你资金是流入了 Fluz、流出了 Fluz，还是仅在内部流转。
  </Accordion>

  <Accordion title="余额快照">
    参见[下文](#balance-snapshots)：每条记录都携带每种余额的事后状态。
  </Accordion>

  <Accordion title="上下文信息">
    `source` 和 `destination` 为展示字符串（如 "Visa \*\*\*\*1234"、"Amazon"）、`description`、`merchant_id`、`logo_url`、`card_last_four`、`card_display_name`、`virtual_card_program`、`source_type`。

    外币交易还会附加 `original_currency_amount`、`original_currency_code` 和 `conversion_rate`。
  </Accordion>

  <Accordion title="你添加的注释">
    `memo`、`transactionCategory`、`attachmentUrl`：参见[添加注释](#annotating-transactions)。
  </Accordion>

  <Accordion title="关联字段">
    `reference_id`、`transfer_id`、`liability_id`、`used_user_cash_balance_id`、`descriptor_id`：用于对账的字段。参见[对账](#reconciling-against-your-own-system)。
  </Accordion>
</AccordionGroup>

### 余额快照

每笔交易都携带该交易应用**之后**每一种余额类型的余额。这使得该信息流成为一个可重放的账本：你无需单独的余额历史 API，就能重建账户在其历史上任意时间点的状态。

| 字段前缀 | 余额类型 | 产品名称 |
| :- | :- | :- |
| `cash_balance_*` | 现金 | 现金余额 |
| `seat_balance_*` | 奖励 | 奖励余额 |
| `gift_card_prepayment_balance_*` | 预付款 | 预付款余额 |
| `reserve_balance_*` | 储备金 | 储备金余额 |
| `other_cash_balance_*` | 其他现金 | — |

<Note>
  `seat_balance_*` 是**奖励**余额。这个命名是历史遗留的，不要去寻找一个单独的“seat”概念。
</Note>

每种余额都有 `_available_balance` 和 `_total_balance` 两个版本。成对出现的 `is_*_affected` 布尔字段（`is_cash_balance_affected`、`is_seat_balance_affected`、`is_gift_card_balance_affected`、`is_reserve_balance_affected`）会告诉你这笔交易实际影响了哪些余额，比对快照做差值判断的成本更低。

→ 参见[钱包概览](/features/move-funds-with-external-accounts)了解每种余额分别是什么。

***

## 过滤

`getTransactions` 接受一个功能丰富的 `TransactionFilterInput`。各字段族如下：

| 字段族 | 字段 |
| :- | :- |
| **记录与状态** | `recordId`、`status` |
| **金额** | `amount`、`amountGte`、`amountLte`，以及 `finalAmount` 对应的同样三个字段 |
| **返现** | `cashbackAmount`、`cashbackPercentage`，分别带有 `Gte`/`Lte` |
| **手续费** | `feeAmount`、`feeAmountGte`、`feeAmountLte` |
| **日期** | `createdGte`、`createdLte`、`updatedGte`、`updatedLte`（ISO 8601，UTC） |
| **商户** | `merchantId`、`merchant` |
| **属性** | `transactionType`、`channel`、`category` |
| **虚拟卡** | `virtualCard`、`virtualCardProgram` |
| **其他** | `fundingSource`、`userCashBalanceId`、`referenceId`、`liabilityId` |

`amount` 是基础金额；`finalAmount` 是金额加上手续费，即实际扣款总额。在核对资金来源被扣了多少款项时，应按 `finalAmount` 过滤。

<Warning>
  **在依赖 `transactionType` 之前，请先确认其可接受的取值。** 参考页面在一处列出了人类可读的字符串（`Add Money`、`Gift Card Purchase`、`Transfer - Out`），又在示例和示例响应中使用了枚举风格的常量（`GIFT_CARD_PURCHASE`、`DEPOSIT`）。两者不可互换。请先查询一小页未过滤的数据，查看你的账户实际返回的 `transaction_type` 取值。
</Warning>

### 分页与吞吐量

`limit` **最大为 20**，`offset` 用于向前翻页。请检查 `hasNextPage`，而不要根据短页面去推断；`totalCount` 会给出过滤后结果集的完整大小。

GraphQL API 对每个 IP 和每个访问令牌都限制为每秒 20 个请求，且响应中不带任何速率限制相关的响应头。参见[速率限制](/concepts/rate-limits)。

<Note>
  **在构建同步任务之前先算一下账。** 每次查询 20 条记录、每秒 20 个请求，上限是**每秒 400 笔交易**，而一次只发一个请求的实际吞吐量会远低于这个数字。一个累计有 50 万笔交易的账户，需要 25,000 次请求才能完整遍历一遍。

  应按增量同步来设计：用 `createdGte`/`updatedGte` 结合你上一次成功同步的水位线来限定每个任务的范围，绝不要重新遍历你已经拥有的历史数据。
</Note>

***

## 为交易添加注释

你可以为任意交易附加一段自由文本 `memo`（最多 255 个字符）、一个 `transactionCategory` 和一个文件：既可以在存款、购买和转账发生时附加，也可以之后通过 `updateTransactionMetadata` 补充。分类会在首次使用时创建，之后再次使用相同名称时会被复用。

<Warning>
  **`attachmentUrl` 是一个会过期的签名 URL，切勿存储它。** 需要用到文件时，请重新获取该笔交易。

  这也会破坏简单的缓存方案。已结算的交易看起来是不可变的，但 `memo`、`transactionCategory` 和 `attachmentUrl` 在结算之后仍然是可变的：因此被缓存的 `SETTLED` 记录会返回过期的注释和失效的附件链接。你可以缓存财务字段，但注释部分需要重新获取。
</Warning>

→ [添加费用详情](/features/add-expense-details)

***

## 与你自己的系统对账

有五个字段用于关联：

| 字段 | 关联对象 |
| :- | :- |
| `reference_id` | 购买展示 ID：一个简短的、人类可读的 Fluz 交易 ID（例如 `1047283`），同样会出现在礼品卡记录和导出文件中，也是 Fluz 支持团队引用的编号 |
| `transfer_id` | 生成该记录的转账，用于钱包间资金转移 |
| `used_user_cash_balance_id` | 资金来自哪个消费账户，对按预算生成报表至关重要 |
| `liability_id` | 该记录所结算的账单支付 |
| `connectedAppId` | 当多个应用共享同一账户时，标识由哪个应用发起 |

一种可行的模式：

1. **在创建订单时，将 `record_id` 和 `reference_id` 存储**到你自己的订单记录上。不要试图之后再靠金额和时间戳去匹配。
2. **按 `updatedGte` 做增量同步**，而不是 `createdGte`：一笔 `PENDING` 交易之后结算时会更新 `updated_at`，按创建日期同步会漏掉这次状态变化。
3. **预期会有结算延迟。** ACH 取款会保持 `PENDING` 状态 1 到 3 个工作日；卡授权则按各自的时间线结算。`expectedClearedDate` 会告诉你什么时候该再来查看。
4. **用快照来核对余额**，而不是靠累加金额。`*_available_balance` 字段是权威数据，已经把手续费、返现和待处理的预留都计算在内。

<Note>
  `externalReferenceId` **不会**出现在交易记录上。如果你需要在一笔资金变动上带上自己的用户 ID，请通过账户进行关联，或者在交易发生时把它写进 `memo`。→ [管理外部引用 ID](/managing-external-reference-ids)
</Note>

***

## 权限范围

`getTransactions` **同时**需要 `LIST_PAYMENT` **和** `LIST_PURCHASES`。缺少任意一个都会返回 `FORBIDDEN` 错误，并在其中指出所需的权限范围。

开始开发前，请在你应用的 Permissions（权限）标签页中启用这两项权限：请求了但未启用的权限范围会被静默丢弃，而不是报错拒绝。→ [配置 OAuth 应用](/configure-o-auth-app)

***

## 下一步

<CardGroup cols={2}>
  <Card title="获取所有交易" icon="list" href="/features/get-all-transactions">
    完整的过滤、字段与分页参考。
  </Card>

  <Card title="被拒绝的交易" icon="circle-x" href="/features/get-decline-transactions">
    从未变成交易的授权请求。
  </Card>

  <Card title="拒绝代码" icon="triangle-alert" href="/features/decline-codes">
    每种拒绝原因分别代表什么。
  </Card>

  <Card title="虚拟卡交易" icon="credit-card" href="/features/get-virtual-card-transactions">
    限定在一张或多张卡上的交易。
  </Card>

  <Card title="礼品卡购买" icon="gift" href="/features/get-gift-card-purchases">
    订单，而非账本条目。
  </Card>

  <Card title="添加费用详情" icon="paperclip" href="/features/add-expense-details">
    备注、分类与附件。
  </Card>
</CardGroup>
