跳到主要内容

回调通知(Webhooks)

Webhooks 是我们的 API 在相关事件发生时(例如收到 PIX 或支付完成)向您注册的 URL 发送的通知。

部分事件暂时不可用

在我们从 Finaya 迁移到 MT Bank 作为结算方期间(2026 年 5 月), 以下事件尚未发送。它们仍出现在 GET /v1/webhooks/events 列表中 以保持契约稳定,您可以现在就订阅 —— 相应模块恢复后将自动开始投递:

  • MED(争议): pix.med.openedpix.med.updated —— 迁移期间 MED 模块离线。
  • 手续费(fees): fee.chargedfee.refunded —— 后端尚未将 MT 的手续费扣款作为独立事件物化;目前手续费会作为一条单独的 INTERNAL_TRANSFER 行出现在对账单中(description fee-{slug}-{ref})。
  • EDI: edi.batch —— EDI 批处理将在后续阶段重新引入。

暂无具体 ETA。各模块恢复时将在变更日志中发布通知。在后台 (Settings → Webhooks)中,这些事件的复选框会被标记为 em breve (即将推出)且不可点击 —— 在后端开始发送之前无法订阅。

Webhook 配置

Webhooks 必须通过 Integrator Portal 进行配置。

查询可用事件

curl -X GET "https://tenant.api.corpx.com/v1/webhooks/events" \
-H "Authorization: Bearer YOUR_TOKEN"

响应:

{
"eventTypes": [
"pix.in.completed",
"pix.out.completed",
"pix.out.failed",
"pix.out.timeout",
"pix.refund.completed",
"pix.refund.failed",
"pix.refund.received",
"pix.med.opened",
"pix.med.updated",
"qrcode.paid",
"qrcode.expired",
"qrcode.cancelled",
"boleto.paid",
"boleto.failed",
"transfer.internal.in",
"transfer.internal.out",
"fee.charged",
"fee.refunded",
"account.balance_updated",
"account.lock_created",
"account.lock_released",
"accreditation.pf.created",
"accreditation.pj.created",
"edi.batch",
"ted.out.requested",
"ted.out.confirmed",
"ted.out.failed",
"ted.in.received",
"ted.payment"
]
}

接收流程

  1. 我们平台上发生了一个事件。
  2. 我们向已注册的 URL 发送 POST 请求。
  3. 您的应用需处理该通知并返回 2xx 状态码。

配置灵活性

我们的 webhook 基础设施支持多种投递方式:

  • 合并:您可以在同一个 URL 接收多种事件类型(例如 pix.in.completedpix.out.completed)。
  • 分离:您可以为每种事件类型配置不同的 URL。
  • 冗余:我们可以同时将同一事件发送到多个独立的 URL。

安全性(目标端认证)

创建或更新 webhook 订阅时,您可以选择我们的投递基础设施如何对发往您端点的请求进行认证。认证方式通过 API 或控制面板按订阅进行配置。

可用认证方式

方式authType描述
HMAC 签名HMAC使用 HMAC-SHA256 和您的密钥对每个请求体进行签名。签名通过 X-Signature 请求头发送。推荐使用。
API KeyAPI_KEY在可配置的 HTTP 请求头中发送静态 API key(默认:X-API-Key)。
Basic AuthBASIC在标准 Authorization: Basic ... 请求头中发送 username:password
Bearer TokenBEARERAuthorization: Bearer ... 请求头中发送 token。
无认证NONE不进行认证。不建议在生产环境使用。

您可以在 Integrator Portal 中创建或更新 webhook 订阅时配置认证方式。前往 Webhooks > Edit Subscription,从下拉菜单中选择您偏好的认证方式。系统将根据所选方式要求您提供所需凭据(例如 HMAC 密钥、API key 或用户名/密码)。


HMAC 签名验证

authType 设置为 HMAC 时,每个请求都会包含一个 X-Signature 请求头,其中包含使用您的 secret 作为密钥对原始请求体计算的 Base64 编码 HMAC-SHA256 哈希值。

公式:

expected = base64(HMAC_SHA256(your_secret, raw_request_body))

将计算出的值与 X-Signature 请求头进行比较。如果匹配,则请求是可信的。

警告

请始终使用原始请求体字节进行验证,而非重新解析/重新序列化的版本。重新序列化 JSON 可能会改变字段顺序或空白字符,导致签名无效。

