Guia de QR Code Estático
Guia de QR Code Estático
Este guia explica como gerar QR Codes estáticos PIX pela API e por que essa é a forma recomendada de recebê-los.
Visão Geral
O QR Code estático é um código reutilizável: o mesmo BR Code aceita vários pagamentos, de pagadores diferentes, em momentos diferentes. O valor pode ser fixo ou aberto (digitado pelo pagador no app do banco dele). É o formato certo para:
- Ponto de venda — placa ou adesivo no balcão, totem, mesa de restaurante
- Cobrança recorrente informal — mensalidade, aluguel, contribuição
- Doações e gorjetas — valor aberto, pagador decide quanto
- Link fixo de pagamento — página “pague aqui” que não muda a cada pedido
Se você precisa de uma cobrança única, com valor definido, expiração e conciliação um-para-um com um pedido, use o QR Code Dinâmico.
É tecnicamente possível montar uma string EMV/BR Code estática por conta própria, seguindo a especificação do arranjo PIX, usando apenas a sua chave. O pagamento cai na conta e o crédito é avisado — mas você fica sem o fio que liga o pagamento à cobrança, sem lookup, sem cancelamento e sem as políticas. A seção seguinte explica exatamente o que se perde.
Por que gerar pela API
Um QR estático criado pela API nasce com um identifier seu, validado aqui
e registrado no liquidante. Esse identificador é o fio que costura o pagamento
do começo ao fim: ele volta no webhook, no extrato e no lookup.
Um BR Code montado por fora não tem esse fio registrado em lugar nenhum. O pagamento cai na conta e os webhooks saem, mas o identificador que chega neles é o que você embutiu no código — se é que embutiu algum — e, fora o dinheiro, nada daquele QR existe do nosso lado.
O identificador vira uma aposta
O liquidante repassa o txid embutido no BR Code como identifier do
pagamento. Se você montou o código com um txid seu, ele aparece nos webhooks e
no extrato, e o fio até funciona. Só que esse valor nunca passou pela nossa
validação (38 caracteres, charset [A-Za-z0-9._-], prefixo fee- reservado) e
não corresponde a QR nenhum aqui dentro. Se ele coincidir com o identifier de
um QR dinâmico ativo da mesma conta, o pagamento é atribuído àquela
cobrança, que passa a constar como paga.
O caso mais comum, porém, é o BR Code estático sair com *** no campo de txid —
o placeholder que a especificação prevê para “sem identificador”. Aí o pagamento
chega sem identificador nenhum. Os dois webhooks continuam saindo, com
identifier vazio, e a única forma de conciliar é por aproximação: valor,
horário e pagador.
O que não existe do nosso lado
Como o QR nunca foi criado aqui, não há registro dele. O lookup por identifier
não encontra nada e o DELETE não tem o que cancelar — para tirar o código de
circulação, resta recolher a placa. As regras da seção qrCode da política
também não são avaliadas, porque não houve criação para avaliar. E ninguém
confere se a chave embutida pertence à conta ou se o EMV está bem formado: um
código torto só falha no app do pagador, e você descobre pelo cliente
reclamando.
A API não tem como “adotar” um código gerado por fora. O
POST /v1/accounts/{accountId}/pix/out/qr-code/decode decodifica um BR Code,
mas serve para pagar um QR de terceiro, não para registrar um QR seu de
recebimento. Se o QR já está impresso e circulando montado por fora, o caminho é
gerar um novo pela API e substituir.
Estático ou dinâmico?
Passo 1: Criar o QR Code Estático
Request
Parâmetros do Body
message não chega ao BR Code estático
O campo é aceito e validado, mas hoje não é repassado ao liquidante na
criação do QR estático — ele não aparece para o pagador nem volta preenchido no
message/description da resposta. Se você precisa de texto visível na
cobrança, use o QR dinâmico, que repassa a mensagem.
Escolha um identifier que signifique algo
O identificador é a sua chave de conciliação, e ele volta em todo pagamento
daquele QR. Em QR estático ele identifica o ponto de cobrança, não a venda:
loja-centro-caixa-01, mesa-14, doacao-site. Assim, quando três pagamentos
chegam, você sabe de qual placa cada um veio.
Resposta de Sucesso (201 Created)
Sem envelope data
A resposta é um objeto plano (top-level). Não há envelope data nem os
campos statusCode/title/message. O código copia-e-cola está em emv e a
chave em pixKey.
Note que não há expiresAt: o QR estático não expira. Ele vale até você
cancelar.
A API não deduplica a criação por identifier — não há tratamento de
Idempotency-Key neste endpoint. Antes de recriar um QR que talvez já exista,
consulte pelo lookup (Passo 4). Recriar com um identificador já usado depende da
resposta do liquidante e pode falhar com conflito.
Passo 2: Exibir o QR Code
Gere a imagem a partir da string emv com qualquer biblioteca de QR code
(qrcode.js, python-qrcode, etc.) e ofereça também o copia e cola:
Como o QR estático não expira, a imagem pode ser impressa, colada numa placa ou publicada num site — ela continua válida enquanto o QR não for cancelado.
Passo 3: Receber os Pagamentos por Webhook
Cada pagamento recebido naquele QR dispara dois eventos, e os dois trazem o
seu identifier:
qrcode.paid— “o QR que eu criei foi pago” (conciliação da cobrança)pix.in.completed— “minha conta foi creditada” (ledger, saldo, extrato)
Assine os dois ou só o que fizer sentido para o seu fluxo; eles descrevem o mesmo dinheiro sob ângulos diferentes.
qrcode.paid
Em QR estático, qrcodeId e identifier carregam o mesmo valor: o
identificador que você escolheu na criação. O que distingue um pagamento do
outro é o endToEnd.
O mesmo QR pago cinco vezes gera cinco qrcode.paid, cada um com seu
endToEnd. Não trate o primeiro evento como “cobrança quitada” e pare de
escutar — o código continua ativo. Use o endToEnd como chave de deduplicação
das suas próprias baixas.
Não existem qrcode.expired nem qrcode.cancelled para QR estático: ele não
expira, e o cancelamento é uma ação sua, síncrona, cuja confirmação é a resposta
HTTP do DELETE.
Passo 4: Conciliar
O identifier do QR aparece nos dois lugares onde você procura dinheiro:
No extrato, cada lançamento traz o campo identifier:
Os parâmetros são startDate/endDate (YYYY-MM-DD)
from/to não são reconhecidos. Como a rota assume o dia de hoje quando
não recebe as datas, mandar ?from=...&to=... não dá erro — devolve
silenciosamente o extrato de hoje. Janela máxima: 31 dias.
No lookup de pagamento, você busca direto pelo identificador:
Consultar o estado do QR
A resposta é o mesmo objeto plano da criação, acrescido dos campos de pagamento
quando há algum: paidAmount, endToEndId, paidAt, payer.
Num QR reutilizável, o lookup reflete o último pagamento conhecido pelo
liquidante, e o status passa a PAID depois do primeiro. Ele não lista os
pagamentos anteriores. Para o histórico completo, use os webhooks qrcode.paid
ou o extrato filtrado por período.
Status possíveis: ACTIVE, AWAITING-PAYMENT, PAID, CANCELLED, EXPIRED,
UNKNOWN — sempre em MAIÚSCULAS.
Passo 5: Cancelar o QR Code
Um QR estático vale até ser cancelado. Cancele quando a placa sai de circulação, o caixa é desativado ou a campanha termina:
Resposta (200 OK):
Depois do cancelamento, o BR Code impresso deixa de ser cobrável — quem escanear recebe erro no app do banco.
Políticas
A criação de QR estático passa pela seção qrCode da política do tenant ou da
conta. Uma violação devolve 422 com errorCode: policy_denied e a lista de
violations:
As regras de valor não se aplicam a QR aberto: sem value na criação, não
há montante para comparar, e as duas são puladas. Se o seu controle de valor
precisa valer sempre, não use QR aberto. Detalhes em
Políticas e Regras.
Escopo Necessário
Uma credencial só com qrcode.manage cria e acompanha QR codes sem enxergar
saldo e extrato da conta. Ver o Guia de Autenticação.
Boas Práticas
- Gere sempre pela API — um BR Code montado por fora custa a conciliação, o lookup e o cancelamento
- Dê nome ao ponto de cobrança — o
identifierdo QR estático identifica a placa/caixa/campanha, não a venda - Deduplique pelo
endToEnd— é o que distingue um pagamento do outro no mesmo QR - Não confie só no lookup — ele mostra o último pagamento; o histórico está nos webhooks e no extrato
- Cancele o que saiu de circulação — QR estático não expira sozinho
- Prefira valor fixo quando houver limite de política — QR aberto pula as regras de
minAmount/maxAmount
Erros Comuns
Os erros vêm no formato { "errorCode": "...", "message": "..." }:
Exemplo:
Lista completa em Erros.
Próximos Passos
- Guia de QR Code Dinâmico - Cobranças únicas com valor e expiração
- Guia de Devolução - Devolver um pagamento recebido
- Webhooks - Configurar as notificações