Pular para o conteúdo
LIQFYdocs
PTEN
Ir para o painel

Pagamentos Pix

O Pix é o trilho de pagamento instantâneo brasileiro. O dinheiro liquida em segundos, 24 horas por dia, todo dia. A Liqfy te dá um endpoint só que devolve o BR Code (Pix Copia e Cola) e o QR Code prontos para renderizar no seu checkout — na mesma resposta que cria a cobrança.

#O fluxo, de relance

text
1. POST /v1/charges  ────────▶  a Liqfy devolve a Cobrança: ch_…, status "pending", pix.br_code + QR
2. Você renderiza o QR e o Pix Copia e Cola na sua tela
3. O cliente escaneia ou cola no app do banco dele
4. O webhook charge.paid chega no seu endpoint
5. Você libera o pedido

#1. Criar a cobrança

Endpoint POST /v1/charges (atalho Pix-first: POST /v1/pix/charges já fixa payment_method: "pix" e devolve exatamente a mesma Cobrança)

Cabeçalhos

text
apikey: lq_live_...
Idempotency-Key: <único por cobrança que você pretende criar>
Content-Type: application/json

Corpo

CampoTipoObrigatórioObservação
amountinteirosimCentavos. 1000 = R$ 10,00. Precisa ser inteiro positivo.
currencystringnãoPadrão "BRL" — a única moeda que cobrança Pix aceita.
payment_methodstringsim"pix" (único valor aceito hoje; o atalho /v1/pix/charges preenche por você).
descriptionstringnãoAté 500 caracteres. Volta dentro de metadata.description.
expires_ininteironãoSegundos até a cobrança expirar (o tempo de vida do QR Pix). 60–86400 (24 h — o teto de uma cobrança Pix imediata; valores maiores são limitados). Omita para usar a janela padrão da conta (geralmente 3600 = 1 h). O pix.expires_at na resposta é sempre a expiração autoritativa.
customer.namestringnãoAparece no extrato do banco quando o provedor suporta.
customer.documentstringnãoCPF ou CNPJ.
customer.emailstringnãoUsado em comprovante.
customer.phonestringnão
expected_payer_tax_idstringnãoTrava de CPF do pagador (opt-in). O CPF/CNPJ (11 ou 14 dígitos) que DEVE pagar esta cobrança. Um pagamento de qualquer outro documento é devolvido automaticamente — veja Trava de CPF do pagador abaixo. Exige customer.name. Precisa ser um CPF/CNPJ válido e, se você também enviar customer.document, precisa coincidir com ele.
metadataobjetonãoChave/valor livre, devolvido igual (chaves reservadas e iniciadas com _ são removidas).

Exemplo

bash
curl -X POST https://liqfy.com.br/v1/charges \
  -H "apikey: $LIQFY_API_KEY" \
  -H "Idempotency-Key: ORD-7821" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 24900,
    "currency": "BRL",
    "payment_method": "pix",
    "description": "Pedido #7821",
    "expires_in": 1800,
    "customer": { "name": "Maria Silva", "document": "12345678901" },
    "metadata": { "order_id": "ORD-7821", "sku": "premium-mensal" }
  }'

Resposta 201 Created

json
{
  "id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
  "object": "charge",
  "amount": 24900,
  "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": "ORD-7821", "sku": "premium-mensal", "description": "Pedido #7821" },
  "created_at": "2026-07-23T14:30:00.000Z"
}
CampoO que fazer com ele
pix.br_codeO payload EMV do "Pix Copia e Cola". Renderize num botão de copiar.
pix.qr_code_url / qr_code_base64Um dos dois sempre vem quando o Pix está disponível. Jogue a URL num <img src="...">, ou decodifique o PNG em base64.
checkout_urlO checkout hospedado da Liqfy para esta cobrança — uma página de pagamento pronta (QR, copia-e-cola, status ao vivo). Redirecione o pagador para cá em vez de montar a sua própria tela. Também vem no GET /v1/charges/{id}, então dá para buscar depois a partir de um id guardado. Você não consegue montar essa URL sozinho: o checkout espera o id sem o prefixo ch_.
pix.expires_atQuando a cobrança expira. Mostre uma contagem regressiva; depois disso o status vira expired.
pix.txidTXID do BACEN — opcional, só aparece quando o provedor vinculou um. Nunca trate como id da cobrança.
settlement{} na criação. O settlement.end_to_end_id só aparece depois que a cobrança chega em paid e foi liquidada/conciliada — nunca na criação.

