Webhooks
Saq 的 webhook 系统实时发送您交易状态变更
的通知。当您创建一笔交易
并提供 callbackUrl 时,我们的系统会在每次状态变更时
向该 URL 发送更新。
什么是 webhook(callback)
webhook(也称为 callback)是一个 POST 请求,当某些事件发生时 由 Saq 发送到您的服务器。与普通 API(您调用 Saq)相反,这里是反向的:Saq 调用您。
设想一笔 Pix 收款。您创建了订单,向客户展示了 QR Code,现在需要知道客户何时付款。有两种方式:
- 轮询,每隔 X 秒询问一次"付了吗?付了吗?"(成本高、慢、不必要)。
- webhook,让 Saq 在付款到账时通知您(即时、高效、推荐)。
如何配置
没有单独的"注册 webhook"endpoint。URL 在 每次创建交易时 通过 body 中的 callbackUrl 字段提供:
{
"amount": 99.90,
"callbackUrl": "https://seusite.com.br/webhooks/saq",
"clientReference": "pedido-2025-001"
}Saq 会在 该交易每次状态变更时(PENDING → COMPLETED、COMPLETED → REFUNDED 等)向该 URL 发送 callback。
在您的服务器上创建一个公开 endpoint
任何可通过互联网访问、接受 JSON POST 请求的地址。例如:https://seusite.com.br/webhooks/saq、https://api.suaempresa.com/saq/callback。
本地开发期间,使用 ngrok 或 Cloudflare Tunnel 等隧道工具暴露 localhost。
创建交易时传入 URL
在每个 POST /pix、POST /withdraw、POST /internal-transfer 中,都包含 callbackUrl 字段。所有交易可使用同一个 URL。
实现 handler
接收 POST、读取 JSON、处理并在 5 秒内返回 2xx。请参见 接收 Pix · 步骤 3 中的示例。
Saq 发送的 POST 必须携带的 header:Content-Type: application/json。
重试机制
Saq 的 webhook 具有强大的重试机制,即使在临时故障时 也能确保送达。Saq 会以指数退避加抖动的方式 最多重发 72 次 相同的 callback,从而更好地分散 负载并避免请求峰值。
**响应时间:**webhook 必须在 5 秒内 返回 HTTP 200 OK。
超过该时间,系统会判定为超时
并启动重试流程。
安全
为保证完整性与安全性,请 限制访问 您的 webhook endpoint。请向支持团队索取 Saq 的 官方 IP,并仅接受来自该来源的 callback。
payload 字段
标识
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 交易 ID |
clientReference | string | 您提供的外部引用 |
virtualCount | string | 虚拟子账户(最长 50 字符)。在 callback 中返回,用于关联门店、分支或 marketplace。 |
callbackUrl | string | 用于接收此 webhook 的 URL |
状态与金额
| 字段 | 类型 | 说明 |
|---|---|---|
status | string | PENDING、COMPLETED、CANCELED、WAITING_FOR_REFUND、REFUNDED、EXPIRED、ERROR |
type | string | DEPOSIT、WITHDRAW、INTERNAL_TRANSFER |
amount | number | 金额(BRL) |
serviceFeeCharged | number | 已收取的手续费 |
生成的收款(存款)
| 字段 | 类型 | 说明 |
|---|---|---|
qrCodeText | string | Pix 复制粘贴码 |
qrCodeUrl | string | QR Code 图片 URL |
qrCodeBase64 | string | Base64 格式的 QR Code 图片 |
generatedName | string | 引用名称 |
generatedDocument | string | CPF 或 CNPJ |
generatedEmail | string | 与交易关联的邮箱 |
付款方
| 字段 | 类型 | 说明 |
|---|---|---|
payerName | string | 付款方姓名 |
payerDocument | string | 付款方证件号 |
payerInstitutionIspb | string | 付款方银行的 ISPB |
payerInstitutionName | string | 付款方银行名称 |
payerAccountNumber | string | 付款方的 Saq 账户(6 位)。仅在内部转账中出现。 |
收款方
| 字段 | 类型 | 说明 |
|---|---|---|
receiverName | string | 收款方姓名 |
receiverDocument | string | 收款方证件号 |
receiverInstitutionIspb | string | 收款方银行的 ISPB |
receiverInstitutionName | string | 收款方银行名称 |
receiverAccountNumber | string | 收款方的 Saq 账户(6 位)。仅在内部转账中出现。 |
通过 Pix 密钥提现
| 字段 | 类型 | 说明 |
|---|---|---|
withdrawPixKey | string | 提现使用的 Pix 密钥 |
withdrawPixType | string | cpf、cnpj、phone、email、evp |
清算与退款
| 字段 | 类型 | 说明 |
|---|---|---|
endToEndId | string | Pix 的 EndToEnd ID |
paidAt | string | 支付时间戳(ISO 8601) |
cancellationReason | string | 取消原因 |
refundEndToEndId | string | 退款的 EndToEnd ID |
refundAmount | string | 退款金额 |
refundStatus | string | PENDING、COMPLETED、CANCELED |
refundReason | string | 退款原因 |
refundDescription | string | 退款描述 |
refundedAt | string | 退款时间戳(ISO 8601) |
时间戳
| 字段 | 类型 | 说明 |
|---|---|---|
createdAt | string | 创建时间戳(ISO 8601) |
updatedAt | string | 更新时间戳(ISO 8601) |
违规(Pix 争议)
| 字段 | 类型 | 说明 |
|---|---|---|
infraction | object | 违规开启时的详情(参见 MED) |
最佳实践
- 快速响应:在 5 秒内返回
2xx。重处理交给 队列/worker,不要放在 handler 中。 - 幂等性:存储
id+status以进行去重。同一个 callback 可能会到达多次(重试、连续状态变更)。 - 使用
clientReference:创建交易时传入 外部标识。会在 callback 中返回,便于与您的订单关联。 - 按 IP 限制:仅接受来自 Saq 官方 IP 的 callback。
查询与重发
API 暴露了已发送 callback 的完整列表:
GET /user/callbacks,分页列表GET /user/callbacks/{id},详情POST /user/callbacks/resend/{transactionId},重发某笔交易的 callbackPOST /user/callbacks/resend,批量重发
Infrações (MED)
O MED é o processo do Bacen para contestar Pix em casos de fraude ou erro do pagador. Quando uma cobrança recebida vira disputa, a Saq cria uma infração e você tem prazo curto para responder com defesa.
Boas práticas
Padrões testados em produção que separam uma integração que dura uma semana de uma que aguenta produção. Idempotência, multi-tenant, callbacks, paginação, dinheiro, segurança, tratamento de erros e checklist final.