验证示例

Node.js:

const crypto = require("crypto");

function verifySignature(secret, rawBody, signatureHeader) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("base64");
return expected === signatureHeader;
}

// In your Express handler:
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-signature"];
if (!verifySignature(WEBHOOK_SECRET, req.body, signature)) {
return res.status(403).send("Invalid signature");
}
const event = JSON.parse(req.body);
// Process event...
res.sendStatus(200);
});

Python:

import hmac, hashlib, base64

def verify_signature(secret: str, raw_body: bytes, signature_header: str) -> bool:
expected = base64.b64encode(
hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(expected, signature_header)

Go:

func verifySignature(secret string, rawBody []byte, signatureHeader string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(rawBody)
expected := base64.StdEncoding.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signatureHeader))
}

API Key 认证

authType 设置为 API_KEY 时,我们会在每个请求的 HTTP 请求头中发送您配置的 API key。默认请求头名称为 X-API-Key,但您可以通过 authConfig.header 进行自定义。

# Creating a subscription with API Key auth:
curl -X POST "https://tenant.api.corpx.com/v1/webhooks" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-Id: your-tenant-id" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhook",
"authType": "API_KEY",
"authConfig": {
"key": "your-api-key-value",
"header": "X-API-Key"
},
"eventTypes": ["pix.in.completed"]
}'

您的服务器应验证请求头中的值是否与预期的 key 匹配。


Basic Auth

authType 设置为 BASIC 时,我们会在每个请求中发送 Authorization: Basic <base64(username:password)> 请求头。

{
"authType": "BASIC",
"authConfig": {
"username": "your-username",
"password": "your-password"
}
}

Bearer Token

authType 设置为 BEARER 时,我们会在每个请求中发送 Authorization: Bearer <token> 请求头。

{
"authType": "BEARER",
"authConfig": {
"token": "your-bearer-token"
}
}

信息性请求头

除上述认证请求头外,我们的投递基础设施还会在每个请求中添加以下信息性请求头:

请求头描述
x-hookdeck-event-id投递事件 ID(用于调试和支持请求)。
x-hookdeck-request-id原始请求 ID。
x-hookdeck-attempt-count投递尝试次数(首次尝试为 1)。

这些请求头仅供参考,无需验证。

IP 白名单

为提高集成安全性,我们建议您的目标服务器验证传入请求的来源 IP 地址。仅接受来自我们基础设施官方 IP 的通知:

  • 34.138.140.223
  • 34.138.161.100
  • 35.231.250.193
  • 35.196.71.29
  • 34.138.56.192

建议将这些地址添加到您防火墙或 Web 服务器的白名单中。

重试

如果您的应用返回错误(非 2xx 状态码)或发生超时,我们的系统将按照指数退避策略尝试重新发送通知:

  • 尝试次数:最多 6 次。
  • 间隔:逐步递增。

在所有尝试用尽后,该事件将被标记为失败。您可以使用我们 API 中的 Replay 端点请求手动重发。

重发事件(Replay)

如果您需要重发某个事件(由于处理失败或通知丢失),请使用 /v1/webhooks/replay 端点。

请求示例:

curl -X POST "https://tenant.api.corpx.com/v1/webhooks/replay" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "X-Tenant-Id: your-tenant-id" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"eventId": "evt_abc_123",
"tenantId": "your-tenant-id"
}'

API 将返回 202 Accepted 状态码,该事件将被加入队列等待新的投递尝试。

通知格式

所有通知遵循标准信封格式。每个事件的具体内容位于 data 对象中。

标准信封

{
"id": "evt_123456789",
"type": "pix.in.completed",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": { }
}

data 中的通用字段

以下字段出现在表示账本流水的所有事件类型中(PIX IN/OUT、退款、QR 支付、内部转账、手续费)。它们是将 webhook 与其他 API 端点关联起来的推荐方式:

字段说明
transactionId我们 API 使用格式的交易标识符。与 GET /v1/accounts/{accountId}/statement 返回的内容以及发起该交易的端点的同步响应一致。用于在我们的 API 中查询交易。
coreId银行合作方核心账本行的 UUID。与账单的 coreId 字段暴露的值相同;在 webhook 与异步账单同步之间保持稳定。用于与合作方导出数据对账。
endToEnd / endToEndId央行 PIX E2E ID(仅 PIX 事件)。
status交易状态。使用标准化词汇表(见下表)。