#TXID e end_to_end_id

ch_… é sempre o id Liqfy da cobrança — o que você guarda, consulta e usa para conciliar webhook. pix.txid e settlement.end_to_end_id são dado contextual do Pix definido pelo BACEN, expostos só quando se aplicam:

json
{
  "id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
  "pix": { "txid": "BACEN-TXID-77" },
  "settlement": {}
}

charge.id !== charge.pix.txid, sempre — mesmo quando os dois existem. Nunca chaveie seu banco pelo TXID nem pelo end_to_end_id; use o ch_….

#Trava de CPF do pagador

Use expected_payer_tax_id para exigir que apenas um CPF/CNPJ específico pague a cobrança — por exemplo, garantir que o comprador pague da própria conta, e não de um terceiro.

bash
curl -X POST https://liqfy.com.br/v1/charges \
  -H "apikey: $LIQFY_API_KEY" \
  -H "Idempotency-Key: ORD-7821" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 24900,
    "payment_method": "pix",
    "customer": { "name": "Maria Silva", "document": "12345678901" },
    "expected_payer_tax_id": "12345678901"
  }'

Como funciona:

  • A cobrança é criada e paga como qualquer outra cobrança Pix.
  • Na liquidação, a Liqfy lê o documento real do pagador no banco e compara com expected_payer_tax_id.
  • Coincide → a cobrança vira paid e seu saldo é creditado, normalmente.
  • Pagou um documento diferente → a cobrança NÃO é creditada. A Liqfy devolve o dinheiro automaticamente a quem pagou (uma devolução Pix padrão, endereçada pelo end_to_end_id original) e a cobrança termina refunded. Você nunca recebe dinheiro de terceiro.
  • O banco não informou o documento do pagador → a cobrança fica em processing (nunca creditada) para revisão manual, em vez de creditar um pagador não verificável.

Observações:

  • É uma garantia no momento da liquidação, não um bloqueio no banco: o BACEN deixa qualquer pagador ler o QR, então o app do pagador ainda pode exibir a cobrança. A proteção é que um pagamento que não coincide é capturado e devolvido automaticamente — seu saldo de lojista só é creditado para um pagador que coincide.
  • expected_payer_tax_id exige customer.name (necessário na cobrança e para a devolução), precisa ser um CPF (11 dígitos) ou CNPJ (14 dígitos) com dígito verificador válido e — se você também enviar customer.document — precisa coincidir com ele. Caso contrário, a requisição é rejeitada com 400.
  • O valor é devolvido na cobrança (expected_payer_tax_id); o documento real do pagador nunca é exposto.

#2. Consultar a cobrança

Endpoint GET /v1/charges/{id}

bash
curl https://liqfy.com.br/v1/charges/ch_a1b2c3d4-0000-0000-0000-000000000009 \
  -H "apikey: $LIQFY_API_KEY"

Aceita tanto o id com prefixo ch_ quanto o id cru. Depois que o Pix é pago e liquidado, o settlement.end_to_end_id aparece e o status vira paid:

json
{
  "id": "ch_a1b2c3d4-0000-0000-0000-000000000009",
  "object": "charge",
  "status": "paid",
  "amount": 24900,
  "currency": "BRL",
  "payment_method": "pix",
  "customer": { "name": "Maria Silva", "document": "12345678901" },
  "settlement": { "end_to_end_id": "E-END-TO-END-99" },
  "metadata": { "order_id": "ORD-7821" },
  "created_at": "2026-07-23T14:30:00.000Z"
}

