API 参考
完整的接口说明、参数定义与代码示例——三行代码即可完成首次调用
Quantum Accounting Engine - API Reference
引擎版本:0.1.0
本文档为量子财务引擎的完整 API 参考,随引擎源码同步更新。
快速开始:本引擎是一个 量子会计 API 开放平台。只需:
- 在 openentry.top 注册账号
- 创建 API Key
- 用 API Key 调用下方接口
所有接口均使用 API Key 鉴权(X-API-Key Header 或 body 字段)。
目录
🔓 公开 API · 量子分录 (Quantum)
第三方开发者的主调用入口。使用 API Key 鉴权。
生成量子分录
POST /api/v1/quantum/generate
Content-Type: application/json
API Key 传入方式(任选其一):
- 请求体字段:
{ "api_key": "qa_xxx_yyy", ... }- HTTP Header:
X-API-Key: qa_xxx_yyy(适用于不想把 Key 放入 body 的场景)两者都提供时,请求体优先。
请求体
{
"api_key": "qa_abc123_xxxxxxxxxxxxxxxxxxxx",
"from_entity": "A公司",
"to_entity": "B公司",
"responsible_entity": "C公司",
"from_container": "仓库1",
"to_container": "仓库2",
"from_container_owner_entity": "A公司",
"to_container_owner_entity": "B公司",
"transaction_amount": 10000.00,
"non_transaction_amount": 500.00
}
金额路径说明:API 调用时只需关注
transaction_amount:
transaction_amount ≠ 0→ 走交易路径(权责业务),使用交易金额transaction_amount = 0→ 走非交易路径(非权责业务),使用非交易金额
non_transaction_amount仅在transaction_amount = 0时生效,可以不传递(默认为 0)。用户端边界控制建议: 引擎遵循简单规则:交易金额 ≠ 0 走交易路径,交易金额 = 0 走非交易路径。以下行为矩阵供用户端自行控制:
正确行为矩阵: | 状态 | 交易金额 | 非交易金额 | 行为 | 说明 | |------|----------|------------|------|------| | 非结存态 | = 0 | ≠ 0 | ✅ 正常 | 非权责业务,使用非交易金额 | | 非结存态 | ≠ 0 | = 0 | ✅ 正常 | 权责业务,使用交易金额 | | 结存态 | = 0 | = 0 | ✅ 正常 | 结存态调拨,后续成本核算填充 | | 结存态 | = 0 | ≠ 0 | ✅ 正常 | 结存态非权责业务 | | 结存态 | ≠ 0 | = 0 | ✅ 正常 | 结存态权责业务 | | 结存态 | ≠ 0 | ≠ 0 | ✅ 正常 | 结存态权责+非权责业务 |
用户端应避免的错误场景: | 状态 | 交易金额 | 非交易金额 | 错误原因 | |------|----------|------------|----------| | 非结存态 | = 0 | = 0 | ❌ 无业务意义,生成0值凭证无价值 | | 非结存态 | ≠ 0 | ≠ 0 | ❌ 非结存态下两者不能同时非0,引擎会忽略非交易金额 |
建议用户端在调用前进行校验:
- 非结存态:确保
transaction_amount和non_transaction_amount二选一(不能同时为0,不能同时非0)- 同一主体内部业务:确保
transaction_amount = 0- 结存态:金额任意,后置成本核算填充
隐私保护架构(推荐开发者使用):为保护用户数据隐私,建议开发者设计如下架构:
用户输入(真实数据)→ 系统生成临时映射表 → 转换为占位符调用引擎 → 引擎返回占位符凭证 → 逆向映射还原真实凭证实现流程:
- 用户输入真实数据:
from_entity: "A公司", to_entity: "B公司", transaction_amount: 10000- 系统生成临时映射表(HashMap,内存中,不持久化):
- 主体/容器:相同真实值 → 相同占位符(如 "A公司" → "A")
- 金额:根据业务类型转换为 1 或 0(不传真实金额)
- 转换为占位符调用引擎:
from_entity: "A", to_entity: "B", transaction_amount: 1- 引擎返回占位符凭证
- 系统逆向映射还原真实凭证返回给用户
占位符建议: | 字段 | 占位符 | 映射示例 | |------|--------|----------| | 转出主体 |
A| "A公司" →A| | 转入主体 |B| "B公司" →B| | 权责主体 |R| "C公司" →R| | 转出容器 |仓库A| "仓库1" →仓库A| | 转入容器 |仓库B| "仓库2" →仓库B| | 容器归属主体 |归属A/归属B| 与主体相同则用相同占位符 |金额占位符: | transaction_amount | 含义 | 说明 | |-------------------|------|------| |
1| 权责业务 | 走交易路径 | |0| 非权责业务 | 走非交易路径 |金额精度与核算责任说明: 本引擎对
transaction_amount/non_transaction_amount仅做"是否为 0 / 正负"的分类判断与透传,不做任何加减乘除或累计运算(无借贷求和、无分摊、无四舍五入)。因此即便字段类型为f64也不存在会计精度风险——占位符0/1为小整数,f64可精确表示,== 0判定可靠;且引擎已对接近 0 的浮点脏值做了归一化兜底(< 1e-9视作 0,详见entry_generator::normalize_amount)。真实金额的核算、对账与持久化精度由quantum-accounting-erp侧负责(该侧应使用定点十进制,如NUMERIC/Decimal),不在本引擎职责范围内。红冲(reversal)字段: 红冲一笔业务请使用显式布尔字段
reversal: true,不要依赖负金额——占位符约定下金额只传 0/1,负数(-0无效、-1会被当作交易业务导致凭证形状错误)。reversal是与金额解耦的纯信号,因此transaction_amount = 0(非交易业务、结存态双 0 调拨)也能正确红冲:引擎生成与原业务同形的凭证组后统一翻转借贷方向。输出 amount 的符号约定:返回的每条
QuantumEntry.amount的符号编码借贷方向——Debit(借)为正、Credit(贷)为负;reversal通过翻转debit_credit使amount被动反号,二者始终一致(等价)。ERP 侧填充真实金额时,应以debit_credit方向(或等价的amount符号)为依据,用真实金额的绝对值按该方向填入,不要对占位符±1与真实金额符号做叠加。amount_type 区分金额来源:
transaction→ 对应transaction_amount,non_transaction→ 对应non_transaction_amount特点:
- 临时映射表仅在单次请求生命周期内存在,请求结束即销毁
- 相同真实值自动映射到相同占位符,保证引擎相等性判定正确
- 用户全程只接触真实数据,零感知占位符
- 映射开销 < 0.01ms,不影响效率
结存态调拨业务(
transaction_amount = 0且non_transaction_amount = 0)返回的 0 值凭证,后续通过成本核算系统填充真实金额。
响应
{
"success": true,
"request_id": "uuid",
"data": {
"entries": [
{
"entry_type": "b2_monetary_outflow",
"quantum_state": "monetary_state",
"amount_type": "transaction",
"balance_direction": "debit",
"debit_credit": "credit",
"amount": -10000.00,
"owner_entity": "A公司",
"container": "仓库1",
"counterparty_entity": "B公司",
"responsible_entity": null,
"cash_flow_id": 0,
"rule_id": "B2.M.OUT",
"is_basic": true
}
],
"from_state": "monetary_state",
"to_state": "monetary_state"
},
"error": null,
"quota": {
"used": 28,
"limit": 100,
"remaining": 72
}
}
配额字段
quota:每次成功调用后会扣减本 Key 的当日配额,返回最新used / limit / remaining。若超过limit,接口返回 HTTP 403 且error.code = "QUOTA_EXCEEDED"(请求不计入配额)。
错误响应
{
"success": false,
"request_id": "uuid",
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "from_entity 不能为空"
}
}
批量生成量子分录
POST /api/v1/quantum/generate-batch
Content-Type: application/json
认证:与单生成相同,使用 API Key 鉴权(body 传入或
X-API-KeyHeader)。配额注意:批量接口会按
facts数量扣减日配额(每个 fact 计 1 单位),与单条generate口径一致;配额不足时整体返回 HTTP 403 且不计入任何配额。详见下文「限流与配置」。
请求体
{
"api_key": "qa_abc123_xxxxxxxxxxxxxxxxxxxx",
"facts": [
{
"from_entity": "A公司",
"to_entity": "B公司",
"transaction_amount": 10000.00
},
{
"from_entity": "C公司",
"to_entity": "D公司",
"transaction_amount": 20000.00
}
]
}
响应
{
"success": true,
"total_count": 2,
"success_count": 2,
"failed_count": 0,
"results": [...]
}
Legacy 路径(向后兼容)
为兼容旧版集成,以下路径已废弃但仍可用,新代码请使用上面的 /api/v1/quantum/* 路径:
| Legacy 路径 | 推荐路径 |
|------------|---------|
| POST /api/v1/generate | POST /api/v1/quantum/generate |
| POST /api/v1/generate-batch | POST /api/v1/quantum/generate-batch |
| POST /api/v1/verify-key | POST /api/v1/quantum/verify-key |
验证密钥
POST /api/v1/quantum/verify-key
Content-Type: application/json
请求体
{
"api_key": "qa_abc123_xxxxxxxxxxxxxxxxxxxx"
}
响应
{
"success": true,
"valid": true,
"user_id": "uuid",
"plan": "free",
"quota": {
"used": 27,
"limit": 100,
"remaining": 73
}
}
🔓 公开 API · 用量统计 (Usage)
第三方开发者查询本 API Key 的用量消耗。
获取指定 API Key 的当日用量
GET /api/v1/usage/daily
X-API-Key: qa_abc123_xxxxxxxxxxxxxxxxxxxx
别名:与
GET /api/v1/usage完全等效。
响应
{
"success": true,
"error": null,
"quota": {
"used": 27,
"limit": 100,
"remaining": 73,
"period": "daily"
}
}
响应字段说明:
| 字段 | 类型 | 说明 |
|------|------|------|
| quota.used | Integer | 当日已消耗配额单位数(来自 api_keys.daily_quota_used);单条 generate 每次计 1 单位,批量 generate-batch 按 fact 数计费(每个 fact 计 1 单位) |
| quota.limit | Integer | 当日配额上限(来自 api_keys.daily_quota_limit) |
| quota.remaining | Integer | 剩余可用单位数(limit - used,下限 0) |
| quota.period | String | 周期标识,固定为 "daily" |
错误响应:
| HTTP | 场景 |
|------|------|
| 400 | 缺少 X-API-Key Header |
| 401 | API Key 无效 |
| 500 | 数据库错误 |
查询当前用户用量统计(需登录)
GET /api/v1/usage/stats
Cookie: session_token=<登录会话令牌>
该接口面向登录用户(控制台),使用
session_tokenCookie 鉴权,返回该用户下所有 API Key 的聚合调用统计。与上方基于
X-API-Key的当日配额查询(只看单个 Key 的配额字段daily_quota_used)不同,此处统计来自usage_logs调用记录(由generate/generate-batch计费成功后写入),反映历史累计调用次数与趋势。
响应
{
"stats": {
"totalCalls": 128,
"apiKeysCount": 3,
"currentPlan": "free",
"todayCalls": 12,
"weekCalls": 56,
"dailyTrend": [ { "date": "2026-07-26", "count": 12 } ],
"topEndpoints": [ { "endpoint": "/api/v1/quantum/generate", "count": 80 } ]
}
}
响应字段说明:
| 字段 | 类型 | 说明 |
|------|------|------|
| stats.totalCalls | Integer | 该用户历史累计调用次数(来自 usage_logs) |
| stats.apiKeysCount | Integer | 该用户拥有的 API Key 数量 |
| stats.currentPlan | String | 当前套餐(free / pro 等) |
| stats.todayCalls | Integer | 当日调用次数 |
| stats.weekCalls | Integer | 近 7 日调用次数 |
| stats.dailyTrend | Array | 按日聚合的调用趋势(用于图表) |
| stats.topEndpoints | Array | 按端点聚合的调用排行 |
错误响应:
| HTTP | 场景 |
|------|------|
| 401 | 未登录或 session_token 无效 / 缺失 |
| 500 | 数据库错误 |
错误码
所有业务接口(/api/v1/quantum/generate、/api/v1/quantum/generate-batch 等)现在都使用真实的 HTTP 状态码,而非统一返回 200 + success:false,便于网关、负载均衡器和监控按状态码统一拦截与统计。错误码与 HTTP 状态码的对应关系如下:
| 错误码 | HTTP 状态码 | 说明 |
|--------|-------------|------|
| MISSING_API_KEY | 400 Bad Request | 缺少 API 密钥(未传 X-API-Key 也未在 body 提供) |
| VALIDATION_ERROR | 400 Bad Request | 请求参数校验失败 |
| KEY_NOT_ACTIVATED | 403 Forbidden | API 密钥未激活 |
| KEY_EXPIRED | 403 Forbidden | API 密钥已过期 |
| KEY_NOT_FOUND | 403 Forbidden | API 密钥不存在 |
| INVALID_API_KEY | 403 Forbidden | API 密钥无效(批量接口) |
| QUOTA_EXCEEDED | 403 Forbidden | 当日配额用尽 |
| UNAUTHORIZED | 401 Unauthorized | 未登录或登录已过期(usage 统计类接口) |
| FORBIDDEN | 403 Forbidden | 无权限访问 |
| INTERNAL_ERROR | 500 Internal Server Error | 服务器内部错误(数据库异常等) |
| RATE_LIMITED | 429 Too Many Requests | 请求过于频繁(令牌桶限速) |
限流与配置
引擎提供两层防护:
- 日配额(daily quota):每个 API Key 每日总调用量上限(
api_keys.daily_quota_limit/daily_quota_used),超限返回QUOTA_EXCEEDED(HTTP 403)。 - 令牌桶(token bucket):按 API Key 维度的瞬时速率/突发限制,超限返回 HTTP 429
RATE_LIMITED,不扣除日配额。与日配额互补——日配额管"总量",令牌桶管"突发速率"。
批量接口也计日配额:/api/v1/quantum/generate-batch 按 facts 数量计日配额,每个 fact 计 1 个单位;配额不足时整体返回 HTTP 403 且不计入任何配额,保证调用方不会因部分失败而白白消耗配额。
令牌桶策略通过配置文件(config.toml)或环境变量调整:
| 配置项 | TOML 路径 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|---|
| 稳态速率 | [rate_limit].requests_per_second | RATE_LIMIT_RPS | 5 | 每 Key 每秒平均可请求数 |
| 突发容量 | [rate_limit].burst_capacity | RATE_LIMIT_BURST | 10 | 令牌桶容量(应 ≥ 稳态速率) |
配置加载顺序:优先读取 config.toml(可用 CONFIG_PATH 指定路径),文件缺失或解析失败时回退到环境变量 / 内置默认值。完整示例见仓库 config.example.toml。
多 worker 注意:在单个进程内,
RateLimiter由Arc包裹并在各 worker 间共享同一组令牌桶,因此全局允许速率就是配置的单桶速率(requests_per_second),并非workers × 单桶速率,进程内跨 worker 限速已是准确的,无需 Redis。只有在多进程部署(多副本 / 多 pod / 真正的多进程模式)时,每个进程才维护独立令牌桶,真实全局速率约为进程数 × 单桶速率,此时才需把状态后端改为共享存储(如 Redis)做精确跨进程限速。
四态体系
转移单定义
一笔资源转移由以下输入参数定义:
T = (from_entity, to_entity,
from_container?, to_container?,
from_container_owner?, to_container_owner?,
responsible_entity?,
transaction_amount?, non_transaction_amount?)
关键设计:用户只需提供业务事实(谁、给谁、什么容器、多少钱),引擎自动推导每条分录的资源形态和金额路径。quantum_state 和 amount_type 是引擎的输出,不是输入。
资源形态推导规则
资源形态(quantum_state)由容器及其归属主体、权责主体的存在性动态推导,对每条分录独立判定:
container ≠ ∅ ∧ owner ≠ ∅ ⇒ monetary_state(货币态)
container ≠ ∅ ∧ owner = ∅ ⇒ inventory_state(结存态)
container = ∅ ∧ resp ≠ ∅ ⇒ responsible_state(权责态)
container = ∅ ∧ resp = ∅ ⇒ quantum_state(量子态)
| 条件 | 推导形态 | 说明 | |------|----------|------| | 有容器 + 容器有归属主体 | 货币态 | 如银行账号,归属某主体("谁的钱") | | 有容器 + 容器无归属主体 | 结存态 | 如仓库,不归属特定主体("存了什么") | | 无容器 + 有权责主体 | 权责态 | 如合同签订,仅涉及权责关系 | | 无容器 + 无权责主体 | 量子态 | 如服务购销、收入、损益、在建工程、制造费用等 |
容器的两类归属:容器分为有归属主体和无归属主体两类。有归属主体的容器(如银行账号,归属 A 公司)判定为货币态;无归属主体的容器(如仓库)判定为结存态。这对应 API 中的
from_container_owner_entity/to_container_owner_entity字段——有值则货币态,无值则结存态。
金额路径判定规则
金额分为交易金额(transaction_amount)和非交易金额(non_transaction_amount),其本质是权责金额与非权责金额:
transaction_amount ≠ 0 ⇒ 权责路径(交易金额)
transaction_amount = 0 ⇒ 非权责路径(非交易金额)
二维判定矩阵
资源形态(由容器/权责主体决定)与金额路径(由交易金额是否为 0 决定)两个维度正交组合,决定引擎最终生成的分录组:
| 资源形态 \ 金额路径 | 权责路径 (tx≠0) | 非权责路径 (tx=0) | |----------------------|------------------|---------------------| | 货币态 | 付款(货币流出 + 权责消除) | 资金调拨(纯转移) | | 结存态 | 赊购入库(物资入库 + 应付) | 调拨入库(纯转移) | | 量子态 | 服务购销(服务 + 应收/应付) | — | | 权责态 | 合同签订(权责确认) | — |
一次转移 T 不是产生单一形态,而是产生一组分录 G(T) = {E₁, E₂, ..., Eₙ},每条分录的
quantum_state和amount_type由引擎独立推导,同一笔业务中多种形态可同时出现。
四态总览
| 状态 | 说明 | 典型场景 | |------|------|----------| | monetary_state | 货币态 | 收款、付款 | | inventory_state | 结存态 | 入库、出库 | | quantum_state | 量子态 | 服务购销、收入、损益、在建工程 | | responsible_state | 权责态 | 合同签订 |
量子分录字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| entry_type | String | 条目类型枚举,snake_case 格式,如 b2_monetary_outflow / d5_inventory_transition_debit |
| quantum_state | String | 量子态类型(引擎推导输出,非用户输入),取值:monetary_state / inventory_state / quantum_state / responsible_state。由容器归属和权责主体动态判定,详见四态体系 |
| amount_type | String | 金额类型(引擎推导输出,非用户输入),取值:transaction(权责金额) / non_transaction(非权责金额)。由 transaction_amount 是否为 0 判定 |
| balance_direction | String | 余额方向,取值:debit(余额在借方,资产/费用类) / credit(余额在贷方,负债/权益/收入类) |
| debit_credit | String | 借贷方向,取值:debit(借) / credit(贷) |
| amount | Number | 金额(符号编码借贷方向:借为正、贷为负) |
| owner_entity | String | 归属主体 |
| container | String/Null | 归属容器(结存态 / 货币态携带) |
| counterparty_entity | String | 对方主体 |
| responsible_entity | String/Null | 权责主体(权责态 / 转移方式必填) |
| cash_flow_id | Integer/Null | 现金流 ID,取值:0=流出 / 1=流入 / null=不适用 |
| rule_id | String | 规则编号,B/D 规则体系,如 B2.M.OUT(基本规则)/ D5.D(衍生规则) |
| is_basic | Boolean | 是否为基本规则(B 系列)。true=基本规则 B1-B3,false=衍生规则 D1-D6 |