前三个字段可以在同一个载荷中共存。如果只有一个出现,则意味着另一个字段对该事件类型不相关(例如:内部转账带有 transactionId + coreId,但没有 endToEnd)。

data.status 可能的值

status 字段在所有事件中使用标准化词汇表:

Status含义事件
SUCCESS操作成功完成;余额已借记/贷记。pix.in.completedpix.out.completedpix.refund.completedpix.refund.receivedqrcode.paidboleto.paidtransfer.internal.intransfer.internal.outfee.chargedfee.refunded
FAILED操作失败。余额未发生变化(或已退回)。详情请查看 data.errorpix.out.failedpix.refund.failedboleto.failed
TIMEOUT调用合作方成功但响应超时。请先在对账单中确认后再使用新的 idempotency-key 重试。pix.out.timeout
EXPIRED动态二维码在 expiration 内未被支付而过期。qrcode.expired
CANCELLED集成方通过 DELETE /qrcodes/{txid} 显式取消了动态二维码。qrcode.cancelled
REVERSED之前已完成的 PIX IN 被撤销(例如完整退款)。当延迟对账覆盖已交付的 PIX IN 时出现。pix.in.completed(罕见,对账后)

MED(争议)事件的 status 使用自己的词汇表:

Status含义
OPEN由索赔方开启的争议,等待响应。
PENDING_DECISION已提交响应,等待央行/监管方决定。
ACCEPTED争议被接受 — 资金已返还(全部或部分)。
REJECTED争议被拒绝 — 资金保留在收款方。
CANCELED由索赔方或监管方取消的争议。

事件:pix.med.openedpix.med.updated

status 保证

对于表示账本流水的事件,status 始终存在。如果您收到的 webhook 中缺少此字段(或为空值),则它是纯信息性事件(例如 account.balance_updated)——此时请使用 type 字段本身来确定语义。

日期与时间格式

API 和 webhook 返回的所有日期/时间字段均遵循 ISO 8601 / RFC 3339 标准,使用 UTC 时区并带 Z 后缀。 这适用于信封字段(occurredAt)以及 data 内部的所有字段(receivedAtcompletedAtinitiatedAtchargedAtopenedAt 等)——同时也适用于 REST 端点(/statement/balance/payments 等)返回的 createdAt/updatedAt

示例:

2026-04-29T23:53:55.001Z         ← 毫秒精度
2026-04-29T23:53:49.328720Z ← 微秒精度
2026-04-30T18:04:36Z ← 不带小数秒

我们绝不输出巴西本地时间(BRT)或不带时区标识的"裸"时间戳。如果您收到不带 Z 后缀的日期字段,请视为缺陷并通知我们 —— 一经定位即会规范化。


事件类型与内容(data

1. pix.in.completed

当 PIX 成功入账到账户时发送。

data 结构:

  • endToEnd:中央银行的唯一交易 ID。
  • amount:交易金额。
  • currency:币种(例如 "BRL")。
  • payer:付款方详情(姓名、证件、银行、支行、账户)。
  • payee:收款方详情(姓名、证件、银行、支行、账户)。
  • reconciliationId:银行合作方的对账标识符(如可用)。
  • receivedAt:收款时间戳。

完整示例:

{
"id": "evt_123456789",
"type": "pix.in.completed",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEnd": "E0000000020251229211433912",
"amount": 150.50,
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"payee": {
"name": "Test Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"receivedAt": "2025-12-29T21:14:33.900Z"
}
}

2. qrcode.paid

当您生成的 QR Code 被支付时发送。

data 结构:

  • endToEnd:中央银行的唯一交易 ID。
  • type:QR Code 类型(staticdynamic)。
  • identifier:QR Code 的 txid(标识符)。
  • qrcodeId:内部 QR Code ID。
  • amount:支付金额。
  • currency:币种。
  • payer:付款方详情。
  • payee:收款方详情。
  • reconciliationId:银行合作方的对账标识符(如可用)。
  • receivedAt:收款时间戳。

完整示例:

{
"id": "evt_987654321",
"type": "qrcode.paid",
"occurredAt": "2025-12-29T21:15:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEnd": "E0000000020251229211500000",
"type": "dynamic",
"identifier": "txid-qr-123",
"qrcodeId": "qr_abc123",
"amount": 250.00,
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "Maria Oliveira",
"document": "98765432100",
"bankCode": "033",
"branch": "0001",
"accountNumber": "54321-0"
},
"payee": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"receivedAt": "2025-12-29T21:14:33.900Z"
}
}

