Skip to content
LIQFYdocs
PTENENEN
Go to dashboard

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对象否自由格式;保留键及以下划线开头的键会被移除。

示例

bash
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

json
{
  "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。

http
GET /v1/charges?limit=25&starting_after=ch_01J…&status=paid
参数类型默认值描述
limit整数251–100。
starting_after字符串—同一资源的收款 id(ch_…)—— 是游标,而非偏移量。最多 140 个字符。
status枚举—公共状态词汇(pending、paid、…)。
created_afterISO 8601—created_at 的下限(含)。
created_beforeISO 8601—created_at 的上限(含)。
customer_id字符串—按付款人证件号过滤。最多 140 个字符。
idempotency_key字符串—按创建时使用的 Idempotency-Key 过滤(1–255 个字符,去除首尾空白)。
json
{
  "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)的字段:

bash
curl "https://api.liqfy.com.br/v1/wallets/balance" \
  -H "Authorization: Bearer $LIQFY_API_KEY"

响应 200 OK

json
{
  "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 可获取扁平的单币种结构:

bash
curl "https://api.liqfy.com.br/v1/wallets/balance?currency=BRL" \
  -H "Authorization: Bearer $LIQFY_API_KEY"
json
{
  "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= 时,404 not_found 表示该账户完全没有钱包(而非路由问题)。错误的路径(/v1/wallets/balance,复数形式,带 /v1 前缀)或未转发 /v1/wallets/* 的中间层都不会到达 Liqfy,而是表现为其自身的错误。

#列出钱包

GET /v1/wallets

账户上的所有钱包 —— 任意 walletType,包括活跃和非活跃的,同一币种可能有多个 —— 认证方式相同。返回一个纯 JSON 数组,不分页。

bash
curl https://api.liqfy.com.br/v1/wallets \
  -H "Authorization: Bearer $LIQFY_API_KEY"

响应 200 OK

json
[
  {
    "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)获取单个钱包。任意类型,无论是否活跃,作用域限于调用方账户。

bash
curl https://api.liqfy.com.br/v1/wallets/a1b2c3d4-e5f6-4789-9abc-def012345678 \
  -H "Authorization: Bearer $LIQFY_API_KEY"

响应 200 OK

json
{
  "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。
paymentMethodsstring[]除非提供 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 锁定。
itemsobject[]否{ 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

json
{
  "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

json
{
  "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字符串—按币种过滤。
startDateISO 8601—createdAt 的下限(含)。
endDateISO 8601—createdAt 的上限(含)。
source枚举—API、PANEL、MANUAL 或 INDEFINIDO(无来源的行)。
sortBy字符串createdAt交易列名(createdAt、amount、status、paidAt、updatedAt、…)。未知列名会导致 500 而非 400 —— 请只使用真实存在的列。
sortOrder枚举descasc 或 desc。

响应 200 OK

json
{
  "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整数7timeZone 中的营业日数,含今天。
from/toISO 8601—显式时间窗口;存在时覆盖 days。
timeZone字符串America/Sao_PauloIANA 时区名称。无效名称 → 400。

days=7 = 今天加上之前的六个自然日。汇总值(totalTransactions、paidTransactions、successRate、volumeByCurrency、methodBreakdown)覆盖整个窗口,无论其长度如何。dailyVolume 每个自然日一个数据点,最多 366 个:窗口更长时保留最近的 366 天。hourlyVolume 仅在窗口为单日时存在 —— 每个营业小时一个数据点,键的格式与 dailyVolume 相同,但附加了小时("YYYY-MM-DDTHH")。methodBreakdownByCurrency 为每个(支付方式,币种)组合提供一行扁平数据。沙箱/测试收款不计入。始终限于您的账户 —— 无法解析账户的请求返回 401。

响应 200 OK

json
{
  "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&currency=BRL

您商户账户的转化漏斗和交易量指标。days 默认为 7(窗口规则与 统计 相同,但没有 366 个数据点的上限);currency 为可选(过滤为单一币种);timeZone 的用法与统计相同。作用域限于您的 API 密钥 —— 无法解析账户时返回 401,绝不会返回全平台数据。

响应 200 OK

json
{
  "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/toISO 8601—窗口边界。
timeZone字符串America/Sao_PauloIANA 时区名称。无效名称 → 400。

响应 200 OK

json
{
  "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 以来创建、当前处于您所读取状态的收款,不含测试收款。

参数类型默认值描述
fromISO 8601—下限(含)。无效值 → 400。

响应 200 OK

json
[
  { "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。

json
[
  {
    "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 投递重新发送 —— 适用于您的端点曾宕机的情况。

json
{ "resent": true, "status": "PAID" }

#对账

POST /payments/{id}/reconcile

请求平台向服务商重新核对该交易,并解决任何不一致之处。

响应 200 OK

json
{ "reconciled": true, "status": "PAID" }

已处于终态的交易返回 { "reconciled": false, "status": "…" }。内部原因和服务商状态不属于商户响应 —— 仅返回 reconciled 和 status。


#确认沙箱支付

POST /payments/{id}/confirm-sandbox

商户用于端到端自测 webhook 的手段:对于使用测试密钥创建的交易,此操作会将模拟收款变为 PAID,并触发正常的 webhook。它绝不会为钱包入账。参见 沙箱。

响应 200 OK

json
{ "confirmed": true, "status": "PAID" }

已处于终态的收款返回 { "confirmed": false, "status": "…", "reason": "ALREADY_TERMINAL" }。非沙箱/测试交易的收款会被拒绝并返回 400。


#收据

GET /payments/{id}/receipt

Liqfy 为具有最终结果的交易提供的自有文档(PDF)—— 绝非收单机构的文档,也绝不会提及服务商名称。处理中的交易返回 400。

json
{ "contentType": "application/pdf", "base64": "JVBERi0xLjcK..." }

仅以下结果才会生成文档,且文档标题随结果而定:

状态文档标题
PAID / APPROVEDComprovante de Pagamento PIX(PIX 付款凭证)—— 唯一的付款收据;已知时包含 BACEN E2E id。
EXPIREDCobrança Expirada(收款已过期)
REFUSEDCobrança Não Aprovada(收款未获批准)
REFUNDEDComprovante de Devolução(退款凭证)
CANCELLEDCobrança Cancelada(收款已取消)
CHARGEBACKPagamento em Devolução(付款退款中)

所有非已付款文档都会声明其不是付款证明,并告知最终客户发生了什么以及下一步该怎么做。付款人证件信息会被脱敏。


#Webhooks

#注册端点

POST /webhooks/endpoints

json
{
  "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

json
{
  "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

json
{
  "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。

json
{
  "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

json
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012" }

响应 200 OK

json
{ "id": "e5f6a7b8-c9d0-4123-9ef0-123456789012", "secret": "<64-char hex>" }

新密钥仅显示一次。轮换是即时的服务端切换 —— 没有重叠窗口。在此调用之后签名的每个 webhook 都使用新密钥,因此请在部署期间让您的验证程序同时接受旧密钥和新密钥,之后再弃用旧密钥(参见 webhooks.md)。


#更新端点

PATCH /webhooks/endpoints/{id}

更新 URL、订阅的事件或状态(ACTIVE/INACTIVE)。仅发送需要更改的字段。

json
{ "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 密钥认证。与收款/提现相关的摘录:

json
[
  { "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

参数描述
statusPENDING、PROCESSING、DELIVERED、FAILED、CANCELLED
eventType按事件名称过滤(charge.paid、charge.refunded、…)。
endpointId按已注册端点过滤。
limit默认 25,最大 100。
offset默认 0。
json
{
  "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}

完整的投递记录,包括响应体和尝试日志。

json
{
  "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 —— 请稍候重试。

json
{ "id": "b2c3d4e5-f6a7-4890-9abc-def012345678", "status": "PENDING", "attempts": 0, "nextRetryAt": "2026-04-25T16:08:00.000Z" }

#批量重放投递

POST /webhooks/deliveries/replay-bulk

json
{ "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/untilcreatedAt 的 ISO 8601 边界。
status投递状态过滤。
eventType事件名称过滤。
limit默认 50,最大 100。
cursor来自 nextCursor 的不透明游标。

#投递统计

GET /webhooks/stats

json
{
  "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.*)

json
{
  "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-Signaturecharge.*/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)参见 错误。