从 v1 迁移 — 完整参考
如需 2 分钟版本,请见从 v1 迁移 — 快速版。
本文档面向审计迁移的开发者、运维团队以及边缘场景。列出约 75 个面向集成方的路由及其在 v2 上的行为。
1. 认证
之前(v1)
TOKEN_URL="https://corpx-{env}.auth.sa-east-1.amazoncognito.com/oauth2/token"
curl -X POST "$TOKEN_URL" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials&scope=api/full"
现在(v2)
TOKEN_URL="https://auth.api.corpx.com/oauth2/token"
curl -X POST "$TOKEN_URL" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d "grant_type=client_credentials&scope=api2/read api2/write"
差异:
- Token URL 变了(经过我们的 CloudFront)。
scope:api/full→api2/read api2/write。- JWT TTL:1 小时(与 v1 相同)。
Idempotency-Key:v2 上可选(缺失时自动生成;仍建议你自己传以便于重试控制)。X-Tenant-Id:所有/v1/*请求必填(GET /v1/me与健康检查除外);路径含accountId时必须与账户租户一致。
2. 已废弃端点(在 2026-11-21 之前仍可用)
v1 上存在但未保留在 v2 规范形态中的 4 条路径,已作为已废弃别名重新启用。它们仍正常响应 — 仅在响应中附加 3 个警示响应头:
Deprecation: true
Sunset: Sat, 21 Nov 2026 00:00:00 GMT
Link: </v1/accounts/.../新路径>; rel="successor-version"
这些响应头遵循 RFC 8594(Deprecation)和 RFC 9745(Sunset)。客户端可以自动检测它们以提醒团队。
预定下线日期:2026-11-21。 该日期之后这些路由将开始返回 410 Gone。
| 已废弃路由(仍可用) | 规范替代 |
|---|---|
GET /v1/accounts/{id}/pix/payments/{paymentId} | GET /v1/accounts/{id}/pix/payments/lookup?identifier=... |
GET /v1/accounts/{id}/payments/{paymentId}(无 /pix/ 别名) | GET /v1/accounts/{id}/pix/payments/lookup?identifier=... |
GET /v1/accounts/{id}/pix/qr-code(无 /lookup) | GET /v1/accounts/{id}/pix/qr-code/lookup?identifier=... |
POST /v1/accounts/{id}/pix/out/qrcode(无连字符) | POST /v1/accounts/{id}/pix/out/qr-code |
这些路由不再出现在 OpenAPI 和 Postman 集合中 — 仅在此处记录以便你有时间迁移。新集成请直接使用规范替代。
3. 移除的端点(7 条路由 — 返回 404)
| v1 路由(已移除) | 替代方案 |
|---|---|
POST /v1/webhooks/replay | 对账单短窗轮询 |
GET /v1/integrator/webhooks | 使用 GET /v1/webhooks |
GET /v1/integrator/webhooks/{id}/deliveries | 无替代 — 如有依赖请联系支持 |
POST /v1/integrator/events/replay | 无替代 |
POST /v1/integrator/events/replay/batch | 无替代 |
POST /v1/accounts/{id}/pix/med/{medId}/send | 使用 /decide(但 MED 当前为 503) |
POST /v1/accounts/{id}/pix/med/{medId}/response | 使用 /answer(但 MED 当前为 503) |
GET /v1/health 在 v2 上仍然存在。我们额外添加了 GET /health 别名(不含 /v1),方便外部健康检查 — 你无需修改任何内容。
4. 行为变化的端点
路径相同、方法相同,但行为或 JSON 结构不同。
4.1 Statement — 缓存 → 实时(payer/payee 字段精简)
GET /v1/accounts/{id}/statement
v1: 读取由 webhook 填充的本地缓存(DynamoDB)。延迟约 50ms;item 中包含 tariff_ref 与翻译后的标签。每行都有完整的 payer.{bankCode,bankIspb,branch,account,pixKey,...} 与 beneficiary.{...},因为它们由 webhook 拼装而成(webhook 携带对手方所有银行字段)。
v2: 请求时直接调用清算银行。延迟约 500ms-1.5s;不再有派生的 tariff_ref(手续费作为对账单中的独立条目);新响应头 X-Source: live。每次查询最大窗口:31 天。
每行 shape 的变化
v2 将对手方对象标准化为 name + document,再加上我方(清算银行 = MT Bank)的银行信息。对手方其余银行字段(branch、account、pixKey 等)不再出现在对账单的行项中,因为清算银行的对账单端点不暴露这些字段。
v1(旧版,来自 webhook 缓存):
{
"amount": -100.00,
"direction": "OUT",
"endToEndId": "E...",
"payer": { "name": "...", "document": "...", "bankCode": "681", "bankIspb": "50871921", "branch": "...", "account": "...", "pixKey": "..." },
"beneficiary":{ "name": "...", "document": "...", "bankCode": "001", "bankIspb": "00000000", "branch": "...", "account": "...", "pixKey": "..." }
}
v2(实时,来自清算银行):
{
"amount": -100.00,
"direction": "OUT",
"endToEndId": "E...",
"payer": { "name": "我的公司有限公司", "document": "12345678000190", "bankCode": "681", "bankIspb": "50871921", "bankName": "MT Instituição de Pagamentos" },
"payee": { "name": "供应商 XYZ", "document": "98765432000110" },
"counterParty": { "name": "供应商 XYZ", "document": "98765432000110" }
}
v2 shape 说明:
payer/payee对由该行的direction决定:direction=IN:payer= 对手方(付款给我们的人);payee= 我方账户;direction=OUT:payer= 我方账户;payee= 对手方(我们付款给的人)。
- 我方 端始终带
name(持有人)、document(CPF/CNPJ)以及清算银行标识(bankCode、bankIspb、bankName)。 - 对手方 端始终只带
name+document。可选字段(bankCode、bankIspb、branch、account、pixKey、accountType、bankName)在为空时被省略 —— v2 的partyToDTO不会输出空字符串的 key。 counterParty(包含对手方name+document的额外对象)继续保留,方便无需检查direction直接查找。- 移除了
authorizationCode字段(清算银行的 API 在对账单中不返回该字段;即便 v1 在 live fallback 下也始终为空)。
如何获取完整的对手方银行 payload
如果你的集成需要对手方的 branch/account/pixKey/bankCode,请使用下列任一替代方案(它们都返回完整 payload,因为来源于专门的 PIX 端点,而不是对账单):
- outbound webhook:
pix.in.completed、pix.out.completed、pix.refund.completed、qrcode.paid—— CorpX 信封中的payer/payee包含所有银行字段。 - 单笔支付查询:
GET /v1/accounts/{id}/pix/payments/lookup?endToEndId=...—— 返回完整交易对象(与 webhook 相同)。 - 二维码:
GET /v1/accounts/{id}/pix/qr-code/lookup?identifier=...—— 对于已支付的二维码,包含payer与payment.endToEnd。
如果你的集成依赖积极的对账单轮询,请改用 webhook:
pix.in.received:收到 PIXpix.out.confirmed:PIX out 完成boleto.paid/boleto.failedqrcode.paid
同样的影响适用于其他原先从相同缓存读取的端点:
GET /v1/accounts/{id}/pix/transactionsGET /v1/accounts/{id}/pix/paymentsGET /v1/accounts/{id}/payments(别名)
它们现在都实时查询清算银行,没有本地缓存。
4.2 MED — 迁移期间 503
所有 /v1/accounts/{id}/pix/med/* 端点返回 503 service_temporarily_unavailable。计划在 v2.x 恢复。如切换时存在活跃 MED,我们团队将单独联系。
med.* webhook 同样暂停 — 此期间不发送任何争议事件。无需移除订阅;模块恢复时事件将自动恢复。
4.3 Boleto — 已激活
v1 上所有 boleto 端点(POST .../boleto/preview、POST .../boleto/pay、GET .../boleto/payments/{id})返回 503。v2 已激活。见 Cash Out 指南。
4.4 PIX out — 同步 vs 异步(并非“全部异步”)
v2 保留与 v1 相同的划分:
| 路由 | 模式 | HTTP 响应 |
|---|---|---|
POST .../pix/out | 同步 | 等待 workflow 最多约 25 秒。及时完成:200 含最终状态(APPROVED、FAILED→422 等)及 endToEndId(如有)。超时:202 + status: PENDING + warning,再查 lookup/webhook。 |
POST .../pix/out/qr-code | 同步 | 同 /pix/out(约 25s)。 |
POST .../pix/out/bank-account | 同步 | 同上。 |
POST .../pix/out/refund | 同步 | 同上。 |
POST .../pix/out/async | 异步 | 立即 202,含 {paymentId, workflowId, idempotencyKey, identifier} — 最终结果靠 webhook 或 GET .../pix/payments/lookup?identifier=...。 |
POST .../pix/out/bank-account/async | 异步 | 立即 202(同 /async)。 |
POST .../pix/out/bigpix(及 bank-account/bigpix) | 异步 | 立即 202(批次;服务端分块不变)。 |
内部变化(不强制改调 async): 编排改为 Temporal,但已使用 POST .../pix/out(无 /async)的集成方仍为同步路径。仅在需要高吞吐或不想占用 HTTP 连接约 25s 时再改用 /async。
幂等: 相同 Idempotency-Key 重试会复用进行中的 paymentId/workflow;FAILED 后换新 key 可再试(见 Cash Out)。
4.5 X-CF-Origin-Verify
v2 仅接受来自 CloudFront 的请求。直接访问 execute-api 返回 403。请始终使用 https://tenant.api.corpx.com/v1。
4.6 临时暂停的 webhook — fee.*、med.*、edi.*
迁移期间,3 个事件家族不发送:
| 家族 | 状态 | 如何继续看到数据 |
|---|---|---|
fee.*(fee.charged、fee.refunded 等) | 暂停 | 手续费作为对账单中的独立条目出现(GET /v1/accounts/{id}/statement)。查找 type=internal-transfer、identifier=fee-{slug}-{operationReferenceId} 指向 CORPX_FEE_ACCOUNT_ID 的条目。 |
med.*(med.opened、med.answered 等) | 暂停 | 整个 MED 模块离线(见 §4.2)。 |
edi.*(CNAB/EDI 批文件事件) | 暂停 | 文件仍在生成,但 webhook 通知暂停。请使用 CNAB 批次 GET 接口跟踪。 |
对你意味着什么:
- 这些事件的订阅可以保留 — 恢复时会自动恢复发送。
- 如你的对账依赖这些事件,请暂时改为对账单轮询(清算银行的查询为实时,无缓存延迟)。
分阶段恢复计划:
fee.*— no-cache 重构稳定后的下一个次版本。med.*— 与 v2.x 上 MED 模块的恢复一同。edi.*— 待定;取决于新的批次管道。
4.7 交易 ↔ 手续费的自动对账 — 暂停
v1: 交易对象包含 fee: { amount, ... } 字段,将每笔 PIX/boleto 与其处理费配对。
v2: 该字段临时移除。对账在客户端通过交叉引用 identifier 完成:
- 主交易:
identifier = <你的 identifier>(或自动生成) - 匹配手续费:
identifier = fee-{slug}-{operationReferenceId},在同一时间窗内从CORPX_FEE_ACCOUNT_ID借记
通过对账单对账:
GET /v1/accounts/{accountId}/statement?startDate=2026-05-21&endDate=2026-05-21
过滤 identifier 以 fee- 开头的条目,通过嵌入的 operationReferenceId 与主交易关联。
no-cache 重构稳定后,交易对象上的 fee 字段会回归。该回归不计划修改载荷 — 仅是字段重新出现。
4.8 Internal transfer by-bank-account — 可选额外字段
POST /v1/accounts/{id}/transfers/internal/by-bank-account
v2 接受两个可选额外字段:holderDocument 和 holderName。当前清算银行需要这些数据;当客户端未发送时,后端会自动查找。非破坏性 — 继续只发送 {branch, accountNumber, value, ...} 的客户端可正常工作。
4.9 PIX QR-code — 响应已扁平化(JSON 破坏性变更)
在完整表(§6)中,这些端点标记为 body-diff,而非 identical:路径相同,但成功响应 JSON 已变。使用 response.data.payload 或 data.location 的代码会失败——包括 POST .../pix/qr-code/dynamic。
影响 5 个 QR-code 端点:
POST /v1/accounts/{id}/pix/qr-code/dynamicPOST /v1/accounts/{id}/pix/qr-code/staticGET /v1/accounts/{id}/pix/qr-code/lookup(以及已废弃别名GET /v1/accounts/{id}/pix/qr-code)DELETE /v1/accounts/{id}/pix/qr-code
v1: Finaya 风格的信封:
{
"statusCode": 200,
"title": "...",
"type": "...",
"message": "...",
"data": {
"txid": "ABC123",
"payload": "00020126...",
"location": "https://qr.mtbank.com.br/cob/...",
"...": "..."
}
}
v2: 规范扁平结构,无信封:
{
"txid": "ABC123",
"emv": "00020126...",
"type": "dynamic",
"status": "ACTIVE",
"value": 12.34,
"message": "Charge X",
"identifier": "abc123",
"expiresAt": "2026-12-31T23:59:59Z",
"createdAt": "2026-05-21T20:00:00Z"
}
字段映射:
| v1(信封) | v2(扁平) | 备注 |
|---|---|---|
data.txid | txid | 不变 |
data.payload | emv | 同一段 BRcode/EMV 字符串 |
data.location | (已移除) | 在客户端从 emv 渲染二维码 |
statusCode、title、type、message(信封) | (已移除) | 由规范字段 type、status、value、identifier、expiresAt、createdAt 替代 |
HTTP 状态码: v2 创建时返回 201 Created(POST)。GET 仍为 200。
最小迁移示例:
- const emv = response.data.payload;
+ const emv = response.emv;
- const qrUrl = response.data.location;
+ // 没有原生等价字段。请使用 qrcode-svg / qrcode.js 等库在客户端渲染 EMV,
+ // 或将其托管到自己的 CDN 以获取公开 URL。
如果移除 location 对你是阻塞性的变更,请联系支持 — 我们可以评估通过缓存的 EMV 生成 CDN URL 来重新引入该字段。
5. 新增端点
| 端点 | 用途 |
|---|---|
GET /v1/me | 当前认证 client_id 的身份信息(便于调试) |
GET /v1/transactions/{id}/timeline | 单笔交易的详细时间线(路径中不含 accountId) |
GET /v1/accounts/{id}/pix/out/bigpix/{batchId} | BigPix 批次聚合状态 |
GET /health | /v1/health 的别名(不含 /v1 前缀) |
6. 完整表
状态说明:
- identical:路径与成功响应 JSON 一致。解析逻辑无需修改。
- body-diff:路径相同,但响应或行为不同。QR-code 行(§4.9)为 JSON 破坏性变更(无
data信封)。 - deprecated:在 2026-11-21 之前仍可用,响应附带
Deprecation: true头。请在下线前迁移到规范替代。 - v1-only:仅 v1 存在的路由;在 v2 上返回 404。
- v2-only:新增路由;仅 v2 存在。
| 端点 | v2 状态 | 备注 |
|---|---|---|
GET /v1/health | identical | 也接受 GET /health |
GET /v1/accreditations/pf | identical | — |
POST /v1/accreditations/pf | identical | CNPJ 的 simplified tier 请求体可能需要 Agreement |
PUT /v1/accreditations/pf | identical | — |
GET /v1/accreditations/pj | identical | — |
POST /v1/accreditations/pj | identical | 同上 |
PUT /v1/accreditations/pj | identical | — |
GET /v1/accounts/{id}/balance | identical | — |
GET /v1/accounts/{id}/statement | body-diff | 实时(无缓存);见 §4.1 |
GET /v1/accounts/{id}/transactions/timeline | identical | — |
GET /v1/transactions/{id}/timeline | v2-only | 新增 |
POST /v1/accounts/{id}/locked-balance/lock | removed (2026-05) | v2 不再维护本地 hold。/balance.locked 只反映 MT 端 blocked。 |
POST /v1/accounts/{id}/locked-balance/unlock | removed (2026-05) | 同上 |
GET /v1/accounts/{id}/pix/limits | identical | — |
PATCH /v1/accounts/{id}/pix/limits | identical | — |
POST /v1/accounts/{id}/pix/out | identical | 同步(约 25s):完成时 200/422;超时 202+warning。§4.4 |
POST /v1/accounts/{id}/pix/out/async | identical | 异步: 立即 202。§4.4 |
POST /v1/accounts/{id}/pix/out/bigpix | identical | 单笔请求体;服务端分块;立即 202(异步)。§4.4 |
GET /v1/accounts/{id}/pix/out/bigpix/{batchId} | v2-only | 批次聚合状态 |
POST /v1/accounts/{id}/pix/out/bank-account | identical | 同步(约 25s)。§4.4 |
POST /v1/accounts/{id}/pix/out/bank-account/async | identical | 异步: 立即 202。§4.4 |
POST /v1/accounts/{id}/pix/out/bank-account/bigpix | identical | 异步: 立即 202(批次)。§4.4 |
POST /v1/accounts/{id}/pix/out/qr-code | identical | 同步(约 25s),同 /pix/out。§4.4 |
POST /v1/accounts/{id}/pix/out/qr-code/decode | identical | — |
POST /v1/accounts/{id}/pix/out/qrcode(无连字符别名) | deprecated | 2026-11-21 下线。使用 /pix/out/qr-code |
POST /v1/accounts/{id}/pix/out/refund | identical | 同步(约 25s)。§4.4 |
GET /v1/accounts/{id}/pix/transactions | body-diff | 实时 |
GET /v1/accounts/{id}/pix/payments | body-diff | 实时 |
GET /v1/accounts/{id}/pix/payments/{paymentId} | deprecated | 2026-11-21 下线。使用 /pix/payments/lookup?identifier= |
GET /v1/accounts/{id}/pix/payments/lookup | identical | — |
GET /v1/accounts/{id}/payments(别名) | body-diff | 实时 |
GET /v1/accounts/{id}/payments/{paymentId}(别名) | deprecated | 2026-11-21 下线。使用 /pix/payments/lookup?identifier= |
POST /v1/accounts/{id}/boleto/preview | body-diff | 503 → 200(v2 已激活 boleto) |
POST /v1/accounts/{id}/boleto/pay | body-diff | 503 → 200 |
GET /v1/accounts/{id}/boleto/payments/{paymentId} | body-diff | 503 → 200 |
POST /v1/accounts/{id}/pix/qr-code/static | body-diff | 破坏性: 无信封;data.payload→emv;无 data.location。§4.9 |
POST /v1/accounts/{id}/pix/qr-code/dynamic | body-diff | 破坏性: 无信封;data.payload→emv;无 data.location。§4.9 |
GET /v1/accounts/{id}/pix/qr-code(无 /lookup) | deprecated | 2026-11-21 下线。使用 /pix/qr-code/lookup?identifier=。响应亦为 body-diff(§4.9) |
GET /v1/accounts/{id}/pix/qr-code/lookup | body-diff | 破坏性: 与 POST 相同的扁平结构。§4.9 |
DELETE /v1/accounts/{id}/pix/qr-code | body-diff | 破坏性: 扁平响应。§4.9 |
GET /v1/accounts/{id}/pix/qr-codes | identical | 分页列表 — 不同于 POST dynamic 的响应契约(§4.9) |
GET /v1/accounts/{id}/pix/qr-codes/stats | identical | — |
GET /v1/accounts/{id}/pix/keys | identical | — |
POST /v1/accounts/{id}/pix/keys | identical | — |
DELETE /v1/accounts/{id}/pix/keys/{pixKey} | identical | — |
GET /v1/accounts/{id}/pix/key/{pixKey} | identical | DICT 查询 |
GET /v1/accounts/{id}/pix/med | body-diff | 503 占位;见 §4.2 |
POST /v1/accounts/{id}/pix/med/{medId}/answer | body-diff | 503 占位 |
POST /v1/accounts/{id}/pix/med/{medId}/decide | body-diff | 503 占位 |
POST /v1/accounts/{id}/pix/med/{medId}/evidence/upload-url | body-diff | 503 占位 |
POST /v1/accounts/{id}/pix/med/{medId}/evidence/add | body-diff | 503 占位 |
POST /v1/accounts/{id}/pix/med/{medId}/evidence/download | body-diff | 503 占位 |
POST /v1/accounts/{id}/pix/med/{medId}/send | v1-only | 使用 /decide(当前 503) |
POST /v1/accounts/{id}/pix/med/{id}/response | v1-only | 使用 /answer(当前 503) |
POST /v1/accounts/{id}/transfers/internal | identical | — |
POST /v1/accounts/{id}/transfers/internal/by-bank-account | identical | 接受可选额外字段(holderDocument、holderName);见 §4.8 |
POST /v1/accounts/{id}/transfers/internal/by-document | identical | — |
GET /v1/accounts/{id}/transfers/internal/lookup/{document} | identical | — |
POST /v1/accounts/{id}/exports | identical | — |
GET /v1/accounts/{id}/exports | identical | — |
GET /v1/accounts/{id}/exports/{exportId}/download | identical | — |
GET /v1/me | v2-only | client_id 调试 |
GET /v1/webhooks | identical | — |
POST /v1/webhooks | identical | — |
PUT /v1/webhooks/{subscriptionId} | identical | — |
DELETE /v1/webhooks/{subscriptionId} | identical | — |
GET /v1/webhooks/events | identical | 目录 |
POST /v1/webhooks/replay | v1-only | 已移除 |
GET /v1/integrator/webhooks | v1-only | 使用 GET /v1/webhooks |
GET /v1/integrator/webhooks/{id}/deliveries | v1-only | 无替代 |
POST /v1/integrator/events/replay | v1-only | 无替代 |
POST /v1/integrator/events/replay/batch | v1-only | 无替代 |
GET /v1/security/ip-allowlist | identical | — |
PUT /v1/security/ip-allowlist | identical | — |
GET /v1/security/ip-allowlist/audit | identical | — |
汇总: 46 个 identical、5 个 body-diff(PIX QR-code — JSON 扁平化,§4.9)、12 个 body-diff/行为类(statement live、MED 占位、boleto 503→200 等)、4 个 deprecated(别名,2026-11-21 下线)、7 个 v1-only(已移除)、3 个 v2-only(新增)。
7. Account ID 保留
你在所有路径与 webhook 中使用的 account_id 在切换前后完全相同。你不需要更新系统中保存的引用。它们仍然是 UUID。
内部变化(对你透明):
- 清算银行的标识符是新的 — 你从未看到该字段。
- 与清算银行的认证机制变了 — 内部 handler。
8. 完整 FAQ
我的 webhook URL 需要改吗? 不需要。
HMAC 密钥变吗? 不变。
account_id 变吗? 不变。
如果出问题,可以回到 v1 吗? 切换后前 4 小时可以 — 我们有预演的回滚方案。之后旧基础设施会逐步下线。
旧 backoffice 保留多久? 切换后 30 天。
高频对账单轮询仍能工作吗? 能,但延迟更高(约 1s,相比旧缓存的 50ms),且每次查询最大窗口为 31 天。对于变化请优先用 webhook。
有新的限流吗?
保持与 v1 相同的每租户限制。如触及限制,返回 429 Too Many Requests 并附 Retry-After。
fee 字段会回到交易对象上吗?
会,在稳定后的下一个次版本。无载荷变化 — 仅字段重新出现。
fee.* / med.* / edi.* webhook 会回来吗?
会,分阶段:fee.* 在下一个次版本;med.* 与 v2.x 上 MED 模块的恢复一同;edi.* 待定。
支持
联系方式:suporte-api@corpx.com — 工作时间内 1 小时内回复。