API 参考
本文完整列出所有公开的 Liqfy v1 端点。所有路径均相对于生产环境基础 URL —— https://api.liqfy.com.br/v1。(目前尚未提供专用的沙箱主机。)
每个请求都需在 Authorization: Bearer <key> 请求头中携带您的 API 密钥进行认证 —— Authorization: Bearer <LIQFY_API_KEY>(lq_test_*/lq_live_*)。为保持兼容,仍接受旧版 apikey: <key> 请求头。所有请求体和响应体均为 JSON。所有金额均为以最小货币单位表示的整数。
API 围绕以下几类资源组织:
- 收款(
/v1/charges)—— 创建和读取 Pix 收款:object: "charge"、ch_…id、Idempotency-Key请求头、pix块。所有集成都从这里开始。 - 钱包(
/v1/wallets)—— 您的账户余额。 - 支付操作(
/v1/payments)—— 针对收款的取消、统计、收据及其他操作,通过其原始 id(去掉ch_前缀)进行寻址。退款通过管理后台发起,而非通过本 API。 - Webhooks(
/v1/webhooks)—— 注册端点并查看投递记录。
#收款
/v1/charges。
公共契约参见 API 约定 §3。每个响应都由白名单序列化器构建 —— 内部 id、PSP 名称、成本或原始服务商负载都不会出现在此处。
#创建收款
POST /v1/charges —— Pix 优先的快捷方式:POST /v1/pix/charges 会在请求体中固定 payment_method: "pix"(覆盖您发送的任何值),并返回完全相同的 Charge。
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
Authorization | 是 | Bearer + 您的 API 密钥(lq_test_* / lq_live_*)。仍接受旧版 apikey 请求头。 |
Idempotency-Key | 是 | 任意非空字符串,作用域为 (merchant, key)。这是资金写操作 —— 缺失时返回 400。 |
请求体
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
amount | 整数 | 是 | 最小货币单位,> 0。 |
currency | 字符串 | 否 | 3 位 ISO 4217 代码,API 会将其转为大写。默认为 "BRL"。Pix 收款必须使用 BRL。 |
payment_method | 字符串 | 是 | "pix" —— 目前唯一接受的值。 |
description | 字符串 | 否 | 最多 500 个字符;读取时会并入 metadata.description。 |
expires_in | 整数 | 否 | Pix 有效期(秒),60–604800(7 天)。超出该范围时 API 返回 400 —— 该值绝不会被截断。当服务商返回其自身的 pix.expires_at 时,以该值为准。 |
customer.name | 字符串 | 否 | |
customer.document | 字符串 | 否 | CPF 或 CNPJ。 |
customer.email | 字符串 | 否 | 必须是有效的电子邮件地址。 |
customer.phone | 字符串 | 否 | |
expected_payer_tax_id | 字符串 | 否 | 将收款锁定到特定付款人:校验和有效的 CPF(11 位)或 CNPJ(14 位)数字(规范化为纯数字)。如果同时发送 customer.document,两者必须一致;如果设置了该字段,则 customer.name 变为必填。 |
metadata | 对象 | 否 | 自由格式;保留键及以下划线开头的键会被移除。 |
示例
curl -X POST https://api.liqfy.com.br/v1/pix/charges \
-H "Authorization: Bearer $LIQFY_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000,
"currency": "BRL",
"description": "Pedido #12345",
"customer": { "name": "Maria Silva", "document": "12345678901" }
}'响应 201 Created
{
"id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
"object": "charge",
"amount": 1000,
"currency": "BRL",
"status": "pending",
"payment_method": "pix",
"customer": { "name": "Maria Silva", "document": "12345678901" },
"pix": {
"br_code": "000201BRCODEPIX",
"qr_code_url": "https://qr.example/img.png",
"expires_at": "2026-07-23T15:00:00.000Z"
},
"checkout_url": "https://checkout.liqfy.com.br/a1b2c3d4-0000-0000-0000-000000000009",
"settlement": {},
"metadata": { "order_id": "12345" },
"created_at": "2026-07-23T14:30:00.000Z"
}pix.txid(当服务商绑定了该值时)和 settlement.end_to_end_id(仅在 paid 且已结算后)属于上下文相关的 Pix 数据 —— 参见 PIX。charge.id 永远不会等于 charge.pix.txid。
使用相同的 Idempotency-Key 和相同的请求体重放请求时,会返回原始的 201,并设置响应头 Idempotency-Replayed: true。
checkout_url 是 Liqfy 为该收款提供的托管收银台 —— 将付款人重定向到该页面,而无需自行渲染 Pix 页面。创建和 GET /v1/charges/{id} 时都会返回该字段,且无法从 charge.id 推导得出(收银台路径会去掉 ch_ 前缀)。
公共状态词汇:pending、processing、paid、failed、expired、cancelled、refunded、disputed。
#获取收款
GET /v1/charges/{id}
接受带 ch_… 前缀的 id 或原始内部 id。作用域限于调用方账户 —— 其他账户的收款会返回 404。
响应 200 OK —— 与创建时相同的 Charge 结构。
当收款上开启了 MED 案件时,metadata.med.caseId 携带该 MED 案件的公共 id(med_…,与 GET /v1/med/cases/{id} 为同一 id),以便您将收款与案件关联。服务商自身的案件 id 永不对外暴露。
#按幂等键获取收款
GET /v1/charges/by-idempotency-key/{key}
查找您使用指定 Idempotency-Key 创建的收款 —— 便于在超时后找回收款,而无需重放创建请求。作用域限于调用方账户。键会被去除首尾空白;空键或长度超过 255 个字符的键返回 400。
响应 200 OK —— 与创建时相同的 Charge 结构。
#列出收款
GET /v1/charges
GET /v1/charges 使用游标分页({ object: "list", data, has_more, next_cursor })列出账户的收款 —— 排序为 createdAt desc,结果稳定,此路由不支持 page/offset。
GET /v1/charges?limit=25&starting_after=ch_01J…&status=paid| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
limit | 整数 | 25 | 1–100。 |
starting_after | 字符串 | — | 同一资源的收款 id(ch_…)—— 是游标,而非偏移量。最多 140 个字符。 |
status | 枚举 | — | 公共状态词汇(pending、paid、…)。 |
created_after | ISO 8601 | — | created_at 的下限(含)。 |
created_before | ISO 8601 | — | created_at 的上限(含)。 |
customer_id | 字符串 | — | 按付款人证件号过滤。最多 140 个字符。 |
idempotency_key | 字符串 | — | 按创建时使用的 Idempotency-Key 过滤(1–255 个字符,去除首尾空白)。 |
{
"object": "list",
"data": [],
"has_more": false,
"next_cursor": null
}此游标列表从不接受 page/offset —— 仅接受 starting_after。当 has_more 为 true 时,将 next_cursor 作为 starting_after 传入以获取下一页。
如需同一批交易的分页、可过滤视图,请参见 GET /v1/payments。
#钱包
/v1/wallets。您账户的余额。只读,作用域限于您的 API 密钥 —— /v1/wallets/* 下的写入路由仅限控制台使用,使用 API 密钥调用时返回 403。
#获取余额
GET /v1/wallets/balance
查询参数 currency 是可选的。不带该参数时(推荐形式),响应会在 balances[] 中包含账户上的所有币种,并在顶层附带主币种(默认为 BRL)的字段:
curl "https://api.liqfy.com.br/v1/wallets/balance" \
-H "Authorization: Bearer $LIQFY_API_KEY"响应 200 OK
{
"available": 880,
"pending": 0,
"total": 880,
"retained": 0,
"currency": "BRL",
"next_release_at": null,
"next_release_amount": null,
"balances": [
{ "currency": "BRL", "available": 880, "held": 0, "pending": 0, "total": 880 }
],
"primary": { "currency": "BRL", "available": 880, "held": 0, "pending": 0, "total": 880 }
}| 字段 | 描述 |
|---|---|
available | 主币种的可用/可提现余额,以最小单位表示(BRL 为分)。880 = R$ 8,80。有符号 —— 账户欠款时为负数。 |
held | 在 balances[]/primary 条目中被冻结(处理中暂扣)的金额。顶层不包含该字段。 |
pending | 已结算但仍被冻结 —— 暂不可用(主币种)。包括处理中的退款冻结,因此可能大于 retained。 |
total | 主币种的 available + held + pending。 |
retained | 主币种处于留存状态的总额(PENDING 冻结)。不包括退款冻结。 |
currency | 主币种(ISO 4217)。默认为 BRL。 |
next_release_at | 下一笔 pending 分批释放时间的 ISO 8601 字符串;若无计划则为 null。 |
next_release_amount | 下一笔释放的金额(最小货币单位),或 null。 |
balances[] | 每个币种一个条目:{ currency, available, held, pending, total }。 |
primary | 主币种(字段与 balances[] 条目相同)。 |
顶层字段(available/pending/total/currency)为主币种数据 —— 为向后兼容而保留。对于多币种账户,请遍历 balances[]。
这些数值的计算方式(它们不可互换):
balances[]和primary只统计活跃的OPERATIONAL钱包,按币种汇总:available = Σ(balance − heldBalance)、held = Σ heldBalance、pending = Σ pendingBalance、total = available + held + pending。- 此形式从不返回
404:即使完全没有钱包,也会返回零值和balances: []。 - 单笔提现只从一个钱包扣款,而下文的扁平
?currency=结构只读取默认钱包 —— 因此对于拥有多个钱包的币种,/balance、?currency=和提现校验可能显示三个不同的available数值。
#单币种(旧版结构)
GET /v1/wallets/balance?currency=BRL
传入 currency 可获取扁平的单币种结构:
curl "https://api.liqfy.com.br/v1/wallets/balance?currency=BRL" \
-H "Authorization: Bearer $LIQFY_API_KEY"{
"available": 880,
"held": 0,
"pending": 0,
"currency": "BRL",
"next_release_at": null,
"next_release_amount": null
}currency 不区分大小写。此结构仅读取账户在该币种下的默认钱包(而非汇总),未知币种返回零值而不是错误。此处没有 total/retained。
认证与错误。 务必发送 API 密钥。缺少或无效的密钥 →
401(绝不会是404)。不带currency时,此路由从不返回404;带上?currency=时,404not_found表示该账户完全没有钱包(而非路由问题)。错误的路径(/v1/wallets/balance,复数形式,带/v1前缀)或未转发/v1/wallets/*的中间层都不会到达 Liqfy,而是表现为其自身的错误。
#列出钱包
GET /v1/wallets
账户上的所有钱包 —— 任意 walletType,包括活跃和非活跃的,同一币种可能有多个 —— 认证方式相同。返回一个纯 JSON 数组,不分页。
curl https://api.liqfy.com.br/v1/wallets \
-H "Authorization: Bearer $LIQFY_API_KEY"响应 200 OK
[
{
"id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"currency": "BRL",
"label": "Operating wallet",
"walletType": "OPERATIONAL",
"isDefault": true,
"isActive": true,
"balance": 880,
"pendingBalance": 0,
"createdAt": "2026-04-25T15:42:11.000Z"
}
]balance/pendingBalance 以最小货币单位表示。它们与 GET /v1/wallets/balance 返回的 available/pending 并不是相同的金额:balance 已包含冻结金额(活跃 OPERATIONAL 钱包上的 available = balance − heldBalance),pendingBalance 仅在单钱包情况下与 pending 一致,且此列表不包含 heldBalance —— 因此无法据此计算 available。
#获取钱包
GET /v1/wallets/{id}
按 id(UUID)获取单个钱包。任意类型,无论是否活跃,作用域限于调用方账户。
curl https://api.liqfy.com.br/v1/wallets/a1b2c3d4-e5f6-4789-9abc-def012345678 \
-H "Authorization: Bearer $LIQFY_API_KEY"响应 200 OK
{
"id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"currency": "BRL",
"walletType": "OPERATIONAL",
"label": "Operating wallet",
"isDefault": true,
"balance": 880,
"pendingBalance": 0,
"heldBalance": 0,
"isActive": true,
"createdAt": "2026-04-25T15:42:11.000Z",
"updatedAt": "2026-07-23T14:31:00.000Z"
}未知 id 或属于其他账户的 id 返回 404 not_found。
#支付操作
/v1/payments。这些路由操作的是您通过 /v1/charges 创建的同一笔收款,通过其原始 id(去掉 ch_ 前缀)进行寻址。它们涵盖 /v1/charges 接口尚未提供的操作 —— 取消、统计、收据、对账 —— 以及采用交易传输格式的创建/读取/列表功能。如需创建收款,建议使用 收款。
退款不属于商户 API:POST /payments/{id}/refund 对每个 API 密钥请求都返回 403(error.code "forbidden",消息以 REFUND_ADMIN_ONLY 标记为前缀)。退款通过 Liqfy 管理后台发起 —— 参见下文的 退款。
/payments 下的内部管理路由(例如 GET /payments/{id}/provider-status)不属于商户 API:使用 API 密钥调用时返回 404,如同该路由不存在。
#创建支付
POST /payments
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
Authorization | 是 | Bearer + 您的 API 密钥。 |
Idempotency-Key | 是 | 首选方式。请求体字段 idempotencyKey 可作为别名使用 —— 若两者同时发送则必须一致(值不一致 → 400);两者都不发送 → 400。 |
请求体
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
amount | 整数 | 是 | 最小货币单位,> 0。 |
currency | 字符串(3–8) | 否 | 默认为 "BRL"。示例:BRL、EUR、USD、USDT。 |
paymentMethods | string[] | 除非提供 checkout | 以下 11 种方式中的一种或多种:PIX、CRYPTO、CREDIT_CARD、BOLETO、MBWAY、MULTIBANCO、IDEAL、BANCONTACT、SEPA、BIZUM、SWAP_NOW。配合 checkout 使用时为可选,用于缩小模板的支付方式范围。 |
checkout | 字符串 | 否 | 托管收银台模板标识(slug,1–80 个字符)。未知 slug → 404;若模板服务不可达 → 503。 |
customerId | 字符串 | 否 | 您的内部用户 id。仅随请求转发 —— 不持久化,不会在响应或商户 webhook 中回显。 |
customerName | 字符串 | 否 | |
customerDocument | 字符串 | 否 | CPF、CNPJ、NIF 或其他税号。 |
customerEmail | 字符串 | 否 | 必须是有效的电子邮件地址。 |
customerPhone | 字符串 | 否 | |
customer | 对象 | 否 | 嵌套的 { name?, document?, email?, phone? }。会被展开到 customer* 字段中;冲突时以扁平字段为准。 |
expectedPayerDocument | 字符串 | 否 | 纯数字的付款人 CPF/CNPJ 锁定。 |
items | object[] | 否 | { name, quantity, unitPrice, totalPrice } —— 除 name 外均为整数 > 0。 |
metadata | 对象 | 否 | 自由格式。其中的 returnUrl/cancelUrl 键必须是 http(s) URL,但下文的一等 returnUrl/cancelUrl 字段才是返回 URL。 |
webhookUrl | 字符串 | 否 | 按交易覆盖的 webhook URL。必须是有效的 URL。 |
country | 字符串 | 否 | 2–3 个字符。 |
riskTier | 枚举 | 否 | LOW、MEDIUM 或 HIGH。 |
environment | 枚举 | 否 | SANDBOX、STAGING 或 PRODUCTION。省略时由平台推导。实际收款去向仅由密钥决定。 |
returnUrl | 字符串 | 否 | 付款人完成支付后返回的地址:不含空白字符或片段(fragment)的 http(s) URL。 |
cancelUrl | 字符串 | 否 | 付款人取消时前往的地址:URL 规则相同。需要 returnUrl。 |
expiresIn | 整数 | 否 | Pix 有效期(秒),60–604800。 |
idempotencyKey | 字符串 | 是 | Idempotency-Key 请求头的请求体别名。每个预期请求唯一;重放时返回原始结果。 |
响应 201 Created
{
"id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"status": "WAITING_PAYMENT",
"amount": 24900,
"currency": "BRL",
"paymentMethods": ["PIX"],
"customerName": "Maria Silva",
"customerDocument": "12345678909",
"customerEmail": "maria@example.com",
"expectedPayerDocument": "12345678909",
"actualPayerDocument": null,
"payerValidationStatus": "PENDING",
"metadata": { "orderId": "ORD-7821" },
"checkoutUrl": "https://checkout.liqfy.com.br/c/a1b2c3d4-e5f6-4789-9abc-def012345678",
"createdAt": "2026-04-25T15:42:11.000Z"
}特定支付方式的字段(pixQrCode、mbEntity、boletoLine、cardRedirectUrl、…)在该方式同步生成时已包含在创建响应中 —— Pix BR Code/QR、Multibanco 实体/参考号、boleto 和银行卡重定向都会在 201 中返回。只有真正稍后才到达的产物才需要后续调用 GET /payments/{id}。
checkoutUrl 在创建和获取时存在,在列表行和取消响应中不存在。付款人校验字段组包括 expectedPayerDocument(您锁定的值)、actualPayerDocument(服务商报告的值)和 payerValidationStatus(NOT_REQUIRED、PENDING、MATCHED、MISMATCH、UNVERIFIED)。
#获取支付
GET /payments/{id}
响应 200 OK
{
"id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"status": "PAID",
"amount": 24900,
"currency": "BRL",
"paymentMethods": ["PIX"],
"paidWith": "PIX",
"pixQrCode": "data:image/png;base64,iVBOR...",
"pixCopyPaste": "00020126580014br.gov.bcb.pix...",
"pixExpiresAt": "2026-04-25T16:12:11.000Z",
"cardRedirectUrl": null,
"mbEntity": null,
"mbReference": null,
"mbExpiresAt": null,
"boletoBarcode": null,
"boletoLine": null,
"boletoPdfUrl": null,
"boletoExpiresAt": null,
"cryptoAddress": null,
"cryptoAmount": null,
"cryptoNetwork": null,
"cryptoCurrency": null,
"platformFee": 200,
"expectedPayerDocument": "12345678909",
"actualPayerDocument": "12345678909",
"payerValidationStatus": "MATCHED",
"metadata": { "orderId": "ORD-7821" },
"checkoutUrl": "https://checkout.liqfy.com.br/c/a1b2c3d4-e5f6-4789-9abc-def012345678",
"createdAt": "2026-04-25T15:42:11.000Z",
"paidAt": "2026-04-25T15:43:08.000Z"
}当字段不适用于所选的 paymentMethods 时,其值为 null。
任何 /v1/payments 响应(创建、获取、列表、取消)都不会说明是哪家收单机构处理了该收款:provider、providerAccountId、providerTransactionId、providerFeeSource、cardClientSecret 和 tenantId 均不返回(已于 2026-10-12 移除),收单机构的成本(providerFee、netAmount)也不返回。银行卡或银行重定向始终以收银台的 /c/{id} 链接形式提供。
#列出支付
GET /payments
查询参数
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
page | 整数 | 1 | |
limit | 整数 | 20 | 最大 100。 |
status | 枚举 | — | 参见下文的 状态枚举。 |
currency | 字符串 | — | 按币种过滤。 |
startDate | ISO 8601 | — | createdAt 的下限(含)。 |
endDate | ISO 8601 | — | createdAt 的上限(含)。 |
source | 枚举 | — | API、PANEL、MANUAL 或 INDEFINIDO(无来源的行)。 |
sortBy | 字符串 | createdAt | 交易列名(createdAt、amount、status、paidAt、updatedAt、…)。未知列名会导致 500 而非 400 —— 请只使用真实存在的列。 |
sortOrder | 枚举 | desc | asc 或 desc。 |
响应 200 OK
{
"data": [ { "id": "a1b2c3d4-e5f6-4789-9abc-def012345678", "...": "..." } ],
"total": 142,
"page": 1,
"limit": 20
}列表行不包含 checkoutUrl。这是分页信封(total/page/limit)—— 游标分页请使用 GET /v1/charges。
#统计
GET /payments/stats?days=7
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
days | 整数 | 7 | timeZone 中的营业日数,含今天。 |
from/to | ISO 8601 | — | 显式时间窗口;存在时覆盖 days。 |
timeZone | 字符串 | America/Sao_Paulo | IANA 时区名称。无效名称 → 400。 |
days=7 = 今天加上之前的六个自然日。汇总值(totalTransactions、paidTransactions、successRate、volumeByCurrency、methodBreakdown)覆盖整个窗口,无论其长度如何。dailyVolume 每个自然日一个数据点,最多 366 个:窗口更长时保留最近的 366 天。hourlyVolume 仅在窗口为单日时存在 —— 每个营业小时一个数据点,键的格式与 dailyVolume 相同,但附加了小时("YYYY-MM-DDTHH")。methodBreakdownByCurrency 为每个(支付方式,币种)组合提供一行扁平数据。沙箱/测试收款不计入。始终限于您的账户 —— 无法解析账户的请求返回 401。
响应 200 OK
{
"totalTransactions": 142,
"paidTransactions": 119,
"todayTransactions": 8,
"successRate": 84,
"volumeByCurrency": [
{ "currency": "BRL", "volume": 1245000, "count": 95 },
{ "currency": "EUR", "volume": 89400, "count": 24 }
],
"todayVolumeByCurrency": { "BRL": 24900, "EUR": 8990 },
"dailyVolume": [
{ "date": "2026-04-19", "currencies": { "BRL": 89000 } },
{ "date": "2026-04-20", "currencies": { "BRL": 124500, "EUR": 4500 } }
],
"hourlyVolume": [
{ "date": "2026-04-20T09", "currencies": { "BRL": 24900 } }
],
"methodBreakdown": [
{ "method": "PIX", "volume": 980000, "count": 78 },
{ "method": "CREDIT_CARD", "volume": 265000, "count": 34 },
{ "method": "MULTIBANCO", "volume": 89400, "count": 7 }
],
"methodBreakdownByCurrency": [
{ "method": "PIX", "currency": "BRL", "volume": 980000, "count": 78 },
{ "method": "CREDIT_CARD", "currency": "BRL", "volume": 265000, "count": 34 },
{ "method": "MULTIBANCO", "currency": "EUR", "volume": 89400, "count": 7 }
],
"statusCounts": { "PAID": 119, "REFUSED": 10 },
"avgPaySeconds": 42
}#指标
GET /payments/metrics?days=7¤cy=BRL
您商户账户的转化漏斗和交易量指标。days 默认为 7(窗口规则与 统计 相同,但没有 366 个数据点的上限);currency 为可选(过滤为单一币种);timeZone 的用法与统计相同。作用域限于您的 API 密钥 —— 无法解析账户时返回 401,绝不会返回全平台数据。
响应 200 OK
{
"days": 7,
"currency": "BRL",
"overall": { "created": 142, "paid": 119, "conversionRate": 83.8 },
"byMethod": [
{ "method": "PIX", "created": 90, "paid": 78, "conversionRate": 86.7 }
],
"refunds": { "count": 2, "volumeByCurrency": { "BRL": 4500 } },
"chargebacks": { "count": 0 }
}#净交易量
GET /payments/net-volume
指定窗口内的净结算交易量(仅 amount − platformFee、PAID)。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
from/to | ISO 8601 | — | 窗口边界。 |
timeZone | 字符串 | America/Sao_Paulo | IANA 时区名称。无效名称 → 400。 |
响应 200 OK
{
"from": "2026-04-19T00:00:00.000Z",
"to": "2026-04-25T23:59:59.999Z",
"byCurrency": {
"BRL": { "netVolume": 1220500, "txCount": 95, "grossVolume": 1245000, "feeTotal": 24500 }
}
}#转化
GET /payments/conversion
按状态划分的漏斗 { currency, status, count, volume } 行 —— 自 from 以来创建、当前处于您所读取状态的收款,不含测试收款。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
from | ISO 8601 | — | 下限(含)。无效值 → 400。 |
响应 200 OK
[
{ "currency": "BRL", "status": "PAID", "count": 95, "volume": 1245000 },
{ "currency": "BRL", "status": "REFUSED", "count": 4, "volume": 12000 }
]#退款(仅限管理后台)
POST /payments/{id}/refund
不能使用 API 密钥调用。 无论请求体为何,所有商户请求都会被拒绝并返回 403:error.code 为 "forbidden",且消息以 REFUND_ADMIN_ONLY 标记开头(这是消息前缀,而非错误码 —— 参见 错误)。退款(全额或部分,PIX 或银行卡)通过 Liqfy 管理后台申请,后台会先设置钱包冻结,然后执行退款。商户可通过 GET /payments/{id}/refunds 和 charge.refunded webhook 跟踪退款状态。
为内部调用方记录的请求体 —— idempotencyKey、amount、reason、strategy(devolution/cashout)、passFeeToTenant、destinationKey、refundId —— 不是商户契约;请勿基于它进行开发。
#列出退款
GET /payments/{id}/refunds
返回针对某笔交易发起的所有退款(最新的在前)。不返回收单机构的退款 id。
[
{
"id": "b2c3d4e5-f6a7-4890-9abc-def012345678",
"transactionId": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"amount": 24900,
"currency": "BRL",
"reason": null,
"failureReason": null,
"status": "REFUNDED",
"origin": "MERCHANT",
"idempotencyKey": "order-7821",
"refundedAt": "2026-04-25T15:50:00.000Z",
"createdAt": "2026-04-25T15:50:00.000Z",
"updatedAt": "2026-04-25T16:12:00.000Z"
}
]status 取值为 PENDING、IN_PROGRESS、PENDING_RECONCILIATION、REFUNDED、FAILED 之一;origin 为 MERCHANT、AUTOMATIC_PAYER_RESTRICTION 或 REVIEW_REJECTION。reason 仅在商户发起的退款中填写 —— 对于平台发起的退款(AUTOMATIC_PAYER_RESTRICTION、REVIEW_REJECTION),该值始终为 null。对商户而言,failureReason 始终为 null:退款失败通过 status: "FAILED" 表示。
#取消支付
POST /payments/{id}/cancel
取消处理中的收款 —— 仅在 WAITING_PAYMENT 或 PENDING 时有效。PROCESSING 会被拒绝并返回 409 payment_not_cancellable,其他任何状态返回 400。已结算(PAID/APPROVED)的收款必须退款,而不能取消。返回更新后的交易,结构与 GET /payments/{id} 相同(不含 checkoutUrl),并发布 charge.failed 事件,附带 status: "CANCELLED" 和 previousStatus。
#重发 webhook
POST /payments/{id}/resend-webhook
将交易的当前状态作为一次新的 webhook 投递重新发送 —— 适用于您的端点曾宕机的情况。
{ "resent": true, "status": "PAID" }#对账
POST /payments/{id}/reconcile
请求平台向服务商重新核对该交易,并解决任何不一致之处。
响应 200 OK
{ "reconciled": true, "status": "PAID" }已处于终态的交易返回 { "reconciled": false, "status": "…" }。内部原因和服务商状态不属于商户响应 —— 仅返回 reconciled 和 status。
#确认沙箱支付
POST /payments/{id}/confirm-sandbox
商户用于端到端自测 webhook 的手段:对于使用测试密钥创建的交易,此操作会将模拟收款变为 PAID,并触发正常的 webhook。它绝不会为钱包入账。参见 沙箱。
响应 200 OK
{ "confirmed": true, "status": "PAID" }已处于终态的收款返回 { "confirmed": false, "status": "…", "reason": "ALREADY_TERMINAL" }。非沙箱/测试交易的收款会被拒绝并返回 400。
#收据
GET /payments/{id}/receipt
Liqfy 为具有最终结果的交易提供的自有文档(PDF)—— 绝非收单机构的文档,也绝不会提及服务商名称。处理中的交易返回 400。
{ "contentType": "application/pdf", "base64": "JVBERi0xLjcK..." }仅以下结果才会生成文档,且文档标题随结果而定:
| 状态 | 文档标题 |
|---|---|
PAID / APPROVED | Comprovante de Pagamento PIX(PIX 付款凭证)—— 唯一的付款收据;已知时包含 BACEN E2E id。 |
EXPIRED | Cobrança Expirada(收款已过期) |
REFUSED | Cobrança Não Aprovada(收款未获批准) |
REFUNDED | Comprovante de Devolução(退款凭证) |
CANCELLED | Cobrança Cancelada(收款已取消) |
CHARGEBACK | Pagamento em Devolução(付款退款中) |
所有非已付款文档都会声明其不是付款证明,并告知最终客户发生了什么以及下一步该怎么做。付款人证件信息会被脱敏。
#Webhooks
#注册端点
POST /webhooks/endpoints
{
"url": "https://merchant.example.com/hooks/liqfy",
"events": ["charge.paid", "charge.failed", "charge.expired"]
}事件名称(收款相关):charge.created、charge.paid、charge.failed、charge.expired、charge.refunded、payout.created、payout.approved、payout.paid、payout.failed,以及 med_case.created 和 med_case.updated。这些事件以带版本号的 evt_ 信封投递,并使用 X-Liqfy-Signature: t=<unix>,v1=<hex> 签名 —— 参见 Webhooks。请订阅这些事件。(med.resolved 属于同一系列,但使用较旧的 { event, data } 信封和 sha256= 签名。)
仅接受规范的收款和提现事件名称。已停用的名称返回 HTTP 400 LEGACY_WEBHOOK_EVENT,并附带规范的 replacement。现有订阅已完成迁移和去重。
响应 201 Created
{
"id": "e5f6a7b8-c9d0-4123-9ef0-123456789012",
"url": "https://merchant.example.com/hooks/liqfy",
"events": ["charge.paid", "charge.failed", "charge.expired"],
"secret": "b8f3a9c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
"status": "ACTIVE"
}secret 仅显示一次 —— 请立即保存。在沙箱/预发布环境之外,URL 必须为 https://,且不得指向 Liqfy 域名;重复的 URL 返回 409,且账户的活跃端点数量有限。
#列出端点
GET /webhooks/endpoints
{
"data": [
{
"id": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"url": "https://...",
"events": ["payment.status_changed"],
"status": "ACTIVE",
"createdAt": "...",
"updatedAt": "..."
}
],
"access": { "canManage": true },
"httpsOnly": true
}Id 为 UUID。access.canManage 表示调用方是否可以写入端点;httpsOnly 表示平台当前是否要求使用 https:// URL。
此端点永远不会返回 secret。
#测试端点
POST /webhooks/endpoints/{id}/test
同步发送一个规范的 charge.paid 示例,使用带版本号的信封和带时间戳的签名。超出每小时测试次数限制时返回 429 WEBHOOK_TEST_RATE_LIMIT。
{
"ok": true,
"statusCode": 200,
"durationMs": 143,
"errorKind": null,
"error": null,
"responseSnippet": "{\"received\":true}",
"eventType": "charge.paid",
"url": "https://merchant.example.com/hooks/liqfy",
"sentHeaders": { "X-Liqfy-Event-Type": "charge.paid" },
"sentPayload": { "id": "evt_...", "object": "event", "...": "..." }
}当 ok 为 false 时,errorKind 为 timeout、connection 或 http。
#轮换密钥
POST /webhooks/endpoints/{id}/rotate-secret
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012" }响应 200 OK
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012", "secret": "<64-char hex>" }新密钥仅显示一次。轮换是即时的服务端切换 —— 没有重叠窗口。在此调用之后签名的每个 webhook 都使用新密钥,因此请在部署期间让您的验证程序同时接受旧密钥和新密钥,之后再弃用旧密钥(参见 webhooks.md)。
#更新端点
PATCH /webhooks/endpoints/{id}
更新 URL、订阅的事件或状态(ACTIVE/INACTIVE)。仅发送需要更改的字段。
{ "url": "https://merchant.example.com/hooks/v2", "status": "ACTIVE" }响应 200 OK —— { id, url, events, status }。永不返回密钥。
#删除端点
DELETE /webhooks/endpoints/{id}
永久移除该端点。待投递给它的消息会被重定向到账户的其他活跃端点;仅当没有其他端点时才会取消。投递历史会保留。
响应 200 OK —— { "deleted": true }。
#事件目录
GET /webhooks/event-catalog
返回完整、最新的可订阅公共事件名称列表及其描述。此路由与 /v1/webhooks 下的其他路由一样,使用相同的 API 密钥认证。与收款/提现相关的摘录:
[
{ "event": "charge.created", "description": "Cobrança criada (Pix/cartão gerado, aguardando pagamento)." },
{ "event": "charge.paid", "description": "Cobrança paga e confirmada (Pix/cartão liquidado)." },
{ "event": "charge.failed", "description": "Cobrança falhou ou foi cancelada." },
{ "event": "charge.expired", "description": "Cobrança expirou sem pagamento." },
{ "event": "charge.refunded","description": "Cobrança reembolsada." },
{ "event": "payout.created", "description": "Saque solicitado." },
{ "event": "payout.approved", "description": "Payout approved." },
{ "event": "payout.paid", "description": "Saque liquidado com sucesso." },
{ "event": "payout.failed", "description": "Saque falhou ou foi rejeitado." }
]#列出投递记录
GET /webhooks/deliveries
| 参数 | 描述 |
|---|---|
status | PENDING、PROCESSING、DELIVERED、FAILED、CANCELLED |
eventType | 按事件名称过滤(charge.paid、charge.refunded、…)。 |
endpointId | 按已注册端点过滤。 |
limit | 默认 25,最大 100。 |
offset | 默认 0。 |
{
"data": [
{
"id": "b2c3d4e5-f6a7-4890-9abc-def012345678",
"endpointId": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"eventType": "charge.paid",
"status": "DELIVERED",
"attempts": 1,
"maxAttempts": 15,
"lastStatusCode": 200,
"lastError": null,
"nextRetryAt": null,
"deliveredAt": "2026-04-25T15:43:09.000Z",
"createdAt": "2026-04-25T15:43:08.000Z",
"updatedAt": "2026-04-25T15:43:09.000Z",
"payload": { "type": "charge.paid", "object": "event", "data": { "object": { "id": "ch_example", "object": "charge", "status": "paid" } } }
}
],
"total": 142,
"limit": 25,
"offset": 0
}列表行包含 payload 和 lastError,而不包含响应体 —— 响应体请见下文的投递详情。
#获取投递记录
GET /webhooks/deliveries/{id}
完整的投递记录,包括响应体和尝试日志。
{
"id": "b2c3d4e5-f6a7-4890-9abc-def012345678",
"endpointId": "a1b2c3d4-e5f6-4789-9abc-def012345678",
"eventType": "charge.paid",
"status": "FAILED",
"attempts": 3,
"maxAttempts": 15,
"lastStatusCode": 502,
"lastError": "HTTP 502",
"lastResponseBody": "Bad Gateway",
"logs": [
{
"id": "c3d4e5f6-a7b8-4901-9abc-def012345678",
"deliveryId": "b2c3d4e5-f6a7-4890-9abc-def012345678",
"attempt": 1,
"statusCode": 502,
"error": "HTTP 502",
"responseBody": "Bad Gateway",
"duration": 312,
"url": "https://merchant.example.com/hooks/liqfy",
"createdAt": "2026-04-25T15:43:09.000Z"
}
],
"endpoint": { "url": "https://merchant.example.com/hooks/liqfy", "status": "ACTIVE" }
}#重放投递
POST /webhooks/deliveries/{id}/replay
将一条投递重新加入队列(重置尝试次数和调度计划)。DELIVERED 状态的投递会被拒绝并返回 400,处于 PROCESSING 状态的投递返回 400 —— 请稍候重试。
{ "id": "b2c3d4e5-f6a7-4890-9abc-def012345678", "status": "PENDING", "attempts": 0, "nextRetryAt": "2026-04-25T16:08:00.000Z" }#批量重放投递
POST /webhooks/deliveries/replay-bulk
{ "status": "FAILED", "endpointId": "a1b2c3d4-e5f6-4789-9abc-def012345678", "limit": 50 }| 参数 | 描述 |
|---|---|
status | 目标状态。默认为 FAILED + CANCELLED。未知值 → 400。 |
endpointId | 限定为某一个端点。 |
limit | 默认 50,最大 500。 |
响应 200 OK —— { "requeued": 12 }。
#拉取事件
GET /webhooks/events
事件的对账视图,采用键集分页:{ data, nextCursor }(注意 camelCase 形式的 nextCursor)。行为 { eventType, payload, status, lastStatusCode, deliveredAt, createdAt } —— 没有逐行的 id。
| 参数 | 描述 |
|---|---|
since/until | createdAt 的 ISO 8601 边界。 |
status | 投递状态过滤。 |
eventType | 事件名称过滤。 |
limit | 默认 50,最大 100。 |
cursor | 来自 nextCursor 的不透明游标。 |
#投递统计
GET /webhooks/stats
{
"total": 1402,
"PENDING": 3,
"PROCESSING": 1,
"DELIVERED": 1380,
"FAILED": 12,
"CANCELLED": 6
}#状态枚举
下表是 /v1/payments 交易路由返回的详细状态枚举(以及其 webhook 投递中的 eventType/payload.data.status)。POST/GET /v1/charges 从不输出这些值;它们输出较小的公共词汇集(pending、processing、paid、failed、expired、cancelled、refunded、disputed —— 参见 快速入门 §5),下面的枚举会映射到这些公共值。
| 交易状态 | 描述 | 公共 charge.status |
|---|---|---|
PENDING | 内部 —— 创建中。很少出现。 | pending |
WAITING_PAYMENT | 等待客户操作。 | pending |
PROCESSING | 银行卡 / 3DS 处理中。 | processing |
PAID | 已结算 —— 非银行卡方式。 | paid |
APPROVED | 已结算 —— 银行卡方式。 | paid |
REFUSED | 收单机构或发卡行拒绝。 | failed |
CANCELLED | 完成前已取消。 | cancelled |
EXPIRED | 时间窗口已过。 | expired |
REFUNDED | 已全额退款。 | refunded |
CHARGEBACK | 发卡行发起了拒付(银行卡)。 | disputed |
DISPUTE | 争议处理中:持卡人争议(银行卡),或已付款 Pix 收款上的 Pix MED 案件。MED 胜诉或撤回后,收款恢复为 PAID。 | disputed |
charge.paid 表示已付款的收款。charge.failed 和 charge.expired 区分失败与过期。因 MED 而转为 DISPUTE 的 Pix 收款不会发送 charge.* webhook —— MED 通过 MED 案件跟踪(参见 获取收款 中的 metadata.med.caseId)。
#Webhook 负载结构
#规范信封(charge.* / payout.*)
{
"id": "evt_5f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c",
"object": "event",
"api_version": "2026-07-23",
"type": "charge.paid",
"created_at": "2026-07-23T14:31:00.000Z",
"data": {
"object": {
"id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
"object": "charge",
"amount": 24900,
"currency": "BRL",
"status": "paid",
"payment_method": "pix",
"settlement": {}
}
}
}| 字段 | 始终存在 | 描述 |
|---|---|---|
id | 是 | evt_… —— 每个业务事件稳定不变,所有重试中保持一致。请据此去重。 |
object | 是 | 始终为 "event"。 |
api_version | 是 | 契约版本,例如 2026-07-23。 |
type | 是 | charge.created | charge.paid | charge.failed | charge.expired | charge.refunded | payout.created | payout.approved | payout.paid | payout.failed | med_case.created | med_case.updated。payout.approved = 提现已批准,等待结算(processing)。 |
data.object | 是 | 该事件对应的公共对象 —— 与 REST 接口中 charge/payout 使用相同的序列化器和字段名,并按 Webhooks 中所述进行事件特定的精简。 |
#Webhook 请求头
| 请求头 | 描述 |
|---|---|
X-Liqfy-Signature | charge.*/payout.* 事件:对 "<t>.<rawBody>" 进行 t=<unix>,v1=<hex> HMAC。KYC、账户生命周期和 med.resolved 事件:对原始请求体进行 sha256=<hex> HMAC。 |
X-Liqfy-Delivery-Id | 每次投递唯一 —— 同一投递的每次重试都相同;用于传输层去重。 |
X-Liqfy-Event-Type | 对应 type / event。 |
验证示例参见 webhooks.md。
#HTTP 状态码
| 状态码 | 用途 |
|---|---|
200 | 成功读取 |
201 | 资源已创建 |
204 | 无内容(例如登出) |
400 | 校验错误,或资金写操作缺少 Idempotency-Key(或在 /v1/payments 上请求头与请求体中的键不一致) |
401 | 缺少 / 无效的 API 密钥 |
403 | 被欺诈 / 频率防护拦截 —— fraud.tenant_velocity_exceeded(账户在短时间内收款尝试过多)或 fraud.customer_velocity_exceeded(同一客户证件号或电子邮件的尝试过多;已过期和已取消的收款不计入)——、使用 API 密钥尝试退款(消息标记 REFUND_ADMIN_ONLY,而非错误码)、account_suspended,或 IP 白名单(仅限账户路由 —— 钱包、提现、交易、MED、api-keys;不包括 payments/charges/webhooks) |
404 | 资源不存在 |
409 | 冲突 —— idempotency_key_reused、idempotency_key_in_flight、payment_not_cancellable |
422 | 收款创建被服务商路由/配置拒绝。会透传 4xx 状态和稳定的 code:NO_PROVIDER_CONFIGURED、UNKNOWN_METHOD、PAYMENT_REJECTED、MOCK_PROVIDER_IN_PRODUCTION、PAYER_IDENTITY_REQUIRED、PAYER_NAME_REQUIRED |
429 | 触发速率限制 |
500 | 服务器错误 —— 可安全重试(幂等性提供保护) |
503 | 上游收单机构不可用(PROVIDER_UNAVAILABLE)—— 请使用退避策略重试 |
收款创建的错误消息是 Liqfy 自有的中性文本 —— 绝不包含服务商名称、其内部代码或账户配置。意外的上游响应会报告为 PROVIDER_ERROR。请向支持团队提供 request_id 以获取详情。
完整的规范错误信封(error.type/error.code/error.message、request_id、X-Request-Id)参见 错误。