Cómo integrar la API PIX de Pagnovo: guía para desarrolladores

Guía práctica de la API Pagnovo: autenticación, creación de cobro PIX, brCode, webhooks con HMAC, sandbox y los errores más comunes al integrar.

Equipo Pagnovo · 2026-08-04

Esta guía cubre el camino completo de una integración PIX con Pagnovo — de la primera llamada autenticada al webhook de confirmación — con el código que realmente funciona en nuestra API.

Referencia completa y siempre actualizada: portal.pagnovo.com/docs.

Antes de empezar: cómo funciona PIX por dentro

PIX es el sistema de pagos instantáneos del Banco Central de Brasil. El pagador inicia el pago, su institución envía la orden al SPI, que valida, debita y acredita — todo en segundos, 24/7.

No te conectas al Banco Central directamente: solo las instituciones autorizadas acceden al SPI. Tu aplicación habla con Pagnovo, que expone una API REST por encima.

Paso 1 — Autenticación

Pagnovo usa autenticación por clave secreta mediante el header Authorization, en formato Basic:

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

Dos detalles importantes:

Opcionalmente puedes configurar una lista blanca de IP para createWithdraw y createRefund. Con ella activa, las llamadas desde otra IP devuelven 400 "IP unauthorized".

Paso 2 — Importes en centavos

Este es el error número uno al empezar: todos los valores monetarios son enteros en centavos.

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

Los cupones porcentuales e intereses usan basis points (1.000 = 10%); las multas fijas, centavos.

Paso 3 — Crear el cobro

POST /transactions/v2/purchase

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

Campos que merecen atención:

La respuesta trae:

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

El brCode es la cadena EMV del copiar-y-pegar; el qrCode, la representación para mostrar.

Paso 4 — Mostrarlo al cliente

Ofrece las dos formas:

Forzar solo el QR a quien está en el celular es una de las mayores causas de abandono.

Paso 5 — Webhooks

Registra el endpoint una vez y elige los eventos:

POST /v2/webhooks

{
  "url": "https://tu-app.com/webhooks/pagnovo",
  "description": "Producción",
  "events": ["cashin.paid", "cashin.refunded", "cashout.success"]
}

La respuesta devuelve un secret en texto plano una sola vez — guárdalo con seguridad. Si lo pierdes, usa POST /v2/webhooks/:id/rotate-secret.

Los eventos disponibles incluyen cashin.paid, cashin.refunded, cashout.success, cashout.failed, cashout.returned, infraction.updated (reemplaza los antiguos CHARGEBACK/BLOCKED) y el ciclo de suscripciones (subscription.created, .activated, .paused, .canceled, .past_due, .expired).

El envelope V2 está estandarizado:

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

Paso 6 — Validar la firma (HMAC)

Nunca proceses un webhook sin validar la firma. Un endpoint abierto es una invitación a que alguien marque pedidos como pagados sin pagar.

Pagnovo firma con HMAC-SHA256 sobre el payload con las claves 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');

// Compara en tiempo constante
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(recibida));

Las tres causas clásicas de firma inválida:

  1. Reserialización diferente — espacios en blanco u orden de claves alterado
  2. Comparación insegura — usar === en vez de comparación en tiempo constante
  3. Secret equivocado — confundir la clave de prueba con la de producción

Paso 7 — Conciliar

El webhook es el camino principal, pero tu aplicación puede estar caída en el momento de la llamada. Mantén una consulta de respaldo para pedidos pendientes:

GET /transactions/:id

Este endpoint acepta el ID de Pagnovo, tu externalId o el end2End del PIX — por eso siempre vale enviar externalId en la creación.

Cada respuesta trae el header x-trace-id; guárdalo en tus logs. Es lo que el soporte usa para encontrar la petición exacta en nuestros servidores.

Paso 8 — Probar en el sandbox

Usa una clave sk_test_*. El sandbox tiene resultados determinísticos por importe, lo que permite probar todos los caminos sin depender de la suerte:

Importe Resultado
R$ 10,00 Aprobado
R$ 10,01 Rechazado
R$ 10,02 Inconsistente
R$ 10,04 Contracargo
R$ 10,05 Reembolso
R$ 10,06 Bloqueado

El entorno de pruebas tiene un límite de 30 operaciones por día (transacciones + retiros + reembolsos).

Errores más comunes

Checklist antes de producción


Empieza por la documentación oficial, crea tu cuenta en portal.pagnovo.com y conoce nuestra API PIX. ¿Dudas en la integración? Habla con el equipo.