purpose: "banking" 的充值目的地。
该目的会保留本地法币,用于法币付款。默认的 fondeo 目的会把入账
法币转换为您账户的主资产(USD 为主资产)。Banking 目前仅支持
BO/BOB/bank_transfer、MX/MXN/bank_transfer 和
AR/ARS/bank_transfer。
两类本地法币目的地
对于本地法币走廊(BO/BOB、MX/MXN、AR/ARS),每个 payin 目的地都带有
purpose,决定入账资金的去向:
请创建第二个
purpose: "banking" 的目的地来持有本地法币用于付款;未指定
目的地的目的地保留历史 fondeo 行为。Banking 目的仅支持
BO/BOB/bank_transfer、MX/MXN/bank_transfer 和 AR/ARS/bank_transfer。
按货币划分的 Banking
🇺🇸 USD — 美元
按本指南的档案 → 账户 → 操作流程开立经典 Banking 客户账户(ACH、Fedwire 和 SWIFT 通道,见下文「开立银行账户」一节)。通过 Banking 收到的 USD 保留 用于付款(payouts);发送到您 CBPay 余额的 USD 落入 您的主资产(USD 为主资产)。🇪🇺 EUR — 欧元
所有欧元业务都通过虚拟 IBAN:申请funding_usdt 地址将入账欧元转换为您的
主资产,或申请 banking_eur 地址持有 BANK_EUR 用于 SEPA 付款(见下文
「欧元:入金地址与欧元银行,集中在一处」一节)。向第三方发送欧元见
SEPA 即时付款。
🇧🇴 BOB — 玻利维亚诺
通过带purpose 的充值目的地接收玻利维亚诺:
fondeo(默认)将入账自动转换为您的主资产(USD 为主资产);banking
保留 BOB 用于本地付款。入金流程见资金账户。
🇲🇽 MXN — 墨西哥比索
通过带purpose 的充值目的地接收比索:
fondeo(默认)将入账自动转换为您的主资产(USD 为主资产);banking
保留 MXN 用于本地付款(payouts)。
🇦🇷 ARS — 阿根廷比索
通过带purpose 的充值目的地接收比索:
fondeo(默认)将入账自动转换为您的主资产(USD 为主资产);banking
保留 ARS 用于本地付款(payouts)。
企业多银行:运营账户
企业账户可以在启用的本地通道中创建多个purpose: "banking" 充值
账户:BO/BOB、MX/MXN 和 AR/ARS,且 method 必须为
bank_transfer。每个目的地使用不同的 Idempotency-Key;重复使用会
返回原账户,不会再次开户。每个企业账户和通道最多保留 50 个 banking
工具(超过时返回 422 deposit_account_limit_reached)。个人账户仍
然每个通道只有一个 banking 工具。
label 是可选的本地昵称,最多 60 个字符,可通过
PUT /v1/payins/deposit-accounts/{instrumentID}/label 修改或清除。
对于 AR/ARS,企业可以先创建没有 bank_alias 的 CVU;此时状态为
alias_pending,余额和流水会返回 409 alias_pending,直到调用
PUT /v1/payins/deposit-accounts/{instrumentID}/bank-alias。个人账户
创建时仍保留 400 missing_alias 规则。
运营查询:
currency、funds_model(BO 为 retained,MX/AR 为
centralized),以及精确的 minor 字符串:credited_in、paid_out、
refunded_in、refunded_out、other_net、derived_available 和
display_available。流水是 payin 与 payout 的分页联合结果;from
和 to 必填。
BO/BOB payout 可在 POST /v1/payouts 或
POST /v1/payouts/qr/confirm 发送 UUID 字段 source_instrument_id。
在其他通道发送会返回 400;不属于账户返回 404 not_found;非活跃
或非 banking 工具返回 422 invalid_source_instrument。省略 UUID 时,
多个活跃来源返回 422 ambiguous_source_instrument。MX/AR 继续从母账户
或 centralizer 付款。
银行服务费用有两种形式。独立固定费用(
banking_customer、banking_account、banking_operation)在每笔操作执行时从您的默认结算资产余额(USD 为主资产)扣除,若操作失败则自动退款。按通道的交易费用(banking_deposit、banking_transfer_ach、banking_transfer_swift、banking_transfer_wire、banking_transfer_sepa)为百分比加固定金额,以操作货币(您的 BANK_USD / BANK_EUR 余额)计收——参见下文「通道费用(存款与转账)」一节。费用为 0(默认值)时服务免费。每个响应中的 banking_fee 和 banking_fee_asset 字段显示实际扣费金额及币种。完整流程
- 创建您的银行客户档案(
POST /v1/banking/customer)——仅一次。 - 上传验证证件并提交审核。
- 状态变为
approved后,按货币开立账户。 - 登记收款人(交易对手)用于第三方付款。
- 发送付款:用
prepare询价,用operations执行。
banking_customer_status_changed 和 banking_operation_status_changed webhook 送达(webhooks)。
1. 创建您的银行客户档案
每个账户仅一次。若省略type、name 或 email,会从您的 CBPay 账户自动填充:
201:
409 banking_customer_exists。
持久幂等性。 平台会为该账户/档案在核心生成确定性的 claim。首次成功
请求返回
201。重复相同请求返回 201 并带有 idempotency_hit: true,
不会创建第二个档案,也不会重复收取档案费用。相同账户使用不同 payload
会返回 409 idempotency_conflict。如果上游/核心结果不明确,API 返回
503 banking_recovery_pending;不要使用新密钥重试。运营人员必须先核对
持久 claim。申请审核。 如果您的组织启用了银行申请审核,此请求可能返回
202 Accepted({"status":"in_review","kind":"banking_application","review_id":"…"})而不是 201——只有在合规团队批准审核后才会创建银行资料。银行资料费用在申请挂起时收取,如果被拒绝则自动退还。通过 webhook txn_review_status_changed 或交易审核跟踪结果。EUR 使用直接虚拟 IBAN 流程。 通用的
POST /v1/banking/customer onboarding 仅支持 USD。不要为 EUR 创建通用
banking profile;请在 Operar EUR 中使用
POST /v1/banking/virtual-ibans,发送 {"purpose":"banking_eur"}。
账户无需先有 banking customer 即可申请该 vIBAN;平台会在批准期间创建所需
的本地关联。向通用 customer 接口发送 currency: "EUR" 会返回
400 banking_eur_requires_viban。2. 证件与验证
以 base64 格式上传每份证件(免费):draft → submitted → under_review → approved 或 rejected。每次变更都会由 banking_customer_status_changed webhook 通知 — 包括自己的档案(customer_kind: self)和你注册的第三方(customer_kind: third_party,附其 third_party_id):
3. 开立银行账户
档案变为approved 后,在通用 Banking onboarding 中只开立 USD 账户(ACH/Fedwire/SWIFT 通道)。EUR 不在此处开立;请直接使用 EUR 虚拟 IBAN 流程 请求 banking_eur。
201——data 中包含用于接收资金的信息(账号/IBAN、路由号、银行):
GET /v1/banking/accounts/{id})返回账户的实时数据 —
名称、币种、状态,以及 data 下的接收资金所需要件(电汇与本地
轨道:银行、账号/IBAN、routing)。用于展示特定账户的入金指引,无需
遍历列表:
source 表示详情的来源:live(银行实时返回)或 mirror(银行当时
无法返回该账户,返回最近一次已知快照——入金要件仍然可用)。
列表仅暴露根据通道配置为您的业务启用的账户。未启用的账户不会出现
在列表中,其按 id 的查询返回
404 not_found。个人账户限制:个人账户最多持有 1 个银行账户。尝试开立第二个会返回
409 banking_account_limit。企业账户没有限制。第三方用户(仅限企业)
如果您的账户是企业,除了您自己的账户外,还可以登记第三方银行用户——您的终端客户(个人或企业)——每个用户拥有自己的身份和验证,以及以其名义开立的银行账户。第三方数量及每个第三方的账户数量均无限制。登记第三方
登记需要该第三方一条已批准的 KYC/KYB 验证的verification_id——这是其在 CBPay 内的唯一身份。类型由验证种类决定(KYC ⇒ INDIVIDUAL,KYB ⇒ COMPANY),数据(姓名、邮箱、地址)会从已验证的档案自动填充(您显式提供的内容优先),并且已校验的证件会自动重新递交给银行服务提供方。此时计收银行客户档案费用(登记失败则退款):
201:
documents_synced 表示自动加载到该第三方银行档案中的验证证件数量。如果某份证件未能同步(或银行要求额外类别),请通过下方的手动证件流程上传,然后执行 submit。申请审核。 启用银行申请审核后,注册第三方也可能返回
202 Accepted(kind: banking_application):只有在审核通过后才会注册第三方,注册费用在被拒绝时自动退还。通过 txn_review_status_changed 或交易审核跟踪结果。third_party_id:所有第三方路由都使用它。列出与查询(GET 中包含实时的验证状态):
第三方验证(免费)
与您自己的档案相同,只是作用于该第三方:第三方账户
第三方获批后,为其开立账户(同样计收banking_account 费用),操作方式与您自己的账户完全一致:
- 每个第三方只属于您:其他 CBPay 账户永远无法查看或操作它(会得到
404)。 - 个人账户尝试创建第三方会收到
403 company_required。 - 未提供
verification_id(或验证未获批准)时,登记会返回422 verification_required/422 verification_not_approved。如果发送的type与验证种类不匹配,则返回422 verification_kind_mismatch。在此规则之前创建的第三方继续正常运作。 - 已登记的第三方会计入您账户摘要中的”新用户”指标。
4. 登记收款人
要向第三方付款,需先用其银行信息登记收款人(免费;需经审核通过后方可使用):GET /v1/banking/counterparties 列出您的收款人,用 POST /v1/banking/counterparties/{id}/accounts 为已有收款人追加更多账户。
欧元:入金地址与欧元银行,集中在一处
所有欧元内容都在这里。欧元虚拟 IBAN(vIBAN)是带两种用途之一的寻址与路由工具,不是供应商的独立余额。下文记录两个用途已经实现的入金和 returns/recalls;provider customer onboarding 与生产启用信息不属于公开的 provider-agnostic 合同。申请 vIBAN
平台可以为已验证且处于 active 状态的账户申请虚拟 IBAN。使用幂等键申请默认入金地址:funding_usdt 是默认用途。平台会从已批准的 KYC/KYB profile 构建 registrant。如果 verified profile 缺少证件签发国家或证件到期日,账户申请可以发送以下顶层可选 override(接受 snake_case 和 camelCase aliases):
incorporation_country / incorporationCountry 与 incorporation_date / incorporationDate。这些值只用于补全已验证 registrant,不会绕过 KYC/KYB。
申请会进入人工审批队列:
banking_eur:
{page, page_size, virtual_ibans}。支持的状态是 pending_approval、pending、active、rejected、failed、disabled 和 closed。账户读取在已有 IBAN 时显示完整值;组织管理员读取会将其掩码。
按地址读取、关闭与查询操作
按 ID 读取单个申请:closed);关闭幂等,后续读取反映终态。
使用 GET /v1/banking/virtual-ibans/{id}/operations 列出单个地址的 Banking 操作(分页与日期窗口与全局操作列表相同)。
第三方虚拟 IBAN
企业账户可以为已接受邀请并完成已批准 KYC/KYB 的自有第三方申请banking_eur vIBAN。第三方是余额 owner,企业管理关系:
banking_eur,并遵循账户申请相同的人工审批和状态周期。
BANK_EUR 余额
对于banking_eur 申请,显式查询已对账余额:
asset: "BANK_EUR"、available、held、purpose 和 source。对 funding_usdt 会返回 409 balance_not_available,因为该用途经 payin credit 链记入您的主资产,而不会持有 BANK_EUR。
发送欧元:payout 与 Banking 操作
发送欧元有两种入口,两者读取同一个地址。请按入口区分,而不是按地址区分:
两个入口的共同机制:
- 来源在请求顶层用
source_virtual_iban_id选择。如果账户只有一个与入口对应用途的 active vIBAN,可以省略该字段。没有 active 来源返回422 funding_account_required;有多个 active 来源但没有明确 UUID 返回422 ambiguous_source_viban。 - 平台会删除调用方提交的付款人身份字段,并从所选 vIBAN 的
registrant由服务端写入payer;如果存在更具体的服务端企业 wallet payer,则优先使用它。 - 对于没有可用 registrant 的 active 原有行,平台会从当前已验证 profile 推导付款人姓名。若 profile 暂时无法读取,返回
503 funding_account_unavailable;若最终身份不完整,返回422 registrant_incomplete。 source_virtual_iban_id是 EUR Banking 操作意图的一部分。使用同一幂等键会返回原操作;并发进行中的请求返回409 operation_in_progress,请使用同一键重试。- 此流程没有按 vIBAN 设置的金额上限。EUR Banking 从账户的
BANK_EUR余额扣款。 - 这道来源门控上线前创建的 Banking operation hold 属于 grandfathered 记录:继续使用原有 dispatch 与 reconciliation 流程。
接收欧元:已验证的入金处理
当银行 provider 发送终态入金事件时,core 将其规范化为banking_virtual_iban_inbound。平台解析 owner vIBAN 并使用其用途:
funding_usdt创建 EUR 的banking_fundingpayin,应用 EUR→USDT 标记汇率和配置的 fee/spread,然后进入 payin firewall 与 credit 链。banking_eur创建BANK_EUR的 Banking 入账镜像,使用 Banking ledger 路径,发送 KYT/operation status,并排队发送 Banking receipt email。
completed、success、settled、credited 或 succeeded 等终态才会产生资金效果。pending/unknown 状态保持可对账,不会增加余额。
failed 和 rejected 是负面的终态,不会创建 credit;尚未 credited 的 funding payin 会标记为 failed,且不会进入重复 refund loop。
Returns/recalls 作为终态
returned、recalled 或 reversed 处理。credit 前发生 return 时,后续 completion replay 不会入账;已 credited 的 funding_usdt payin 会进入确定性的 chargeback/refund 路径;已 ledger 化的 banking_eur operation 会追加 reverse entry。后续 completion 事件不能复活已经 returned 的 operation。payment_rail: "SEPA_INSTANT"、purpose(funding_usdt 或 banking_eur)和虚拟 IBAN reference。
EUR 错误
EUR 常见问题
申请虚拟 IBAN 会创建 BANK_EUR 余额吗?
申请虚拟 IBAN 会创建 BANK_EUR 余额吗?
不会。用途会记录在申请中,但虚拟 IBAN 不是供应商的独立余额。只有
banking_eur 地址才暴露已对账的 BANK_EUR 余额;funding_usdt 经 payin 链记入您的主资产。超时后可以重试吗?
超时后可以重试吗?
使用相同幂等键重试。新的键会创建新的申请,不能用来猜测一次不明确的供应商请求结果。
为什么状态是 pending_approval?
为什么状态是 pending_approval?
每个分配都需要组织运营人员在调用银行通道前进行人工审批。
同一个地址能用于 payout 和 Banking 操作吗?
同一个地址能用于 payout 和 Banking 操作吗?
每个入口读取自己对应的用途:SEPA payout 从入金地址付款,Banking 操作从 Banking 地址付款。显式
source_virtual_iban_id 始终优先于自动选择。已验证第三方的 Banking
企业账户可以为已批准的第三方 KYC 或 KYB submission 请求 banking 目的地。请求按 submission 和通道自然幂等;验证批准后会自动创建目的地。intent_id、kind、verification_id、country、currency、
method、status 和 fulfilled_instrument_id。状态为 pending、
fulfilled 或 abandoned;验证被拒绝后再次请求返回
409 intent_abandoned。引用账户自身的 onboarding verification 返回
422 verification_invalid。
5. 发送付款
两种操作类型:
先询价(免费,不移动资金):
banking_operation 费用):
202:
banking_fee 和 banking_fee_asset 仅在收取费用时出现。按通道计费时,币种为操作货币(BANK_USD / BANK_EUR);使用旧版回退时为您的默认结算资产。
- 最终状态通过
banking_operation_status_changedwebhook 送达(completed/failed);您也可以轮询GET /v1/banking/operations/{id}。操作达到最终状态后,webhook 中会包含其receipt_url,并可通过GET /v1/banking/operations/{id}/receipt下载 PDF 凭证(凭证)。 - 使用相同
Idempotency-Key的重试会返回原始操作(idempotency_hit: true),不会再次收取费用。
带筛选条件的完整历史:
每笔银行操作——包括自动从银行发现的入账存款和银行费用——在银行报告这些字段时都会暴露其
direction(in / out)、净额 amount、currency、counterparty 和
reference。这些字段为可选,出现在
GET /v1/banking/operations 和
GET /v1/banking/operations/{id} 中。banking_operation_status_changed Webhook 在设计上保持轻量:
它只携带标识符和新状态,不包含增强字段。收到该事件后,
请查询操作详情以读取方向、金额、对手方和参考号。参见
webhooks。
通道费用(存款与转账)
除了独立固定费用外,banking 还支持按通道的交易费用——百分比加固定金额,始终以操作货币(BANK_USD / BANK_EUR)计收,绝不使用 USDT:
对于转账,可用余额必须覆盖
金额 + 费用——否则 API 返回
402 insufficient_funds,且操作不会被创建。如果操作在发起后被
明确同步拒绝,费用将自动退还(与旧版费用相同的纪律)。
回退规则: 如果通道没有专属配置(账户级和平台级都没有),则适用旧的
banking_operation 费用(固定金额,从您的默认结算资产扣除)。通道配置为 0% + 0 固定费用表示
明确免费——不会回退到旧版费用。
操作状态
错误
常见问题
Banking 资金会显示在我的 USD 余额里吗?
Banking 资金会显示在我的 USD 余额里吗?
不会。Banking 资金存放在你的银行账户中,通过
GET /v1/banking/accounts/{id}/balance 查询。权威余额始终以银行为准;你的
对账单 会在 BANK_USD/BANK_EUR 镜像余额中对其
进行核对。按通道的费用以操作货币计收(您的 BANK_USD/BANK_EUR 余额);
只有旧的 banking_operation 回退费用才从您的默认结算资产余额中扣除。操作失败时手续费会怎样?
操作失败时手续费会怎样?
自动退款 —— 档案、账户和操作的手续费一视同仁,包括按通道的费用
(在明确同步拒绝时退还)。使用相同的
Idempotency-Key 重试会返回原始操作(idempotency_hit: true),绝不会
重复收费。我可以开多少个银行账户?
我可以开多少个银行账户?
每种货币一个(USD、EUR)。此外,个人账户总共最多持有 1 个银行账户
(
409 banking_account_limit);企业账户没有限制。为什么我的某个账户不在列表里?
为什么我的某个账户不在列表里?
列表只展示按通道配置为你的业务启用的账户。未启用的账户不会出现,
其按 id 的查询会返回
404 not_found —— 如需启用请联系你的 CBPay 团队。个人账户可以登记第三方用户吗?
个人账户可以登记第三方用户吗?
不可以 —— 第三方是企业能力(
403 company_required)。登记还需要该第三方
一次已通过的 KYC/KYB 验证的 verification_id。如何知道一笔付款到达最终状态?
如何知道一笔付款到达最终状态?
订阅
banking_operation_status_changed:它在 completed / failed 时触发,
最终状态时附带 receipt_url。你也可以轮询
GET /v1/banking/operations/{id}。Banking creation claims and recovery
Creation claims are durable records, not permission to send a second provider request. The platform storesbanking_creation_claims with kind,
idempotency_key, request_hash, status, attempts and refund state. Migration
105 creates this table and its single-flight lock; migration 106 stores
transaction-firewall fee-refund recovery. Migration 074 persists the resolved
core provider on customer idempotency claims.
Recovery rules
- A completed account recovery compares the provider account ownership with
the claimed customer’s
ProviderID. - A terminal provider authentication response (
401or403) does not by itself prove that the creation failed; the claim remains recoverable. - Reusing the same idempotency key with a different request hash is rejected.
- A completed claim can be replayed with HTTP
200andidempotency_hit: true; recovery does not call the provider again. POST /v1/org/banking/creation-claims/refundretries a pending fee refund forkind=customerorkind=account.POST /v1/org/txn-firewall/fee-refunds/{resourceID}/retryretries the durable firewall-fee refund. A completed refund replays as HTTP200.
POST /v1/ops/banking/account-creations/reconcile verifies the provider
account and finalizes the local mirror. The org-admin routes list claims,
reconcile customer claims, and retry refunds. These operations are locked so
concurrent reconciliation cannot originate duplicate money movement.