Cash-Out 凭证
以结构化格式获取 PIX 交易凭证,数据已格式化用于向最终用户显示。
端点
GET /api/external/transactions/:id/receipt请求头
| 头 | 类型 | 必填 | 描述 |
|---|---|---|---|
Authorization | String | 是 | ApiKey {client_id}:{client_secret} |
路径参数
| 参数 | 类型 | 必填 | 描述 |
|---|---|---|---|
id | String | 是 | 交易 ID(transaction_id) |
可用性
凭证查询 transactions 表 — 仅对具有最终状态(settled 或 failed)的交易可用。仍在处理的交易(outbound_requests 中的 processing 状态,stage 1-2)在此返回 404;请先通过 GET /transactions/:id 查询并等待提升到 transactions 后再请求凭证。
已付款的 QR 显示在链接的真实交易的凭证中(不是 QR 本身)— 使用 webhook pix.charge.paid 或查询中返回的 transaction_id。
示例
curl -X GET https://api.owem.com.br/api/external/transactions/PIXOUT20260309a1b2c3d4e5f6/receipt \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"成功响应 -- 200
{
"worked": true,
"receipt": {
"transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
"end_to_end_id": "E37839059202603091530abcdef01",
"external_id": "order-9876",
"type": "pix",
"direction": "outbound",
"status": "settled",
"amount": 300000,
"amount_formatted": "R$ 30,00",
"fee_amount": 350,
"fee_formatted": "R$ 0,035",
"net_amount": 300350,
"description": "Pagamento fornecedor",
"counterparty_name": "Joao Silva",
"recipient_key": "12345678901",
"created_at": "2026-03-09T15:30:00Z",
"completed_at": "2026-03-09T15:30:02Z",
"institution": {
"name": "Owem Pay",
"cnpj": "37.839.059/0001-88",
"ispb": "37839059"
}
}
}凭证字段
receipt 对象包含正好 17 个字段(包括子对象 institution)。这是完整清单 — 此端点没有其他字段返回:
| # | 字段 | 类型 | 描述 |
|---|---|---|---|
| 1 | receipt.transaction_id | String | 交易唯一标识 |
| 2 | receipt.end_to_end_id | String | SPI/BACEN 的 End-to-End 标识 |
| 3 | receipt.external_id | String | 客户端在 cash-out 中提供的 external ID。未提供时或 external ID 未通过清理时为 null(最多 128 字符,仅 a-zA-Z0-9._:-) |
| 4 | receipt.type | String | 交易类型。观察到的值:pix(默认)、pix_return(退款)。遗留记录可能返回其他值(ted、tef 等)— 控制器对 t.type 执行 passthrough 而不过滤 |
| 5 | receipt.direction | String | 字段持久化在 transactions.direction 时为 outbound 或 inbound。当 nil 时,控制器回退到 Helpers.infer_direction/2,它在推断路径中仅返回 credit(目标账户是收款方)或 debit(目标账户是付款方)— 从不返回 inbound/outbound |
| 6 | receipt.status | String | 通过 Helpers.format_status/1 解析的交易状态。可能值:settled(正常)、pending(transactions.status=2)、failed(status=3)、completed(对 status=1 且 payment_status=nil 的记录的遗留回退)。参见 可能值 |
| 7 | receipt.amount | Integer | 值,以基础单位(÷ 10.000 得到雷亚尔)。300000 = R$ 30,00 |
| 8 | receipt.amount_formatted | String | 以雷亚尔格式化的值(R$ 30,00) |
| 9 | receipt.fee_amount | Integer | 手续费,以基础单位 |
| 10 | receipt.fee_formatted | String | 以雷亚尔格式化的手续费(适用时包括子分,例:R$ 0,035) |
| 11 | receipt.net_amount | Integer | 净额,以基础单位(回退 `t.net_amount |
| 12 | receipt.description | String | 转账描述 |
| 13 | receipt.counterparty_name | String | 对手方姓名(付款方或收款方,根据 direction) |
| 14 | receipt.recipient_key | String | 收款方的 PIX 密钥(仅出款) |
| 15 | receipt.created_at | String | 创建日期(ISO 8601,来自 t.started_at) |
| 16 | receipt.completed_at | String | 完成日期(ISO 8601,来自 t.finished_at) |
| 17 | receipt.institution | Object | 发行机构数据 — 带 name、cnpj(格式化 XX.XXX.XXX/XXXX-XX)和 ispb 的子对象 |
格式化字段
凭证包括 _formatted 字段,值已转换为雷亚尔(例:R$ 30,00、子分手续费为 R$ 0,035)。使用这些字段向用户显示。使用数字字段(amount、fee_amount、net_amount)进行计算。没有 net_amount_formatted — 从 amount_formatted + fee_formatted 派生显示。
凭证不返回对手方字段
此端点明确省略出现在其他查询中的以下字段(例:GET /transactions/:id、GET /transactions/e2e/:e2e_id、按 ID 查询 PIX IN):
payer_documentrecipient_documentpayer_ispbpayer_bank_name
如果您的集成基于 cash-in 示例假设了 /receipt 中的这些字段,它在运行时读取 undefined。要访问对手方完整数据(文档、ISPB、银行名称),请使用 GET /transactions/:id 或 GET /transactions/e2e/:e2e_id — 两者都使用 transactions 表(相同源),但通过 Helpers.format_external_transaction/1 暴露完整结构。
凭证 vs 按 ID 查询
端点 /receipt 和端点 GET /transactions/:id 使用相同源(transactions),但返回不同的结构:
/receipt(17 个字段):专注于显示 — 添加_formatted、institution,并省略上面列出的 4 个对手方字段。GET /transactions/:id("settled" 结构中 18 个字段):专注于集成 — 包括对账有用的完整对手方上下文(payer_document、recipient_document、payer_ispb、payer_bank_name、counterparty_name),并省略_formatted字段。
使用 /receipt 为最终用户生成 PDF/电子邮件/确认屏幕。使用 GET /transactions/:id 进行程序化集成和内部对账。
错误响应 -- 404
{
"worked": false,
"detail": "Transação não encontrada"
}