3. pix.out.completed

当出账 PIX 转账成功完成时发送。

data 结构:

  • endToEnd:端到端 ID。
  • key:使用的目标密钥。
  • identifier:交易标识符。
  • amount:转账金额。
  • payer:您的账户详情。
  • payee:目标账户详情。
  • reconciliationId:银行合作方的对账标识符(如可用)。
  • initiatedAt:转账发起时间。
  • completedAt:确认完成时间。

完整示例:

{
"id": "evt_out_123",
"type": "pix.out.completed",
"occurredAt": "2025-12-29T21:14:53.900Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEnd": "E9999999920251229211433900",
"key": {
"type": "CPF",
"key": "12345678900"
},
"identifier": "transfer-001",
"amount": 50.00,
"reconciliationId": "FAlGf89fN0ol41Wyc5zVQ0k5KD",
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z",
"completedAt": "2025-12-29T21:14:53.900Z"
}
}

4. pix.out.failed

当出账 PIX 转账失败时发送。

data 结构:

  • endToEnd:端到端 ID(如可用)。
  • error:错误描述/失败原因。
  • key:目标密钥。
  • identifier:交易标识符。
  • amount:金额。
  • payer:您的账户详情。
  • payee:目标账户详情。
  • reconciliationId:银行合作方的对账标识符(如可用)。
  • initiatedAt:发起时间戳。

完整示例:

{
"id": "evt_out_err_123",
"type": "pix.out.failed",
"occurredAt": "2025-12-29T21:14:35.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEnd": "E9999999920251229211433900",
"error": "Insufficient balance in destination account or invalid key",
"key": {
"type": "EMAIL",
"key": "teste@exemplo.com"
},
"identifier": "transfer-002",
"amount": 1000.00,
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "Failed Recipient",
"document": "00000000000",
"bankCode": "001",
"branch": "0001",
"accountNumber": "00000-0"
},
"initiatedAt": "2025-12-29T21:14:33.900Z"
}
}

5. payment.sent (已弃用)

已弃用

此事件将在未来版本中移除。请改用带有 methodPAYMENT)字段和 payload 中 payment 对象的 pix.out.completed

当支付指令(PIX Out)被银行合作方确认并与对账单中的交易对账后发送。

data 结构:

  • paymentId:支付指令标识符。
  • endToEnd:中央银行的端到端交易 ID。
  • identifier:集成方创建支付时提供的标识符。
  • amount:支付金额。
  • currency:币种(例如 "BRL")。
  • status:支付状态(COMPLETED)。
  • key:目标 PIX 密钥(类型和值)。
  • payer:付款方详情(姓名、证件、银行、支行、账户)。
  • payee:收款方详情(姓名、证件、银行、支行、账户、PIX key)。
  • initiatedAt:支付指令创建时间戳。
  • completedAt:确认时间戳。

完整示例:

{
"id": "evt_pay_123",
"type": "payment.sent",
"occurredAt": "2026-02-13T15:50:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"paymentId": "pay_abc123",
"endToEnd": "E3674167520260213154900123456789",
"identifier": "order-12345",
"amount": 150.50,
"status": "COMPLETED",
"key": {
"type": "CPF",
"key": "12345678900"
},
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"account": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"account": "12345-6",
"pixKey": "12345678900"
},
"initiatedAt": "2026-02-13T15:49:30.000Z",
"completedAt": "2026-02-13T15:50:00.000Z"
}
}

6. payment.refunded (已弃用)

已弃用

此事件将在未来版本中移除。请改用带有 method: REFUND_RECEIVEDpix.in.completed

当您发送的支付(PIX Out)被收款方退回时发送。

data 结构:

  • paymentId:原始支付指令标识符。
  • originalEndToEnd:原始支付的端到端 ID。
  • refundEndToEnd:退款的端到端 ID(D 码)。
  • identifier:集成方提供的标识符。
  • originalAmount:原始支付金额。
  • refundAmount:退款金额。
  • currency:币种。
  • status:状态(REFUNDED)。
  • initiatedAt:原始支付时间戳。
  • refundedAt:退款时间戳。

