内部转账指南
本指南介绍如何在同一银行的账户之间进行内部转账,涵盖三种可用方法及其使用场景。
概述
内部转账在同一银行的账户之间转移资金,无需通过 PIX 网络。转账即时处理。
有三种方式识别目标账户:
| 方法 | 端点 | 目标账户要求 | 使用场景 |
|---|---|---|---|
| 按账户 ID | /transfers/internal | 必须启用 API 访问 | 自有账户间转账 |
| 按证件号 | /transfers/internal/by-document | 银行任意账户 | 向任何账户持有人转账 |
| 按支行/账号 | /transfers/internal/by-bank-account | 必须启用 API 访问 | 已知支行和账号时使用 |
1. 按账户 ID 转账
最高效的方法。当源账户和目标账户都已在 API 中注册时使用。
端点: POST /v1/accounts/{accountId}/transfers/internal
curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/transfers/internal" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-001" \
-d '{
"destinationAccountId": "773107de-139e-48d1-9462-f4e88f251891",
"value": 1500.00,
"description": "分支间转账",
"identifier": "branch-transfer-001"
}'
字段:
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
destinationAccountId | string (UUID) | 是 | 目标账户 UUID(API 内部标识符) |
value | number | 是 | 金额(巴西雷亚尔,最多2位小数) |
description | string | 否 | 转账描述(最多 140 个字符) |
identifier | string | 否 | 用于追踪的唯一标识符。省略时自动生成 |
响应 (200):
{
"paymentId": "pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"workflowId": "internal-out-{accountId}-branch-transfer-001-int-001",
"runId": "b7c1f0e2-...",
"transactionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"endToEndId": "E50871921202603181530000000001",
"destinationAccountId": "773107de-139e-48d1-9462-f4e88f251891",
"status": "COMPLETED",
"value": 1500.00,
"description": "分支间转账",
"identifier": "branch-transfer-001",
"idempotencyKey": "int-001",
"completedAt": "2026-03-18T15:30:00Z"
}
转账被拒绝时,返回相同结构的响应体,但状态码为 422,status 为
"FAILED",并填充 errorCode/errorReason 字段。
2. 按证件号(CPF/CNPJ)转账
当目标账户未在 API 中注册时使用。适用于银行生态系统中的任何账户。
端点: POST /v1/accounts/{accountId}/transfers/internal/by-document
curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/transfers/internal/by-document" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-002" \
-d '{
"document": "12345678000190",
"value": 500.00,
"description": "供应商付款",
"identifier": "supplier-payment-002"
}'
字段:
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
document | string | 是 | 目标账户持有人的 CPF 或 CNPJ(纯数字) |
value | number | 是 | 金额(巴西雷亚尔) |
description | string | 否 | 转账描述(最多 140 个字符) |
identifier | string | 否 | 用于追踪的唯一标识符。省略时自动生成 |
当目标证件号存在多个激活账户时,按证件号寻址存在歧义,请求将被拒绝
并返回 409 multiple_destination_accounts。此时请改用
/transfers/internal/by-bank-account(分行号 + 账号)或
/transfers/internal(destinationAccountId)。
3. 按支行和账号转账
当您有支行号和账号时使用。两个账户都必须在 API 中注册。
端点: POST /v1/accounts/{accountId}/transfers/internal/by-bank-account
curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/transfers/internal/by-bank-account" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: tenant-yourcompany" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: int-003" \
-d '{
"branch": "0001",
"accountNumber": "200038274",
"holderDocument": "12345678000190",
"holderName": "目标公司",
"value": 250.00,
"description": "退款",
"identifier": "refund-003"
}'
字段:
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
branch | string | 是 | 目标账户支行号 |
accountNumber | string | 是 | 目标账号 |
holderDocument | string | 是 | 目标账户持有人的 CPF/CNPJ —— 清算行需要该证件号来路由 |
holderName | string | 否 | 目标账户持有人姓名 |
value | number | 是 | 金额(巴西雷亚尔) |
description | string | 否 | 转账描述(最多 140 个字符) |
identifier | string | 否 | 用于追踪的唯一标识符。省略时自动生成 |
如何选择方法?
目标账户是否启用了 API?
├── 是 → 您有账户 ID (UUID) 吗?
│ ├── 是 → 使用 /transfers/internal(最快)
│ └── 否 → 使用 /transfers/internal/by-bank-account
└── 否 → 使用 /transfers/internal/by-document
实际示例:
- 公司分支机构间调拨 →
/transfers/internal(按账户 ID) - 向银行供应商付款 →
/transfers/internal/by-document(按 CPF/CNPJ) - 向已知支行账号转账 →
/transfers/internal/by-bank-account
Webhooks
内部转账完成后,双方都会收到 webhook:
- 发送方:
transfer.internal.out - 接收方:
transfer.internal.in
{
"id": "transfer-internal-out-pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"type": "transfer.internal.out",
"occurredAt": "2026-03-18T15:30:00.000000000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-yourcompany",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"data": {
"paymentId": "pay_2f4a0f88-2147-49f2-a4e2-4f7b9f6c0f7a",
"transactionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"endToEnd": "E50871921202603181530000000001",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"direction": "OUT",
"sourceAccountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"sourceTenantId": "tenant-yourcompany",
"destinationAccountId": "773107de-139e-48d1-9462-f4e88f251891",
"destinationTenantId": "tenant-yourcompany",
"amount": 1500.00,
"description": "转给 SP 分支",
"identifier": "branch-transfer-001",
"status": "SUCCESS"
}
}
data 是扁平结构:没有包含姓名和证件号的嵌套 source/destination
对象——对手方以 sourceAccountId / destinationAccountId 呈现。
transfer.internal.in 一侧的负载相同,只是 accountId 为目标账户,
direction 为 "IN"。
由于结算是原子且同步的,webhook 始终以 data.status: "SUCCESS" 送达——这是 transfer.internal.* 唯一可能的取值。失败(余额不足、目标账户不存在、账户被冻结等)会直接体现在 POST /transfers/internal* 的 HTTP 响应中,不会产生 webhook。
发给付款方的 webhook(transfer.internal.out)会原样携带您在请求体(POST /transfers/internal*)中提交的 identifier 和 description,以及同步响应中也包含的 paymentId 和 transactionId。这样无需额外查询流水即可在您的系统中完成对账。
只有当目标账户同样由 CorpX 管理时才会发出 transfer.internal.in 一侧的事件;它会重复相同的字段(包括付款方设置的 identifier),仅 accountId 和 direction 不同。
要接收这些 webhooks,请在订阅的事件类型中包含 transfer.internal.in 和/或 transfer.internal.out。
常见错误
| 状态码 | errorCode | 原因 |
|---|---|---|
| 400 | missing_fields | 缺少必填字段(value、description、目标账户) |
| 400 | invalid_field | 金额超过 2 位小数、分行号无效、描述格式错误 |
| 400 | invalid_identifier | identifier 超出字符集 [A-Za-z0-9._-] 或超过 38 个字符 |
| 404 | beneficiary_not_found | 目标账户不存在(CorpX 中没有该 destinationAccountId,或该证件在清算行没有账户) |
| 422 | beneficiary_not_active_at_partner | 账户在 CorpX 存在,但清算行尚无该持有人(开户流程未完成) |
| 422 | beneficiary_incomplete | 清算行返回的持有人缺少分行号/账号 |
| 422 | recipient_account_not_found | 清算行未找到所提供的目标账户 |
| 409 | multiple_destination_accounts | 该证件下有多个活跃账户(请使用 by-bank-account) |
| 409 | identifier_conflict | 该源账户下已存在使用相同 identifier 的转账 |
| 422 | insufficient_funds | 可用余额不足以支付该金额 |
| 422 | balance_reservation_failed | 余额存在但无法锁定(冻结、并发) |
| 422 | partner_account_disabled | 源账户在银行已停用 |
| 422 | limit_exceeded_transaction / limit_exceeded_daily | 超出转账限额 |
| 422 | partner_rejected | 因银行内部政策被拒绝,partner 区块包含其说明的原因 |
| 502 | partner_error / partner_unavailable | 银行侧错误或不可用 |
422 是结果,202 是不确定被拒绝的转账返回 422,带 status: "FAILED"、errorCode 和 errorReason
——资金未发生变动,也不会有 webhook。202 且 status: "PENDING" 含义
不同:请求已发出,但在同步窗口内未收到确认。此时请先查询流水再重新发起——使用
相同 Idempotency-Key 重复提交会复用进行中的操作,但换用新的 key 可能导致重复
转账。