法币付款 API 支持组织从 Infini USD 余额向第三方银行账户付款 USD。
所有接口使用以下前缀:
/v2/payouts
| 方法 | 接口 | 用途 |
|---|---|---|
POST | /v2/payouts/quotes | 校验银行资料并获取有时效性的付款报价 |
POST | /v2/payouts | 创建并立即开始执行法币付款 |
POST | /v2/payouts/status/batch | 按创建时间区间分页查询付款状态 |
GET | /v2/payouts/{payout_id} | 查询当前付款状态 |
第一期不提供收款人资源。银行收款资料随 Quote 一次性提交,并不可变地绑定到 quote_id;POST /v2/payouts 不能替换或修改这份收款资料。
创建 Quote 时,请选择需要准确固定的是收款金额,还是付款账户的总扣款金额。fee_paid_by 会改变 Infini 对两侧金额的计算方式,并非仅用于展示。第一期支持以下两种方式。
适用于收款人必须准确收到指定金额的场景,例如支付发票。
{
"amount": "1000.00",
"amount_mode": "receive",
"fee_paid_by": "PAYER"
}收款人准确收到 1000.00 USD。PAYER 表示手续费外扣,付款手续费会额外计入 Infini USD 余额的扣款金额。
receiving_amount为1000.00。sending_amount = receiving_amount + transfer_fee_amount + bank_fee_amount。transfer_fee_amount = sending_amount × fee_rate_decimal;Infini 会反算并增加sending_amount,确保扣除全部手续费后收款金额仍然准确。
例如,服务费率为 0.001、银行费为 50.00 USD 时,计算结果为 sending_amount=1051.05、transfer_fee_amount=1.05、receiving_amount=1000.00。
适用于付款总扣款不能超过固定预算的场景。
{
"amount": "1000.00",
"amount_mode": "send",
"fee_paid_by": "BENEFICIARY"
}Infini 准确扣除 1000.00 USD。BENEFICIARY 表示手续费内扣,付款手续费从该金额中扣除,因此收款人的到账金额会更少。
sending_amount为1000.00。receiving_amount = sending_amount - transfer_fee_amount - bank_fee_amount。transfer_fee_amount = sending_amount × fee_rate_decimal。
例如,服务费率为 0.001、银行费为 50.00 USD 时,计算结果为 sending_amount=1000.00、transfer_fee_amount=1.00、receiving_amount=949.00。
请仅使用以上字段组合。第一期不支持其他 amount_mode 与 fee_paid_by 组合。修改 fee_paid_by 后必须重新请求 Quote;quote_id 会固定 Payout 使用的手续费承担方和计算结果。
sending_amount:Infini USD 余额的实际总扣款金额。receiving_amount:发送到收款银行账户的金额。transfer_fee_amount:Infini 为处理该笔付款收取的服务费,不包含任何银行或通道费。bank_fee_amount:所选银行及付款通道对应的银行手续费,例如 SWIFT、ACH 或 Wire。billing.total_fee:所有手续费项目的合计,完整明细见billing。fee_rate_decimal:Quote 使用的手续费率;rate是汇率。
对账时,请使用 sending_amount 作为该笔付款的支出金额。
API 付款不会进入后台人工审批流。POST /v2/payouts 会执行具有最终效力的付款前校验,并立即开始执行。
银行付款是异步过程。创建成功并返回 status=processing,表示请求已经通过 Infini 校验且付款执行已经开始,不代表收款人的银行账户已经到账。
completed 表示付款已经成功完成。对端银行仍可能拒收并退回一笔已经完成的汇款。原付款继续保持 completed,独立补偿退款通过可选的 return 对象体现。
POST /v2/payouts/quotes 会校验收款资料,并执行初步的路由、金额、合规和限额检查。它返回一份包含收款资料、金额、汇率、费用和手续费承担方的有时效快照。一份 Quote:
- 不会冻结组织余额;
- 不会批准或创建付款;
- 过期后不能继续使用;
- 不保证当前限额、合规状态、余额或服务商可用性保持不变。
POST /v2/payouts 会在创建主付款单、扣减余额并开始银行执行前,重新执行所有关键校验。
client_reference_id 在商户范围内唯一标识一笔逻辑付款:
- 使用相同引用和完全相同的业务请求重试时,返回已有资源;
- 付款幂等重试时,响应中的
is_duplicate=true; - 使用相同引用提交不同业务数据时,返回
409 idempotency_conflict。
quote_id 和其他决定付款内容的字段都会参与幂等一致性比较。
同一组织同一时间只允许一笔 POST /v2/payouts 请求进入执行流程。如果已有付款请求正在提交,API 会在消费 Quote、创建付款单和扣减组织余额之前拒绝并发请求:
{
"code": 108015,
"message": "Another payout submission is in progress. Please retry shortly.",
"data": {
"error": "payout_submission_in_progress",
"field": null,
"retryable": true
}
}请在短暂的随机退避后重试。同一笔逻辑付款应继续使用原来的 client_reference_id,以保持幂等保护有效。
应用层错误统一使用以下响应结构:
{
"code": 108006,
"message": "Insufficient payout balance",
"data": {
"error": "insufficient_balance",
"field": "amount",
"retryable": false
}
}程序逻辑应依据 code 或 data.error 处理,不要依赖仅用于排查问题的 message。仅当 data.retryable=true 且对应的临时状态已经恢复时才进行重试。HMAC 请求如果被网关直接拒绝,由于没有进入应用层,响应可能只有 message 字段。
Fiat Payout 专属业务错误码使用预留的 108001-108099 号段。HTTP 状态码与响应体 code 的职责不同:HTTP 状态码表示错误类别,code 表示稳定的业务原因。
| HTTP | code | data.error | 可能接口 | 可重试 | 含义与处理方式 |
|---|---|---|---|---|---|
| 400 | 30013 | invalid_parameter | Quote、Create、Get、List | 否 | 请求字段缺失、格式错误、不支持或彼此不一致。修正 data.field 后重新提交。 |
| 401 | 401 | authentication_failed | 全部接口 | 否 | HMAC 或应用鉴权失败。检查 API Key、签名、Date、Digest 和参与签名的请求路径。 |
| 403 | 403 | permission_denied | 全部接口 | 否 | API Key 缺少所需权限、IP 策略拒绝请求,或组织无权访问对应资源。 |
| 403 | 108010 | payout_source_account_not_found | Quote、Create | 否 | 组织没有 USD 付款账户。 |
| 404 | 404 | resource_not_found | Create、Get | 否 | 当前鉴权组织下不存在该 quote_id 或 payout_id。 |
| 409 | 108012 | idempotency_conflict | Create | 否 | client_reference_id 已被不同业务数据使用。不同的逻辑付款必须使用新的引用。 |
| 409 | 108013 | quote_already_used | Create | 否 | Quote 已被消费,请重新获取 Quote。 |
| 409 | 108014 | quote_not_active | Create | 否 | Quote 已不再处于可用状态,请重新获取 Quote。 |
| 409 | 108015 | payout_submission_in_progress | Create | 是 | 当前组织已有另一笔付款正在提交。短暂随机退避后重试。 |
| 409 | 108011 | payout_source_account_invalid | Quote、Create | 否 | USD 付款账户配置不一致,请联系 Infini 支持。 |
| 422 | 108001 | invalid_fee_mode | Quote | 否 | amount_mode 与 fee_paid_by 组合不受支持。 |
| 422 | 108002 | quote_expired | Create | 是 | Quote 已过期。请重新获取 Quote,不要继续重试过期的 quote_id。 |
| 422 | 108003 | quote_unavailable | Quote、Create | 是 | Quote 计算或其绑定的收款资料快照暂时不可用,短暂等待后重新获取 Quote。 |
| 422 | 108004 | amount_exceeds_limit | Quote | 否 | 金额超过当前支持的付款金额,请降低金额。 |
| 422 | 108005 | amount_too_small | Quote | 否 | sending_amount 必须大于 100 USD,请提高金额。 |
| 422 | 108006 | insufficient_balance | Create | 否 | 组织 USD 可用余额不足以支付 sending_amount,入金后再创建付款。 |
| 422 | 108007 | daily_limit_exceeded | Create | 否 | 该付款会超过账户共享的每日提现限额,请等待下一个限额周期或降低金额。 |
| 503 | 108009 | payout_service_unavailable | Create | 是 | 付款执行服务或服务商流动性暂时不可用。同一笔逻辑付款稍后重试时继续使用原来的 client_reference_id。 |
| 500 | 500 | internal_error | 全部接口 | 是 | 发生未预期的内部错误。可安全重试;如果持续出现,请携带 Request ID 联系 Infini 支持。 |
Quote 请求包含银行账户敏感信息,响应只返回脱敏账号。客户端不得将完整银行账号写入 URL、日志、client_reference_id、statement_reference 或其他自由文本元数据。
| 付款状态 | 含义 |
|---|---|
processing | 已开始执行,等待最终结算 |
completed | 银行合作方在当前已知状态下报告付款完成 |
failed | 付款在银行成功完成前失败 |
API 付款不会出现待审批状态。
使用 POST /v2/payouts/status/batch 可以按包含边界的 Unix 秒时间区间对账付款。结果按创建时间倒序排列。接口使用页码分页:page 默认值为 1,page_size 默认值为 20,且不能超过 100。
如果对端银行随后退回一笔已完成付款,status 继续保持 completed,failure 保持 null,return 返回独立退款信息:
{
"status": "completed",
"return": {
"status": "refunded",
"reason_code": "recipient_bank_rejected",
"reason": "Beneficiary bank rejected the transfer",
"returned_amount": "1000.00",
"refund_amount": "1000.00",
"retained_fee": "51.00",
"currency": "USD",
"returned_at": 1786674271
}
}returned_amount:银行合作方报告的退回金额。refund_amount:实际退回组织余额的金额。retained_fee:原付款未退还的手续费。returned_at:独立退款入账时间。
未发生银行退汇时,return 为 null。
查询一笔已知付款时使用 GET /v2/payouts/{payout_id},按时间窗口对账时使用 POST /v2/payouts/status/batch;两者均为对外权威对账接口。