完整示例:

{
"id": "evt_pay_ref_123",
"type": "payment.refunded",
"occurredAt": "2026-02-13T16:00:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"paymentId": "pay_abc123",
"originalEndToEnd": "E3674167520260213154900123456789",
"refundEndToEnd": "D3674167520260213160000987654321",
"identifier": "order-12345",
"originalAmount": 150.50,
"refundAmount": 150.50,
"status": "REFUNDED",
"initiatedAt": "2026-02-13T15:49:30.000Z",
"refundedAt": "2026-02-13T16:00:00.000Z"
}
}

7. pix.refund.completed

当 PIX 退款完成时发送。

data 结构:

  • originalEndToEnd:被退款的原始交易 ID。
  • refundEndToEnd:新退款 PIX 的 ID。
  • identifier:退款标识符。
  • amount:退款金额。
  • payer:您的账户详情(发起退款方)。
  • payee:目标账户详情(接收退款方)。
  • reconciliationId:银行合作方的对账标识符(如可用)。
  • initiatedAt:发起时间戳。
  • completedAt:完成时间戳。

完整示例:

{
"id": "evt_ref_123",
"type": "pix.refund.completed",
"occurredAt": "2025-12-29T21:14:53.900Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"originalEndToEnd": "E0000000020251229211433912",
"refundEndToEnd": "D0000000020251229211453900",
"identifier": "refund-999",
"amount": 150.50,
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z",
"completedAt": "2025-12-29T21:14:53.900Z"
}
}

8. pix.refund.failed

当退款请求失败时发送。

data 结构:

  • originalEndToEnd:原始交易 ID。
  • error:失败原因。
  • identifier:标识符。
  • amount:金额。
  • payer:您的账户详情。
  • payee:目标账户详情。
  • initiatedAt:发起时间戳。

完整示例:

{
"id": "evt_ref_err_123",
"type": "pix.refund.failed",
"occurredAt": "2025-12-29T21:14:35.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"originalEndToEnd": "E0000000020251229211433912",
"error": "Original transaction has already been refunded",
"identifier": "refund-998",
"amount": 150.50,
"payer": {
"name": "Your Company",
"document": "12345678000199",
"bankCode": "999",
"branch": "0001",
"accountNumber": "98765-4"
},
"payee": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"initiatedAt": "2025-12-29T21:14:33.900Z"
}
}

9. fee.charged

当账户被收取银行费用时发送(例如按笔收取的 PIX 手续费)。

data 结构:

  • amount:收取的费用金额。
  • currency:币种。
  • feeServiceType:触发收费的操作类型(例如 PIX_OUTPIX_IN)。
  • description:费用描述。
  • chargedAt:收费时间戳。

完整示例:

{
"id": "evt_fee_123",
"type": "fee.charged",
"occurredAt": "2026-02-14T20:30:43.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"amount": 2.99,
"feeServiceType": "PIX_OUT",
"description": "Banking Fee",
"chargedAt": "2026-02-14T20:30:43.000Z"
}
}

10. pix.med.opened

当新的 MED(特别退回机制)争议针对某笔交易发起时发送。

data 结构:

  • endToEndId:争议中的交易 ID。
  • identifier:关联标识符。
  • qrcodeId:QR Code ID(如适用)。
  • amount:争议金额。
  • currency:币种。
  • claimant:提出索赔的人员详情(姓名、证件、银行、支行、账户)。
  • openedAt:MED 发起日期。
  • deadlineAt:响应截止日期。

完整示例:

{
"id": "evt_med_123",
"type": "pix.med.opened",
"occurredAt": "2025-12-29T21:14:33.912Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEndId": "E0000000020251229211433912",
"identifier": "tx-med-001",
"qrcodeId": "qr_abc123",
"amount": 150.50,
"claimant": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"openedAt": "2025-12-29T21:14:33.900Z",
"deadlineAt": "2026-01-05T21:14:33.900Z"
}
}

10. pix.med.updated

当 MED(特别退回机制)争议更新(状态变更、新信息、解决方案)时发送。

data 结构:

  • endToEndId:争议中的交易 ID。
  • identifier:关联标识符。
  • qrcodeId:QR Code ID(如适用)。
  • amount:争议金额。
  • currency:币种。
  • status:当前 MED 状态(OPENCLOSEDAGREEDDISAGREED)。
  • result:争议结果(如已解决)。
  • claimant:提出索赔的人员详情。
  • openedAt:MED 发起日期。
  • updatedAt:最后更新日期。

