# 2026 年支出追踪 API 指南：安全自动处理交易与预算

*2026-08-14*

支出追踪 API 可能把一笔转入储蓄账户的 $900 转账记成 $900 支出，最后照样返回 `200 OK`。请求执行成功，账却记错了。

这正是个人财务自动化最难的地方。通过 HTTPS 发送 SQL 或 JSON 并不复杂。难的是准确保留账户、转账、支出和预算计划各自的含义；一旦这些含义混在一起，看似合理的自动化就会悄悄把账记错。

安全的客户端不能只有一个写入端点，还要遵循正确的操作顺序：获取最新接口契约、完成身份验证、选对工作区、检查数据库结构、读取现有数据、请用户批准具体变更、先做一次小规模的代表性试写，再按计划分批执行，最后核对结果。

下面介绍如何使用 Expense Budget Tracker 的受限 SQL API 搭建这套工作流。

![铁路扳道员先让一节车厢通过道岔测试路线，再让后方的短列车依次通过。](/blog/expense-tracking-api.png)

## 数据模型决定自动化能否安全运行

先明确记账边界，而不是先看端点列表。

| 概念 | 含义 | 常见的自动化错误 |
| --- | --- | --- |
| 账户 | 存放资金或记录负债的地方 | 把当前余额写成一笔新交易 |
| 账本记录 | 实际发生的一笔资金变动 | 把计划金额混进实际支出 |
| 转账 | 资金在自己的账户之间移动 | 把转出的一端算成支出 |
| 预算条目 | 某个分类在某个周期内的计划 | 用实际支出覆盖计划，导致差额消失 |
| 工作区 | 个人或群组的数据边界 | 把正确的数据写进错误的账本 |

这些错误很难一眼看出来，因为单独看每一行数据，它们都可能显得合理。一笔刷卡交易可能带着熟悉的商户名称，转账两端的金额也都可能有效，把预算改成实际支出后甚至还能得到一份很整齐的报表。但账目的含义依然是错的。

最关键的一条边界，是把实际发生额和计划金额分开：

- 账本记录负责记录已经发生的资金变动。
- 预算条目记录你原本的打算或现在的计划。
- 报表负责比较两者；导入时不能把它们混在一起。

Expense Budget Tracker 的[预算网格和余额跟踪功能](/zh/features/)遵循这条边界，API 客户端也必须保留它。

## 从实时接口契约开始