#Consultar em laço ou usar webhook?

Use exclusivamente webhook para liberar pedido e gravar no banco — o webhook é a fonte da verdade. O GET /v1/charges/{id} serve para consulta pontual (ferramenta de suporte, um botão "verificar status" que alguém aperta), não para ficar consultando em laço.

#3. Receber o webhook

Quando o pagador paga, você recebe um POST assinado no seu endpoint registrado, com o envelope canônico de evento:

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": { "end_to_end_id": "E-END-TO-END-99" }
    }
  }
}

Veja Webhooks para verificação de assinatura, retentativa e registro do endpoint.

#Exemplos de código

Os trechos abaixo usam HTTP direto. Se preferir, há SDKs oficiais para Node.js, Python e .NET, que já cuidam de idempotência, retry e verificação de webhook.

#Node.js (fetch)

js
const res = await fetch('https://liqfy.com.br/v1/charges', {
  method: 'POST',
  headers: {
    'apikey': process.env.LIQFY_API_KEY,
    'Idempotency-Key': pedido.id,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    amount: 24900,
    currency: 'BRL',
    payment_method: 'pix',
    customer: { name: pedido.cliente.nome, document: pedido.cliente.documento },
    metadata: { order_id: pedido.id },
  }),
});

if (!res.ok) throw new Error(`Liqfy ${res.status}: ${await res.text()}`);
const cobranca = await res.json();
// cobranca.id (ch_…) → guarde no pedido
// cobranca.pix.br_code / qr_code_url → renderize na hora

#PHP

php
$ch = curl_init('https://liqfy.com.br/v1/charges');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST           => true,
  CURLOPT_HTTPHEADER     => [
    'apikey: ' . getenv('LIQFY_API_KEY'),
    'Idempotency-Key: ' . $pedido->id,
    'Content-Type: application/json',
  ],
  CURLOPT_POSTFIELDS => json_encode([
    'amount'         => 24900,
    'currency'       => 'BRL',
    'payment_method' => 'pix',
    'customer'       => ['name' => $pedido->nomeCliente],
    'metadata'       => ['order_id' => $pedido->id],
  ]),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($status !== 201) throw new Exception("Liqfy $status: $body");
$cobranca = json_decode($body, true);

#Python (requests)

python
import os, requests

r = requests.post(
    "https://liqfy.com.br/v1/charges",
    headers={
        "apikey": os.environ['LIQFY_API_KEY'],
        "Idempotency-Key": pedido.id,
    },
    json={
        "amount": 24900,
        "currency": "BRL",
        "payment_method": "pix",
        "customer": {"name": pedido.cliente.nome},
        "metadata": {"order_id": pedido.id},
    },
    timeout=10,
)
r.raise_for_status()
cobranca = r.json()

#Casos de borda e dúvidas

P: Os campos pix.br_code / QR não vieram na resposta. R: A criação Pix-first devolve os dois de forma síncrona. Se faltarem, o status normalmente já vem failed — confira primeiro se a requisição não tem erro de validação (GET /v1/charges/{id} relê a cobrança guardada).

P: Por quanto tempo o QR vale? R: Veja o pix.expires_at da cobrança — é definido por cobrança. Depois de expirar, o status vira expired e é preciso criar uma cobrança nova.

P: Dá para estornar uma cobrança Pix? R: Sim — POST /v1/payments/{id}/refund, total ou parcial (tire o prefixo ch_ para obter o id que ele espera). Veja a Referência da API. Um atalho /v1/charges/{id}/refund ainda não existe.

P: Pago taxa se o cliente nunca pagar? R: Não. A taxa incide só em cobrança paid, e nunca é discriminada na resposta pública de charge.

P: Meu cliente pagou o valor errado. R: O Pix é de valor exato. Cobrança paga a menor continua pending e o banco devolve o pagador. Pagar a mais é raro, e é tratado do mesmo jeito.

#Próximo

Configure webhooks para produção