Para gerar um QR Code Pix por cobrança via API, você cria a cobrança e recebe o QR pronto. Na API Pix da xFlow, cada POST /api/v1/charges retorna uma cobrança com id próprio, o valor do pedido, o status pending e o código em dois formatos: pix.qrCodeBase64, uma imagem PNG pronta para a tela, e pix.copyPaste, o mesmo código em texto. Quando o cliente paga, o status muda para paid e o seu sistema recebe o webhook transaction.paid.
QR Code estático x dinâmico
O Banco Central define os tipos de QR Code Pix no Manual de Padrões para Iniciação do Pix. A diferença está em onde ficam os dados do pagamento.
| QR Code estático | QR Code dinâmico | |
|---|---|---|
| Onde ficam os dados | Todos dentro do próprio código | O código traz uma URL; os dados vêm do prestador do recebedor no momento da leitura |
| Chave Pix | Obrigatória | Obrigatória |
| Valor | Opcional | Definido na cobrança |
| Identificador da transação (txid) | Opcional, até 25 caracteres | Obrigatório, de 26 a 35 caracteres |
| Quem gera | A automação do recebedor; não faz parte da API Pix do Banco Central | A API Pix do prestador do recebedor |
| Recursos | Restritos: chave, valor, texto livre, txid | Amplos: conciliação pelo txid, valor configurável, campos estruturados |
O estático é o código fixo, como o cartaz no caixa de uma loja. O mesmo código serve para muitos pagamentos, e o prestador do recebedor não tem como garantir que o txid não se repita. O dinâmico nasce para uma cobrança: tem valor, identificador único para conciliar e prazo de pagamento. Na especificação do Banco Central, esse prazo fica no campo calendario.expiracao, como um número de segundos, e vale 86.400 (24 horas) quando não é informado.
O txid é o identificador que liga o Pix recebido à cobrança. É ele que torna a conciliação automática no modelo do Banco Central.
Por que empresas buscam o QR dinâmico
Quem procura "QR Code Pix dinâmico por API" quase sempre quer resolver três problemas:
- Valor certo em cada pedido. O cliente não digita o valor, então não paga a menos nem a mais.
- Baixa automática. O sistema sabe qual pedido foi pago sem ninguém conferir extrato.
- Um código por venda. Cada pedido tem o seu código e o seu status, com um fim claro: pago ou expirado.
A API da xFlow entrega exatamente isso. Cada cobrança é única, carrega o valor em amountCents, tem o seu external_reference (o id do pedido no seu sistema) e muda de status sozinha. A confirmação chega com payer (quem pagou) e pix.endToEnd, o End-to-end ID do Pix, para bater com o extrato.
Importante: a documentação da xFlow não informa qual dos formatos técnicos do Banco Central o código segue e pede que ele seja tratado como opaco. Para a sua integração, isso não muda nada: você exibe o QR, oferece o copia e cola e espera a confirmação. A conciliação é feita pelo
idda cobrança, peloexternal_referencee pelopix.endToEnd.
Como gerar o QR Code por API
Com cURL:
curl -X POST https://app.xflowpayments.com/api/v1/charges \
-u "pk_live_...:sk_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-1234" \
-d '{
"amountCents": 1990,
"customer": {
"name": "Cliente Exemplo",
"email": "cliente@exemplo.com",
"document": "00000000000"
},
"description": "Pedido #1234",
"external_reference": "pedido-1234"
}'A resposta 201:
{
"id": "clx7a9...",
"livemode": true,
"status": "pending",
"amountCents": 1990,
"external_reference": "pedido-1234",
"pix": {
"copyPaste": "00020101br.gov.bcb.pix...",
"qrCodeBase64": "data:image/png;base64,iVBORw0..."
},
"createdAt": "2026-07-20T00:00:00.000Z",
"request_id": "req_kJ2m9..."
}O pix.qrCodeBase64 já é uma data-URL, então vai direto no HTML: <img src="data:image/png;base64,...">. Se precisar do arquivo, por exemplo para anexar num e-mail, decodifique a parte depois da vírgula. Em Python:
import base64
import os
import requests
resp = requests.post(
"https://app.xflowpayments.com/api/v1/charges",
auth=(os.environ["XFLOW_PUBLIC_KEY"], os.environ["XFLOW_SECRET_KEY"]),
headers={"Idempotency-Key": "pedido-1234"},
json={
"amountCents": 1990,
"customer": {"name": "Cliente Exemplo", "email": "cliente@exemplo.com", "document": "00000000000"},
"description": "Pedido #1234",
"external_reference": "pedido-1234",
},
timeout=30,
)
resp.raise_for_status()
cobranca = resp.json()
# data:image/png;base64,iVBOR... -> bytes do PNG
png = base64.b64decode(cobranca["pix"]["qrCodeBase64"].split(",", 1)[1])
with open("qr-pedido-1234.png", "wb") as f:
f.write(png)Mais exemplos em Python estão em API Pix com Python. Para o lado do texto, veja Pix copia e cola por API.
Ciclo de vida e expiração
A cobrança nasce pending e muda conforme o pagamento:
| Status | O que significa |
|---|---|
pending |
Aguardando pagamento |
paid |
Pago e confirmado; o líquido entra no seu saldo |
expired |
Expirou sem pagamento |
canceled |
Cancelada |
refunded |
Estornada |
under_review |
Em análise |
blocked |
Bloqueada |
A documentação da xFlow não traz um parâmetro para definir a validade do QR nem informa um prazo padrão. O que ela documenta é o status expired. Também não existe webhook de expiração: os eventos de cobrança são transaction.pending, transaction.paid, transaction.refunded e transaction.refund_failed. Na prática:
- Para saber se uma cobrança expirou, consulte
GET /api/v1/charges/{id}ou liste comGET /api/v1/charges?status=expired. - Se o cliente voltar depois de a cobrança expirar, crie uma cobrança nova. Use uma
Idempotency-Keynova, comopedido-1234-2: com a chave antiga e o mesmo corpo, a API devolveria a cobrança anterior. - O
external_referencepode se repetir entre cobranças. Assim, as duas tentativas do mesmo pedido aparecem juntas na busca porexternal_reference=pedido-1234.
Erros comuns ao exibir o QR Code
- Prefixo duplicado. O
pix.qrCodeBase64já começa comdata:image/png;base64,. Se o seu código acrescentar o prefixo de novo, a imagem não carrega. - Imagem distorcida. Exiba o QR em proporção quadrada, sem esticar e sem compressão com perda. Um QR borrado pode não ser lido pela câmera.
- QR de cobrança vencida. Antes de mostrar um código salvo, confira o status. Se a cobrança estiver
expired, gere outra. - Buscar o QR na listagem. A listagem de cobranças não traz
pix.qrCodeBase64nempix.copyPaste. Para mostrar de novo, useGET /api/v1/charges/{id}. - Criar a cobrança no navegador. A chamada à API sai do seu servidor. O segredo
sk_live_nunca vai para o front-end.
Confirmação: webhook primeiro, consulta como reserva
Mostrar o QR é metade do trabalho. A outra metade é saber que ele foi pago. Cadastre um endpoint e ouça transaction.paid. Cada entrega é assinada com HMAC-SHA256 e reenviada até 3 vezes se você não responder 2xx. Como reserva, consulte o status da cobrança pela API. O guia de webhook Pix mostra o handler completo.
Para testar tudo sem dinheiro real, use uma chave de teste: o QR de teste não é pagável, e você simula o pagamento com POST /api/v1/test/charges/{id}/pay. Veja o passo a passo em API Pix sandbox.
Perguntas frequentes
Qual a diferença entre QR Code Pix estático e dinâmico?
No estático, todos os dados do pagamento ficam dentro do próprio código, e só a chave Pix é obrigatória. No dinâmico, o código traz uma URL e os dados da cobrança são buscados no prestador do recebedor na hora da leitura, com identificador obrigatório para conciliar.
A API da xFlow devolve a imagem do QR Code?
Sim. A criação da cobrança retorna pix.qrCodeBase64, um PNG em data-URL pronto para usar numa tag img, e pix.copyPaste com o mesmo código em texto.
Quanto tempo o QR Code da cobrança vale?
A documentação da xFlow não traz um parâmetro nem um prazo de expiração. A cobrança pode passar ao status expired; consulte o status pela API e, se for o caso, crie uma nova cobrança para o pedido.
Preciso de biblioteca para gerar QR Code?
Não. A xFlow entrega a imagem pronta. Você só exibe o pix.qrCodeBase64 e oferece o pix.copyPaste num botão de copiar.