完整示例:

{
"id": "evt_med_456",
"type": "pix.med.updated",
"occurredAt": "2025-12-30T15:20:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"endToEndId": "E0000000020251229211433912",
"identifier": "tx-med-001",
"qrcodeId": "qr_abc123",
"amount": 150.50,
"status": "CLOSED",
"result": "AGREED",
"claimant": {
"name": "John Smith",
"document": "12345678900",
"bankCode": "001",
"branch": "0001",
"accountNumber": "12345-6"
},
"openedAt": "2025-12-29T21:14:33.900Z",
"updatedAt": "2025-12-30T15:20:00.000Z"
}
}

9.1. fee.refunded

当银行退还之前收取的费用时发送(返现、调整等)。结构与 fee.charged 相同,kind="REFUNDED"。资金已经入账。

{
"id": "evt_fee_456",
"type": "fee.refunded",
"occurredAt": "2026-02-15T13:42:11.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"transactionId": "fee-7c2a...11",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 2.99,
"description": "Bank fee refund",
"feeServiceType": "PIX",
"originalRef": "fee-9c1f...e2",
"occurredAt": "2026-02-15T13:42:11.000Z",
"status": "SUCCESS",
"kind": "REFUNDED"
}
}

11. transfer.internal.in

发送到内部转账的收款账户。direction="IN"amount 为 BRL 正值。counterparty 携带对方账户信息,isLocal=true 表示对方也是 CorpX 账户。

{
"id": "evt_int_in_001",
"type": "transfer.internal.in",
"occurredAt": "2026-04-23T14:21:05.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"data": {
"transactionId": "internal-in-9d4a5b7c-1234-4abc-9876-abc123456789",
"accountId": "773107de-139e-48d1-9462-f4e88f251891",
"tenantId": "tenant-acme",
"direction": "IN",
"amount": 500.00,
"description": "Salary payment",
"occurredAt": "2026-04-23T14:21:05.000Z",
"status": "SUCCESS",
"counterparty": {
"partnerAccountId": "a1b2c3d4-...",
"name": "EMPRESA ORIGEM LTDA",
"document": "12345678000199",
"isLocal": false
}
}
}

12. transfer.internal.out

发送到内部转账的发款账户。结构与 transfer.internal.in 相同,direction="OUT"。当转账由集成方通过 POST /v1/accounts/{accountId}/transfers/internal 发起时,原始 identifier 会回显在 data.identifier

{
"id": "evt_int_out_001",
"type": "transfer.internal.out",
"occurredAt": "2026-04-23T14:21:05.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"data": {
"transactionId": "internal-out-9d4a5b7c-1234-4abc-9876-abc123456789",
"accountId": "a1b2c3d4-aaaa-bbbb-cccc-111122223333",
"tenantId": "tenant-acme",
"direction": "OUT",
"amount": 500.00,
"description": "Salary payment",
"occurredAt": "2026-04-23T14:21:05.000Z",
"status": "SUCCESS",
"counterparty": {
"partnerAccountId": "b2c3d4e5-...",
"name": "MARIA SILVA",
"document": "12345678900",
"isLocal": false
}
}
}

13. pix.out.timeout

当合作方调用成功但响应超时时发送。这不是失败 — 请先查看对账单后再使用新的 idempotency-key 重试。使用相同的 key 重试是安全的,最终结果可用时会返回。

{
"id": "evt_pix_out_timeout_001",
"type": "pix.out.timeout",
"occurredAt": "2026-05-04T10:42:11.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"transactionId": "tx_38a1b2c3",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"idempotencyKey": "client-key-789",
"endToEndId": "E0000000020260504104211",
"amount": 250.00,
"status": "TIMEOUT",
"warning": "调用合作方成功但响应超时。请先在对账单中确认,再使用新的 idempotency-key 重试;使用相同 key 是安全的。"
}
}

14. pix.refund.received

当 PIX out 的收款方主动退回款项时发送(与我方未发起退款的情况)。与 pix.refund.completed 不同——后者确认的是我们发起的退款。

