通过对方的 Pix 密钥把余额转到另一个 PayZu 账户,响应中直接带有结果。
资金不经过 Pix:目的地始终是另一个 PayZu 账户,由其 Pix 密钥识别。其他任何目的地,请使用提现。
发起转账
POST /transactions/internal-transfer,作用域 INTERNAL_TRANSFER。WITHDRAW 不能访问这个路由:凭证需要 INTERNAL_TRANSFER。必填:以分为单位的 amount,以及另一个 PayZu 账户的 Pix 密钥 toPixKey。
为每笔转账生成一个 Idempotency-Key;重复调用时,发送同一个。
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST https://api.hub.payzu.com.br/api/v1/transactions/internal-transfer \
-H "Authorization: Bearer $PAYZU_TOKEN" \
-H "Idempotency-Key: $IDEMPOTENCY_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 10000,
"toPixKey": "financeiro@lojaparceira.com.br",
"comment": "Repasse do mês"
}'import crypto from 'node:crypto';
const idempotencyKey = crypto.randomUUID();
const res = await fetch('https://api.hub.payzu.com.br/api/v1/transactions/internal-transfer', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PAYZU_TOKEN}`,
'Idempotency-Key': idempotencyKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 10000,
toPixKey: 'financeiro@lojaparceira.com.br',
comment: 'Repasse do mês',
}),
});
const transferencia = await res.json();comment 显示在转账凭证上。callbackUrl 在你这一端接收 Webhook,需要回调密钥。所有字段见转账到另一个 PayZu 账户。
读取结果
响应(201)带有结果。为 CONFIRMED 时,金额已在对方账户中:不需要等待 INTERNAL_TRANSFER_SENT Webhook。
{
"id": "hubp-20261005L9C3VH6KMA127431",
"status": "CONFIRMED",
"side": "SENT",
"amount": 10000,
"serviceFee": 100,
"totalDebited": 10100,
"counterparty": {
"name": "Loja Parceira Ltda",
"document": "12.345.678/0001-95",
"pixKey": "financeiro@lojaparceira.com.br"
},
"comment": "Repasse do mês",
"providerRejectedReason": null,
"callbackUrl": null,
"createdAt": "2026-10-05T15:02:44.010Z",
"confirmedAt": "2026-10-05T15:02:44.418Z",
"failedAt": null
}手续费另加:对方账户收到完整的 amount,你的账户扣出 totalDebited。为 FAILED 时,没有任何扣款,providerRejectedReason 带有固定消息,用于展示。
下载凭证
可选。GET /transactions/internal-transfer/{transferId}/receipt 以 base64 返回 PDF,适用于 CONFIRMED 的转账。它不是 Pix 凭证,也没有 end-to-end 标识:转账以 id 标识。
重复请求
Idempotency-Key 遵循提现的规则,比较使用金额和目的地。同一个键配上其他金额或目的地,会以 409 TRANSFER_IDEMPOTENCY_KEY_REUSED 被拒绝。
遇到 502,且银行未响应(PROVIDER_UNAVAILABLE)或临时拒绝(details.status 为 408 或 429 的 PROVIDER_REFUSED)时,转账可能已经发出。它会停留在 REQUESTED,没有结果,金额留在可用余额之外:
- API 不会自行解决:没有任何 Webhook 或查询能提前给出结果。PayZu 会与银行核对,之后转账变为
CONFIRMED或FAILED。 - 用同一个
Idempotency-Key重复请求会返回原转账,仍为REQUESTED,不会再发送一笔。新的键会创建另一笔转账。 - 在结果核对出来之前,它计入当天的每日上限。
银行的最终拒绝会让转账变为 FAILED,并退回金额。
两端
同一笔转账出现在两个账户中,由 side 表明是哪一端:
| 字段 | side: "SENT" | side: "RECEIVED" |
|---|---|---|
amount | 转给目的地的金额 | 转入的金额 |
serviceFee 和 totalDebited | 手续费和扣款总额 | 0 |
counterparty | 收款方 | 转出方 |
counterparty.pixKey | POST 响应中为完整值;查询和列表中已脱敏 | 已脱敏 |
callbackUrl | 发送的 URL | null |
| Webhook | INTERNAL_TRANSFER_SENT | INTERNAL_TRANSFER_RECEIVED |
只有已确认的转账才会产生 Webhook。
查询
GET /transactions/internal-transfer/{transferId}和GET /transactions/internal-transfer,作用域INTERNAL_TRANSFER_READ。列表包含两端;?side=SENT或?side=RECEIVED筛选其中一端。也可以按status、dateFrom和dateTo筛选。- 其他账户的转账或不存在的转账,返回
404TRANSFER_NOT_FOUND。
限额
- 余额不足会拒绝整笔转账,按
totalDebited计算。TRANSFER_INSUFFICIENT_BALANCE带details.available和details.required。 - 金额必须在账户转账的最小值和最大值之间,见限额中的
internalTransfer。 - 每日上限独立于提现:
dailyInternalTransfer。0会阻止所有转账,limit: null表示无上限。超出时返回422TRANSFER_DAILY_LIMIT。 - 每个凭证每分钟最多 5 次请求,每个账户 10 次。超过后,API 返回
429和Retry-After。
拒绝
需要换一个目的地或调整账户的拒绝:
| 状态 | code | 何时 |
|---|---|---|
| 404 | TRANSFER_DESTINATION | 没有任何 PayZu 账户启用了该密钥。请使用提现。 |
| 422 | TRANSFER_DIFFERENT_PROVIDER | 目标账户在另一家银行运营。请使用提现。 |
| 422 | TRANSFER_SAME_ACCOUNT | 该密钥属于你自己的账户。 |
| 422 | TRANSFER_AMBIGUOUS_DESTINATION | 该密钥在多个账户中处于启用状态。 |
| 422 | TRANSFER_DESTINATION_NOT_ACTIVE | 目标账户未激活。 |
| 422 | TRANSFER_MAIN_ACCOUNT_DESTINATION | 该密钥属于一个不接收转账的账户。 |
| 422 | TRANSFER_NO_ORIGIN_KEY | 你的账户没有启用的 Pix 密钥。见 Pix 密钥。 |
| 422 | ACCOUNT_BLOCKED_BY_PROVIDER | 银行冻结了你账户的转出或目标账户的转入。details.operation 指明是哪一种。 |
| 422 | ACCOUNT_HELD_BY_STAFF | 你的账户或目标账户被客服暂扣。 |
所有拒绝及其 code 见转账到另一个 PayZu 账户,凭证和作用域相关的拒绝见身份认证。