Pular para o conteúdo
xFlow Payments

Blog

Como saber se o Pix foi pago pela API

Para saber se um Pix foi pago pela API da xFlow, assine o webhook transaction.paid e, como reserva, consulte GET /api/v1/charges/{id} até o status sair de pending. Só libere o pedido com status paid, assinatura válida, livemode: true e valor igual ao do pedido.

Atualizado em · Equipe xFlow Payments · 5 min de leitura

Para saber se um Pix foi pago pela API da xFlow, use o webhook transaction.paid como caminho principal e a consulta GET /api/v1/charges/{id} como reserva. Uma cobrança está paga quando o status é paid. Antes de liberar o pedido, o seu sistema confere três coisas: que o aviso é legítimo (assinatura do webhook ou resposta da própria API), que não é teste (livemode: true) e que o valor bate com o do pedido.

O que conta como pago

Na documentação, paid significa pago e confirmado, e o líquido entra no seu saldo. A xFlow confere o pagamento na adquirente antes de lançar o valor no saldo. Só depois disso a cobrança vira paid e o webhook é enviado.

A cobrança paga traz, além do status:

  • paidAt: a data do pagamento, em ISO 8601 (UTC);
  • payer: nome, CPF ou CNPJ e banco de quem de fato pagou, informados pelo PSP;
  • pix.endToEnd: o End-to-end ID, o identificador único da liquidação do Pix.

Os outros status também pedem tratamento: pending (aguardando), expired (expirou sem pagamento), canceled, under_review (em análise), blocked e refunded. Só paid libera o pedido.

Caminho 1: webhook transaction.paid

O webhook avisa o seu servidor sem você perguntar. A cada pagamento confirmado, a xFlow envia um POST para a sua URL, com o header x-webhook-signature (HMAC-SHA256 do corpo cru). O handler deve:

  1. validar a assinatura antes de ler o corpo;
  2. conferir data.status === "paid" e data.livemode === true;
  3. comparar data.amount com o valor do pedido (no webhook o campo é amount; na API, amountCents);
  4. achar o pedido pelo data.external_reference ou pelo data.id;
  5. dar baixa uma vez só, porque o mesmo evento pode chegar de novo;
  6. responder 2xx rápido, para não provocar reenvio.

O código completo, em Node.js e Python, está no guia de webhook Pix.

Caminho 2: consulta do status

A consulta serve quando o webhook ainda não chegou, por exemplo enquanto o cliente está na tela de pagamento, ou quando você quer confirmar um evento antes de liberar algo de valor alto.

js
const BASE = "https://app.xflowpayments.com/api/v1";
const AUTH = "Basic " + Buffer.from(
  `${process.env.XFLOW_PUBLIC_KEY}:${process.env.XFLOW_SECRET_KEY}`,
).toString("base64");
const espera = (ms) => new Promise((ok) => setTimeout(ok, ms));

async function aguardarPagamento(id, { tentativas = 20, intervaloMs = 5000 } = {}) {
  for (let i = 0; i < tentativas; i++) {
    const res = await fetch(`${BASE}/charges/${id}`, { headers: { Authorization: AUTH } });
    if (res.status === 429) {
      await espera(Number(res.headers.get("retry-after") ?? 5) * 1000);
      continue;
    }
    if (!res.ok) throw new Error(`consulta falhou: ${res.status} ${res.headers.get("x-request-id")}`);
    const cobranca = await res.json();
    if (cobranca.status !== "pending") return cobranca; // paid, expired, under_review...
    await espera(intervaloMs);
  }
  return null; // ainda pendente: o webhook ou a varredura resolvem depois
}

Três cuidados com a consulta:

  • Ela conta no limite de requisições, que é por conta. Toda resposta autenticada traz x-ratelimit-remaining; acima do limite, a resposta é 429 com retry-after.
  • Pare quando o status sair de pending. Um laço sem fim por cobrança abandonada consome o limite da conta à toa.
  • O intervalo é escolha sua. A documentação não define frequência de consulta. Escolha um intervalo que caiba no limite da sua conta.

Caminho 3: varredura pela listagem

Se o seu servidor ficou fora do ar por mais tempo do que os reenvios do webhook cobrem, recupere o estado pela listagem:

bash
curl "https://app.xflowpayments.com/api/v1/charges?status=paid&from=2026-10-25&to=2026-10-25&limit=100" \
  -u "pk_live_...:sk_live_..."

A resposta traz data e has_more. Enquanto has_more for true, repita com starting_after igual ao id do último item. Rode a varredura em intervalos e dê baixa nos pedidos que ainda estavam pendentes no seu banco. O mesmo raciocínio, aplicado ao extrato, está em conciliação de pagamentos.