data 结构:

  • transactionId:收到退款的确定性 ID(pix-refund-received-{refundEndToEnd})。
  • refundEndToEnd:退款的 D-code(BACEN)。
  • originalEndToEnd:被退回的原 PIX out 的 E-code。
  • originalIdentifier:原 PIX out 的 identifier(创建支付时发送的值),如有则返回。
  • accountId / tenantId:收到退款的账户。
  • amount:退回金额。
  • description:合作方描述。
  • receivedAt:退款时间戳。
  • payer:退回方(对手方 / 原 PIX out 收款人):姓名、证件、银行、支行、账号。
  • payee:收到退款的账户(我方账户 / 原 PIX out 付款人):姓名、证件、银行、支行、账号。
  • status:始终为 "SUCCESS"
{
"id": "evt_pix_refund_recv_001",
"type": "pix.refund.received",
"occurredAt": "2026-05-04T11:11:43.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"transactionId": "pix-refund-received-D2026050420260504...",
"refundEndToEnd": "D2026050420260504000000001",
"originalEndToEnd": "E0000000020260503100000001",
"originalIdentifier": "client-refund-key-001",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 320.00,
"description": "PIX refund",
"receivedAt": "2026-05-04T11:11:43.000Z",
"payer": {
"name": "João Silva",
"document": "12345678901",
"bankCode": "341",
"bankIspb": "60701190",
"branch": "0001",
"accountNumber": "12345-6"
},
"payee": {
"name": "Acme Corp LTDA",
"document": "12345678000199",
"bankCode": "681",
"bankIspb": "50871921",
"branch": "0001",
"accountNumber": "98765-4"
},
"status": "SUCCESS"
}
}

15. qrcode.expired

动态二维码在 expiration 配置的时间内未被支付而过期时发送。

{
"id": "evt_qrcode_exp_001",
"type": "qrcode.expired",
"occurredAt": "2026-05-04T12:00:00.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"txid": "qr_abc123",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 99.90,
"expiredAt": "2026-05-04T12:00:00.000Z",
"status": "EXPIRED"
}
}

16. qrcode.cancelled

集成方在支付前通过 DELETE /v1/qrcodes/{txid} 显式取消动态二维码时发送。

{
"id": "evt_qrcode_cancel_001",
"type": "qrcode.cancelled",
"occurredAt": "2026-05-04T11:45:30.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"txid": "qr_abc123",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 99.90,
"cancelledAt": "2026-05-04T11:45:30.000Z",
"status": "CANCELLED"
}
}

17. boleto.paid

通过 POST /v1/accounts/{accountId}/boleto/pay 支付的 boleto 被发卡银行确认时发送。

{
"id": "evt_boleto_paid_001",
"type": "boleto.paid",
"occurredAt": "2026-05-04T15:00:11.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"transactionId": "bol_aabbccdd",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 1234.50,
"digitableLine": "00190.00009 03450.000004 47018.500003 1 88880000123450",
"paidAt": "2026-05-04T15:00:11.000Z",
"status": "SUCCESS"
}
}

18. boleto.failed

发卡银行拒绝支付时发送。data.error 包含原因。

{
"id": "evt_boleto_failed_001",
"type": "boleto.failed",
"occurredAt": "2026-05-04T15:00:11.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-acme",
"accountId": "acc_123456",
"data": {
"transactionId": "bol_eeffgghh",
"accountId": "acc_123456",
"tenantId": "tenant-acme",
"amount": 1234.50,
"digitableLine": "00190.00009 03450.000004 47018.500003 1 88880000123450",
"status": "FAILED",
"error": {
"code": "boleto_expired",
"message": "Boleto 已过期 — 请重新出票"
}
}
}

19–22. ted.out.*ted.in.received

TED 事件遵循与 boleto.* 相同的信封结构。完整的负载示例(ted.out.requestedted.out.confirmedted.out.failedted.in.received)参见 TED 指南

已弃用别名ted.paymentted.out.confirmed 一起以相同负载分发,仅为向后兼容性保留。将在 v3.0 中移除。

最佳实践

  • 幂等性:您的应用应做好多次接收同一 webhook 的准备。使用信封中的 id 避免重复处理。
  • 快速响应:收到 webhook 后立即返回 200 OK 状态码,并异步处理业务逻辑以避免超时。
  • 时间戳验证:检查 occurredAt 是否过旧(建议 5 分钟容差),以防止重放攻击。