Uma integração Pix está pronta para produção quando cinco coisas estão resolvidas: o segredo da API não sai do servidor, nenhuma repetição gera cobrança ou saque em dobro, o webhook é validado e processado uma vez só, cada pagamento é conciliado pelo End-to-end ID e alguém fica sabendo quando algo falha. A lista abaixo segue a API Pix da xFlow e foi feita para marcar item a item antes de virar a chave. Copie para a ferramenta de tarefas do seu time e só publique com tudo marcado.
Conta e credenciais
- Cadastro da empresa aprovado. Com a conta em análise ou bloqueada, as chamadas de produção recebem
403 account_inactive. - Credencial de produção criada em Desenvolvedores > Chaves de API, com
pk_live_esk_live_. - Segredo
sk_live_guardado num cofre ou variável de ambiente do servidor, fora do repositório, do front-end e dos logs. - Variáveis separadas para teste e produção, sem chance de uma ir para o ambiente da outra.
- Allowlist de IP configurada com os IPs de saída dos servidores que chamam a API.
- Procedimento escrito para trocar e revogar credenciais. A revogação no painel é imediata.
Os detalhes de cada controle estão em segurança na integração da API Pix.
Criação de cobrança
- Valores em centavos, como inteiros: R$ 19,90 é
1990emamountCents. - Limite mínimo e máximo por cobrança da sua conta conferido em Empresa > Limites e taxas. Fora da faixa, a resposta é
400 validatione nada é criado. -
customer.name,customer.emailecustomer.document(CPF ou CNPJ, só dígitos) sempre preenchidos. -
Idempotency-Keyúnico por pedido em todoPOST /api/v1/charges. - Nova chave de idempotência para uma nova tentativa do mesmo pedido, como depois de uma cobrança expirada.
-
409 idempotency_conflicttratado: indica a mesma chave com outro corpo, ou seja, bug no seu código. -
external_referencecom o id do pedido no seu sistema (até 120 caracteres). - Resposta
502 charge_failedcom tratamento definido: nova tentativa com espera crescente ou mensagem ao cliente. - Chamada feita pelo servidor. O navegador e o app falam só com o seu back-end.
- Endpoint de criar cobrança do seu site protegido contra robôs, para não consumir o limite de requisições da conta.
A lógica da idempotência, com exemplos de repetição segura, está em idempotência em API de pagamento.
Tela de pagamento
- QR Code exibido a partir de
pix.qrCodeBase64e copia e cola a partir depix.copyPaste, sem alterar nenhum caractere. - Botão de copiar com aviso de "código copiado" e alternativa quando a área de transferência não estiver disponível.
- Para mostrar o código de novo, consulta por
GET /api/v1/charges/{id}; a listagem não traz o QR. - Status conferido antes de reexibir um código salvo. Não há webhook de expiração: uma cobrança
expiredsó aparece na consulta.
Se você gera o QR no seu lado, siga como gerar o QR Code a partir do Pix copia e cola.
Webhook
- Endpoint de produção cadastrado, com URL
https://pública e certificado válido. - Eventos certos na lista do endpoint:
transaction.paid,transaction.refunded,transaction.refund_failede, se você saca pela API, oswithdrawal.*. - Segredo do endpoint guardado. Ele aparece uma única vez, na criação.
- HMAC-SHA256 validado sobre o corpo cru, com comparação em tempo constante.
-
livemode: trueconferido antes de dar baixa em pedido real. - Valor do evento (
data.amount, em centavos) comparado com o valor do pedido. - Handler idempotente: o mesmo evento pode chegar de novo, e a baixa acontece uma vez só.
- Resposta
2xxlogo depois de gravar o evento; o resto vai para uma fila. - Rota do webhook fora de login, CSRF e regras de WAF que bloqueiem
POSTexterno. - Endpoints de teste e de túnel apagados. O limite é de 20 por conta.
- Varredura periódica com
GET /api/v1/charges?status=paide o período, como reserva para avisos perdidos.
Se algo falhar no primeiro dia, o roteiro de webhook Pix não chega ajuda a achar a causa.
Conciliação
- Gravados por cobrança:
id,external_reference,status,paidAt,pix.endToEndepayer. - Gravados no pagamento:
netefee, que chegam no eventotransaction.paid. - Conciliação com o extrato pelo End-to-end ID, e não por valor e horário.
- Relatório diário com a listagem paginada: repita com
starting_afterenquantohas_morefortrue. - Saldo conferido com
GET /api/v1/balance, que separaavailableereserved. - Regra definida para quando
payerfor diferente decustomer.
O processo completo, com várias adquirentes, está em conciliação de pagamentos.
Estorno e saque
- Regras do estorno conhecidas: total, uma vez por cobrança, só para cobrança
paide até 90 dias após o pagamento. - Resposta
202tratada como "em processamento"; o resultado vem portransaction.refundedoutransaction.refund_failed. - Recusas
422tratadas, comoinsufficient_balance, que trazshortfallCents. -
Idempotency-Keyúnico em todoPOST /api/v1/transfers. - Fluxo de aprovação definido: com o saque automático desligado, o saque nasce com
pending_approval: true. - Separação de funções: quem pede o saque não é quem aprova.
- Se a integração não saca, pergunta feita ao suporte sobre deixar o saque via API desabilitado na conta. Nesse caso, a API responde
403 api_withdrawal_disabled.
Limites, erros e monitoramento
-
429 rate_limitedtratado com espera pelo headerretry-after. - Header
x-ratelimit-remainingacompanhado nos picos de tráfego. -
request_id(req_...) gravado em todo log de chamada à API. - Cada código de erro com uma ação definida, conforme erros da API Pix.
- Alertas para: aumento de
4xxe5xx, picos de401, webhooks recusados pelo seu handler, cobranças pendentes há tempo demais e divergências na conciliação. - Time sabe onde olhar: Integrações > Logs da API (30 dias de retenção) e a página de status.
Testes no sandbox antes da virada
- Fluxo completo com chave de teste: criar cobrança e simular o pagamento com
POST /api/v1/test/charges/{id}/pay. - Evento
transaction.paidrecebido comlivemode: falsee ignorado para pedidos reais. - Evento repetido não gera baixa dupla.
- Corpo com assinatura inválida recusado com
401. - Mesma
Idempotency-Keycom corpo diferente devolvendo409. - Estorno de teste concluído; no sandbox ele conclui na hora.
O roteiro do ambiente de teste está em API Pix sandbox.
No dia da virada
- Variáveis trocadas para
pk_live_esk_live_, e respostas trazendolivemode: true. - Primeira cobrança real de valor baixo criada, paga com um app de banco e confirmada pelo webhook.
- Essa cobrança encontrada no extrato pelo
pix.endToEnd. - Estorno real testado, se o seu negócio usa estorno.
- Saque e split reais de valor baixo, se você usa esses recursos. Os dois não rodam no sandbox, então este é o primeiro teste deles.
- Logs e alertas acompanhados de perto nas primeiras horas.
A referência de cada endpoint e campo citado aqui está na documentação da API.
Perguntas frequentes
O que não dá para testar no sandbox antes do go-live?
Com chave de teste, o copia e cola não é pagável, o split retorna 400, o saque retorna 403 test_mode_unsupported e o saldo vem zerado. Esses pontos só podem ser conferidos em produção, com uma operação real de valor baixo.
Preciso da conta aprovada para ir para produção?
Sim. A chave de teste pode ser criada antes da aprovação do cadastro, mas com a conta em análise ou bloqueada a API responde 403 account_inactive às chamadas de produção.
Como conciliar os pagamentos depois do go-live?
Guarde o id da cobrança, o seu external_reference e, no pagamento, o pix.endToEnd e o payer. O End-to-end ID é o identificador único da liquidação e é o campo para bater cada cobrança com o extrato.
Posso trocar a chave de teste pela de produção sem mudar o código?
Sim. As chaves de teste e de produção usam os mesmos endpoints e formatos. Troque as variáveis de ambiente e confirme que as respostas passam a trazer livemode: true.