Qual caminho usar em cada situação

Situação Caminho
Baixa automática do pedido Webhook transaction.paid
Cliente esperando na tela de pagamento Webhook, com consulta da cobrança como reserva
Confirmar antes de liberar algo de valor alto Webhook e, em seguida, GET /api/v1/charges/{id}
Servidor ficou fora do ar Listagem com status=paid e o período
Cobrança antiga sem resposta Consulta: pode ter virado expired

A tela do cliente

O navegador ou o app do cliente não chama a API da xFlow, porque a chamada usa o segredo da chave. A tela pergunta ao seu servidor, por exemplo em /pedidos/1234/status, e o servidor responde com o que está no seu banco, atualizado pelo webhook. Só quando o pedido continua pendente por mais tempo que o normal o servidor consulta a API. Assim, muitos clientes olhando a tela ao mesmo tempo não viram uma consulta à API cada um.

Se a cobrança expirar enquanto o cliente espera, ofereça um código novo. O passo a passo está em cobrança Pix expirada.

Não confie em comprovante

Imagem de comprovante enviada pelo cliente não prova pagamento: pode ser editada ou ser de outro Pix. Libere o pedido só com paid vindo da API. Se o cliente insiste que pagou, consulte a cobrança e, se precisar, procure pelo external_reference em GET /api/v1/charges?external_reference=pedido-1234, que mostra todas as cobranças do pedido.

Vale também decidir o que fazer quando quem pagou não é quem comprou. O customer é o que você informou; o payer é quem de fato pagou. Em muitos negócios isso é normal, como um familiar que paga a compra. Em outros, pede uma revisão antes de liberar.

Como testar a verificação

Com a chave de teste, crie a cobrança e chame POST /api/v1/test/charges/{id}/pay. A cobrança vira paid e o webhook transaction.paid chega com livemode: false. Confira se o seu código recusa a baixa de pedidos reais com esse evento e se a consulta devolve paid depois da simulação. O roteiro está em API Pix sandbox, e a referência dos campos na documentação da API.

Perguntas frequentes

Webhook ou consulta: qual usar para verificar o pagamento Pix?

Os dois. O webhook transaction.paid é o caminho principal, porque avisa sem você perguntar. A consulta GET /api/v1/charges/{id} é a reserva, para quando o webhook atrasa, e a listagem com status=paid serve para uma varredura periódica.

O comprovante enviado pelo cliente serve como confirmação?

Não. Imagem de comprovante pode ser editada. O pedido só deve ser liberado quando a API informar status paid, pelo webhook assinado ou pela consulta da cobrança.

O que fazer quando a cobrança está under_review?

Esperar. under_review significa que a cobrança está em análise. Não libere o pedido até a cobrança chegar a paid.

O pagador pode ser outra pessoa?

Pode. customer é o que você informou ao criar a cobrança, e payer é quem de fato pagou, com nome, CPF ou CNPJ e banco informados pelo PSP. Defina no seu sistema o que fazer quando os documentos forem diferentes.

Continue lendo

BlogWebhook Pix: eventos, assinatura HMAC e boas práticasWebhook Pix é o aviso que a API envia para a sua URL quando algo acontece com uma cobrança ou um saque, como o pagamento confirmado. Na xFlow, cada aviso é um POST JSON assinado com HMAC-SHA256, reenviado até 3 vezes até você responder 2xx.BlogCobrança Pix expiradaNa API da xFlow, cobrança Pix expirada é a que passou ao status expired: expirou sem pagamento. Não há webhook de expiração, então você detecta pela consulta ou pela listagem com status=expired e, se o cliente ainda quiser pagar, cria uma cobrança nova para o mesmo pedido, com outra Idempotency-Key.BlogConciliação de pagamentos com várias adquirentesConciliar pagamentos é conferir se cada valor recebido bate com um pedido e com o extrato. Com várias adquirentes, cada uma devolve dados de um jeito. Na xFlow, toda cobrança volta no mesmo formato, com End-to-end ID, dados de quem pagou, a referência do seu pedido, valor, líquido e taxa.BlogAPI Pix sandbox: como testar sem mover dinheiroO sandbox da API Pix da xFlow funciona com chaves pk_test_ e sk_test_: mesmos endpoints, mesmas respostas com livemode: false, nenhum dinheiro real e um endpoint para simular o pagamento que dispara o webhook transaction.paid.GlossárioO que é End-to-end IDEnd-to-end ID (EndToEndId) é o identificador único de uma transação Pix na liquidação. Na API da xFlow, ele aparece no campo pix.endToEnd das cobranças pagas e serve, junto com os dados do pagador, para conciliar o recebimento com o extrato.