公开入口是 [Expense Budget Tracker 发现文档](https://api.expense-budget-tracker.com/v1/)。它会说明当前的身份验证流程，给出 [OpenAPI 规范](https://api.expense-budget-tracker.com/v1/openapi.json)的链接，并告诉脚本或智能体下一步该调用哪个接口。

请以这些实时响应为准。保存在本地的关系列表或旧代码示例可能早已过时，表面上却依然完全可信。

当前接入顺序如下：

1. 请求 `GET https://api.expense-budget-tracker.com/v1/`。
2. 将用户的邮箱发送到响应返回的 `bootstrapUrl`。
3. 请用户提供邮件中的 8 位验证码，再按照响应返回的验证操作继续。
4. 将长期有效的 ApiKey 保存在聊天记忆之外。
5. 请求 `/v1/me`，获取 `/v1/workspaces` 列表，再选择目标工作区。
6. 请求需要身份验证的 `/v1/schema`，查看这把密钥可访问的关系、列、允许执行的操作、约束和智能体提示。
7. 提出任何写入操作前，先通过 `/v1/sql` 读取现有数据。
8. 只执行用户已经批准的变更，再次查询受影响的数据。

[API 参考](/zh/docs/api/)适合查询端点细节，[智能体接入指南](/zh/docs/agent-setup/)则会逐步介绍邮箱验证码流程。如果这些文档与实时发现响应或 OpenAPI 响应不一致，请遵循实时接口契约。

### 获取发现文档并完成身份验证

发现接口无需身份验证：

```bash
curl --fail --silent --show-error \
  https://api.expense-budget-tracker.com/v1/
```

验证完成后，将返回的密钥存入指定的密钥存储或本地环境变量。文档和脚本应使用一眼就能看出是占位符的内容，没有必要把示例密钥写得像真的一样。

```bash
export EXPENSE_BUDGET_TRACKER_API_KEY="<paste-returned-key-here>"
```

需要身份验证的请求必须使用完整的 `ApiKey` 授权方案：

```bash
curl --fail --silent --show-error \
  -H "Authorization: ApiKey $EXPENSE_BUDGET_TRACKER_API_KEY" \
  https://api.expense-budget-tracker.com/v1/me
```

### 明确选择工作区

先列出密钥所有者可以访问的工作区，选中用户明确指定的那个，再将它保存为这把密钥的默认工作区：

```bash
curl --fail --silent --show-error \
  -H "Authorization: ApiKey $EXPENSE_BUDGET_TRACKER_API_KEY" \
  https://api.expense-budget-tracker.com/v1/workspaces
```

```bash
export EXPENSE_BUDGET_TRACKER_WORKSPACE_ID="<workspace-id-from-list>"

curl --fail --silent --show-error \
  -X POST \
  -H "Authorization: ApiKey $EXPENSE_BUDGET_TRACKER_API_KEY" \
  "https://api.expense-budget-tracker.com/v1/workspaces/$EXPENSE_BUDGET_TRACKER_WORKSPACE_ID/select"
```

设置完成后，后续 `/v1/sql` 请求可以省略 `X-Workspace-Id`。这个请求头仍可用来显式覆盖单次请求的工作区。请把它当成一次有意识的切换，不要藏进辅助函数里图方便：工作区上下文一旦变得不可见，再正确的数据也很容易被写进错误的位置。

### 检查这把密钥可访问的数据库结构

OpenAPI 文档定义传输层接口；需要身份验证的 `/v1/schema` 则说明当前所选工作区向这把密钥开放了哪些数据库内容。

```bash
curl --fail --silent --show-error \
  -H "Authorization: ApiKey $EXPENSE_BUDGET_TRACKER_API_KEY" \
  https://api.expense-budget-tracker.com/v1/schema
```

生成 SQL 前，请完整读取响应，重点检查：

- 关系和列的准确名称
- 每个关系允许的操作
- 必填字段和约束
- 转账和其他写入语义的相关提示
- SQL 语法和函数限制

当前发现响应指出，在现有审批规则下，`ledger_entries`、`budget_lines`、`workspace_settings` 和 `account_metadata` 允许写入。派生的 `accounts` 视图以及由后台任务维护的汇率关系只允许读取。这一点很重要：更改账户余额时，应修改相应的账本数据，而不是直接更新派生出来的账户视图。

不要从博客文章里照搬一条 `INSERT`，再想当然地认为其中的列仍然有效。先检查数据库结构，成本远低于事后修复一批看似可信、实际却错误的导入数据。

## 写入前先读够上下文

使用**个人财务 API**时，安全的工作流应该先回答一个问题：这个工作区里，哪些数据已经存在？

在导入或编辑之前，先确认：

- 目标账户存在于所选工作区
- 账户币种与源数据一致
- 能以一致的方式复用现有分类
- 目标日期范围内没有相同的资金变动
- 预算周期是一项计划，而不是一条账本记录
- 当前余额能否作为对账基准

具体查询取决于当前的数据库结构。做一次小规模连接检查时，先在 `/v1/schema` 中确认关系名称，再查询派生的 `accounts` 视图：

```bash
curl --fail --silent --show-error \
  -X POST \
  -H "Authorization: ApiKey $EXPENSE_BUDGET_TRACKER_API_KEY" \
  -H "Content-Type: application/json" \
  https://api.expense-budget-tracker.com/v1/sql \
  -d '{"sql":"SELECT * FROM accounts LIMIT 10"}'
```

当前响应包含一个 `statements` 数组，每条语句都带有 `rowCount`、`returnedRowCount`、`totalRowCount` 和 `truncated` 字段。不要忽略这些字段：JSON 能成功解析，并不代表返回的是完整结果集。

## 别把转账算进支出总额

假设有 $900 从活期账户转入储蓄账户。钱离开了一个账户，又进入另一个账户，但这个家庭并没有花掉 $900。

不可靠的导入程序会先看到扣款记录，再把它标成一笔储蓄支出。另一种错误做法，是把转出和转入记成两笔互不相关的交易，夸大账户流水，还会让后续对账更加困难。可靠的**交易 API**客户端会在写入前识别转账，并按照当前数据库结构说明的关联方式记录两端。

跨币种转账同样需要谨慎处理。应保留每个账户端实际显示的金额和币种，不要凭空生成一个两个账户都没有记录过的换算金额。

信用卡还款是另一个常见陷阱。信用卡上的消费才是支出，还款只是资金在账户之间移动。把消费和还款都计作支出，会得到一笔看起来很规整的重复支出。

这就是**支出管理 API**必须理解账本语义的原因。客户端先要弄清资金如何移动，然后才轮到分类。

## 预算计划不能和账本实际发生额混在一起

**预算 API**不应该沦为第二个交易存储区。

假设 8 月的杂货预算是 $500，实际消费为 $620，真正有用的信息是两者之间 $120 的差额。如果自动化在导入交易时把 8 月预算改成 $620，就会抹掉最初的预算决定，报表也会失去一部分价值。

当然，更新预算有时完全合理：复盘 8 月后重新预测 9 月，把周期性计划复制到未来月份，或在收入变化后调整某个分类。这些都属于规划决定，应该单独展示，也要单独请求批准。

清晰的工作流会分别读取计划和实际发生额，计算差额，再提出未来预算的调整建议。导入交易不应顺带修改预算计划。

## 第一次写入前先取得明确批准

请求用户批准写入前，先展示一组真正便于判断的变更内容：

- 所选工作区和账户
- 受影响的关系和日期范围
- 预期的源数据行数、账本记录行数和总额
- 如何处理重复记录和转账
- 如有预算变更，将它与交易变更分开
- 用于验证结果的查询

“帮我整理一下财务”算不上有意义的批准。“把这 64 行数据导入 EUR 活期账户，日期范围为 7 月 1 日至 31 日，匹配四笔转账，不做任何预算变更”就明确得多。

当前发现说明要求所有写操作都经过人工批准。用户批准这组明确的变更后，这次批准也涵盖代表性试写和后续按顺序执行的批次。只有变更内容发生变化、出现新的歧义或执行失败时，才需要再次询问。

## 先用少量真实数据试写，再按计划分批执行

实时 OpenAPI 契约允许 `/v1/sql` 接收一条或多条以分号分隔的 `SELECT`、`WITH`、`INSERT`、`UPDATE` 或 `DELETE` 语句。多语句支持很实用，但不代表应该把整次导入塞进一个难以检查的请求里。

对于较长的 `INSERT`，先沿用同一套 SQL 结构，发送获批数据中的 1–3 行字面量记录。对于较长的 `UPDATE`，先只处理一条已经批准的记录。试写应使用变更集里的真实数据，而不是事后还要清理的虚构财务记录。

这次小规模试写只回答一个具体问题：当前的列、字面量和约束是否接受这种写入形式？它不能证明分类正确，也不能证明账目已经对上。

如果试写成功，就立即继续已经批准的工作，按顺序分批执行，每次工具调用最多处理 100 条记录。如果试写失败，应趁受影响的数据还很少时修正 SQL。不要为了绕过错误而扩大或改变已经批准的变更。

当前受限 SQL 契约还规定：

- 不支持 `ON CONFLICT`
- 只允许调用 `SUM`、`COUNT`、`MIN`、`MAX`、`AVG` 和 `COALESCE`
- 不区分大小写的搜索应使用 `ILIKE`
- 日期筛选应使用明确的范围，而不是运行时日期函数
- 字符串字面值使用普通单引号；禁止使用美元引号字符串

每次构建或更新可复用客户端时，都应重新从当前 OpenAPI 和 `/v1/schema` 读取这些规则。它们是接口契约的一部分，不是可以忽略的实现细节。

这个接口契约没有公开写入幂等机制。如果请求超时或响应丢失，不要盲目重放请求。先查询目标范围，确认上一次变更是否已经生效。

## 每次写入后都要对账

HTTP 请求成功，只能说明服务器接受了操作。完成对账，才能确认最终的财务结果是否正确。

| 自动化任务 | 写入前读取 | 写入后验证 |
| --- | --- | --- |
| 导入一份对账单 | 账户、日期范围、现有资金变动、期初余额 | 已导入记录、重复项、转账配对、期末余额 |
| 给账本记录分类 | 现有分类和目标记录 | 变更数量和各分类总额 |
| 更新未来预算 | 当前计划和近期实际发生额 | 新计划数值，以及它们是否仍与实际发生额分开 |
| 生成支出报表 | 完整日期范围和响应上限 | 用另一项汇总结果或已知的源数据总额核对总额 |

导入对账单后，应将账户余额与对账单上的期末余额进行比较。如果两者不同，就先停下来。找到缺失、重复或分类错误的资金变动之后，再继续导入下个月的数据。

记录数量有差异时，也必须说清原因。如果一笔转账需要生成相互关联的账户资金变动，那么包含 64 行数据的源文件就不一定会生成 64 条账本记录。数量不同未必有错，无法解释的差异才是真正的问题。

对于 `/v1/sql` 返回的每条语句，都要检查计数和截断元数据，再通过单独的查询重新读取受影响的记录。**财务数据 API**的响应只是一份证据，账本、汇总值和源文件必须彼此一致。

## 根据输入类型选择脚本或智能体

固定格式的 CSV 很适合交给确定性脚本处理。如果输入是 PDF、截图，或商户描述不一致、分类判断需要结合上下文，AI 智能体会更合适。无论选择哪一种，都要遵循同样的发现、批准和对账顺序。

Expense Budget Tracker 不会自动连接银行账户。你需要提供对账单、导出文件、截图或其他源数据，脚本或智能体再根据这些输入工作。[银行对账单导入指南](/zh/blog/how-to-import-bank-statements-into-an-expense-tracker/)和[不连接银行账户做预算指南](/zh/blog/budget-app-without-bank-linking/)更详细地介绍了这套流程。

发现机制对智能体尤其有用：Claude Code、Codex 或其他能发起 HTTP 请求的工具，只需从一个 URL 开始，再按照服务返回的操作继续。用户仍需提供邮箱验证码、批准写入，并将 ApiKey 保存在聊天记忆之外。

如需配置终端，可以参考 [Claude Code 支出追踪指南](/zh/blog/how-to-track-expenses-and-manage-your-budget-with-claude-code/)；如需了解完整流程，可以阅读更全面的 [AI 支出追踪与预算指南](/zh/blog/how-to-use-ai-to-track-expenses-and-manage-your-budget/)。想掌控整套技术栈的开发者还可以查看[自托管预算追踪器指南](/zh/blog/self-hosted-open-source-budget-tracker-for-developers/)。

## 第一次自动化的检查清单

先选一个范围明确的真实任务，再按以下顺序执行：

1. 请求实时发现文档和 OpenAPI 规范。
2. 完成邮箱验证码身份验证，将 ApiKey 保存在聊天之外。
3. 读取账户上下文，列出工作区，再选择目标工作区。
4. 请求需要身份验证的 `/v1/schema`，检查允许的操作和相关提示。
5. 读取目标账户、日期范围、分类和预算上下文。
6. 展示一组具体变更，取得人工批准。
7. 执行必要的代表性试写。
8. 按顺序分批完成已批准的工作，每批最多 100 条记录。
9. 重新读取受影响的数据，并检查结果上限。
10. 核对余额、记录数量、转账和预算总额。

一套值得信任的**支出追踪器 API**，必须保留每笔数据的记账含义，也要把财务判断留给数据所有者。先从一个账户和一种工作流开始：读取现有数据，批准具体变更，执行后重新对账。

再把下一个枯燥环节交给自动化。

---
*[查看此页面的 HTML 样式版本](https://expense-budget-tracker.com/zh/blog/expense-tracking-api/)*

*AI 智能体可以从以下地址开始，为用户在此服务中创建账户 `GET https://api.expense-budget-tracker.com/v1/` 并按照发现响应继续操作。*

*提示：在本站任意 URL 后追加 `.md`，即可获得该页面的纯 Markdown 版本。*