Como integrar a API PIX da Pagnovo: guia para desenvolvedores

Guia prático da API Pagnovo: autenticação, criação de cobrança PIX, brCode, webhooks com HMAC, sandbox e os erros mais comuns de quem está integrando.

Equipe Pagnovo · 2026-08-04

Este guia cobre o caminho completo de uma integração PIX com a Pagnovo — da primeira chamada autenticada ao webhook de confirmação — com o código que realmente funciona na nossa API.

Referência completa e sempre atualizada: portal.pagnovo.com/docs.

Antes de começar: como o PIX funciona por trás

O PIX é o sistema de pagamentos instantâneos do Banco Central. O pagador inicia o pagamento, a instituição dele envia a ordem ao SPI, que valida, debita e credita — tudo em segundos, 24/7.

Você não se conecta ao Banco Central diretamente: quem tem acesso ao SPI são as instituições autorizadas. Sua aplicação conversa com a Pagnovo, que expõe uma API REST por cima disso.

Passo 1 — Autenticação

A Pagnovo usa autenticação por chave secreta via header Authorization, no formato Basic:

curl -X POST https://api.pagnovo.com/transactions/v2/purchase \
  -H "Authorization: Basic $(echo -n 'secret:sk_test_SUA_CHAVE' | base64)" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 18990, "description": "Pedido #1042", "externalId": "order-1042" }'

Dois detalhes importantes:

Opcionalmente, você pode configurar uma allowlist de IP para createWithdraw e createRefund. Com ela ativa, chamadas de outro IP retornam 400 "IP unauthorized".

Passo 2 — Valores em centavos

Esse é o erro nº 1 de quem começa: todos os valores monetários são inteiros em centavos.

Valor real Campo amount
R$ 1,00 100
R$ 189,90 18990
R$ 1.500,00 150000

Cupons percentuais e juros usam basis points (1.000 = 10%); multas fixas, centavos.

Passo 3 — Criar a cobrança

POST /transactions/v2/purchase

{
  "amount": 18990,
  "description": "Pedido #1042",
  "externalId": "order-1042",
  "postbackUrl": "https://sua-app.com/webhooks/pagnovo",
  "restrictPayerDocument": true
}

Campos que valem atenção:

A resposta traz:

{
  "id": "...",
  "status": "PENDING",
  "amount": 18990,
  "brCode": "00020126...",
  "qrCode": "..."
}

O brCode é a string EMV do copia-e-cola; o qrCode, a representação para exibir.

Passo 4 — Exibir para o cliente

Ofereça as duas formas:

Forçar só o QR em quem está no celular é uma das maiores causas de abandono.

Passo 5 — Webhooks

Registre o endpoint uma vez e escolha os eventos:

POST /v2/webhooks

{
  "url": "https://sua-app.com/webhooks/pagnovo",
  "description": "Produção",
  "events": ["cashin.paid", "cashin.refunded", "cashout.success"]
}

A resposta devolve um secret em texto puro uma única vez — guarde-o com segurança. Se perder, use POST /v2/webhooks/:id/rotate-secret.

Eventos disponíveis incluem cashin.paid, cashin.refunded, cashout.success, cashout.failed, cashout.returned, infraction.updated (substitui os antigos CHARGEBACK/BLOCKED) e o ciclo de assinaturas (subscription.created, .activated, .paused, .canceled, .past_due, .expired).

O envelope V2 é padronizado:

{
  "event": "cashin.paid",
  "environment": "TEST",
  "payload": { "id": "...", "status": "APPROVED", "amount": 18990 }
}

Passo 6 — Validar a assinatura (HMAC)

Nunca processe um webhook sem validar a assinatura. Um endpoint aberto é um convite para alguém marcar pedidos como pagos sem pagar.

A Pagnovo assina com HMAC-SHA256 sobre o payload com as chaves ordenadas:

import crypto from 'crypto';

function sortObjectKeys(obj: any): any {
  if (Array.isArray(obj)) return obj.map(sortObjectKeys);
  if (obj !== null && typeof obj === 'object') {
    return Object.keys(obj).sort().reduce((acc, key) => {
      acc[key] = sortObjectKeys(obj[key]);
      return acc;
    }, {} as any);
  }
  return obj;
}

const expected = crypto
  .createHmac('sha256', secret)
  .update(JSON.stringify(sortObjectKeys(payload)))
  .digest('hex');

// Compare em tempo constante
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(recebida));

As três causas clássicas de assinatura inválida:

  1. Reserialização diferente — espaços em branco ou ordem de chaves alterada
  2. Comparação não segura — usar === em vez de comparação em tempo constante
  3. Secret errado — confundir a chave de teste com a de produção

Passo 7 — Conciliar

Webhook é o caminho principal, mas sua aplicação pode estar fora do ar na hora da chamada. Mantenha uma consulta de fallback para pedidos pendentes:

GET /transactions/:id

Esse endpoint aceita o ID da Pagnovo, o seu externalId ou o end2End do PIX — por isso vale sempre enviar externalId na criação.

Toda resposta traz o header x-trace-id; guarde-o nos logs. É com ele que o suporte encontra a requisição exata nos nossos servidores.

Passo 8 — Testar no sandbox

Use uma chave sk_test_*. O sandbox tem resultados determinísticos por valor, o que permite testar todos os caminhos sem depender de sorte:

Valor Resultado
R$ 10,00 Aprovado
R$ 10,01 Rejeitado
R$ 10,02 Inconsistente
R$ 10,04 Chargeback
R$ 10,05 Estorno
R$ 10,06 Bloqueado

O ambiente de teste tem limite de 30 operações por dia (transações + saques + estornos).

Erros mais comuns

Checklist antes de produção


Comece pela documentação oficial, crie sua conta em portal.pagnovo.com e conheça nossa API PIX. Dúvidas na integração? Fale com o time.