Kushki envía notificaciones de webhook a tu servidor por cada evento de transacción presencial: cargos, autorizaciones, capturas, anulaciones, reversos y reembolsos. Tu endpoint recibe el payload del evento inmediatamente después de que la terminal confirma la operación.Los webhooks de pagos presenciales se configuran desde la Kushki Console, en Desarrolladores → Webhooks. La configuración de webhooks por API no está soportada para pagos presenciales.
Eventos soportados#
| Evento | Se dispara cuando |
|---|
approvedTransaction | Se aprueba un cargo, una autorización o una captura |
declinedTransaction | El emisor o la red rechaza una transacción |
initializedTransaction | Se inicializa una autorización en dos pasos |
voidTransaction | Se completa una anulación o un reverso |
refundTransaction | Se completa un reembolso |
Payload del webhook#
Todos los eventos comparten un envelope común. Los campos transactionType y transactionStatus identifican el evento específico.{
"transactionType": "SALE",
"transactionStatus": "APPROVAL",
"transactionId": "1234567890abcdef",
"ticketNumber": "987654321",
"clientTransactionId": "ae6dd41a-9173-4ec7-8734-3178454ef341",
"amount": 500.00,
"currency": "PEN",
"responseCode": "000",
"responseText": "APPROVED",
"approvalCode": "123456",
"cardType": "credit",
"paymentBrand": "VISA",
"maskedCard": "XXXXXXXXXXXX1234",
"binCard": "411111",
"isDeferred": false,
"merchantId": "<your-merchant-id>",
"created": "2026-01-01T14:32:00.000Z",
"processorBankName": "BCP",
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2",
"posDetails": {
"brand": "SUNMI",
"model": "P2-EU",
"serialNumber": "SN71652",
"terminalId": "TID001"
}
}
Campos principales#
| Campo | Descripción |
|---|
transactionType | SALE, AUTHORIZATION, CAPTURE, VOID, REVERSE, REFUND |
transactionStatus | APPROVAL, DECLINED, INITIALIZED |
ticketNumber | Ticket de la transacción asignado por Kushki; úsalo para la conciliación |
clientTransactionId | El UUID que enviaste en la petición original |
transactionReference | Referencia a nivel de adquirente; obligatoria para anular, capturar y reembolsar |
approvalCode | Código de aprobación del emisor (presente en transacciones aprobadas) |
responseCode | Código de respuesta ISO 8583; 000 significa aprobada |
posDetails.serialNumber | Número de serie de la terminal que procesó la transacción |
Referencia de tipos de transacción#
Cargo (SALE)#
Se dispara cuando se completa un pago único.{
"transactionType": "SALE",
"transactionStatus": "APPROVAL",
"amount": 500.00,
"currency": "PEN",
"isDeferred": false
}
En cargos diferidos, isDeferred es true y se incluye un objeto deferred:{
"transactionType": "SALE",
"transactionStatus": "APPROVAL",
"isDeferred": true,
"deferred": {
"months": "6",
"monthlyAmount": 83.33
}
}
Autorización (AUTHORIZATION)#
Se dispara cuando se realiza una preautorización en dos pasos.{
"transactionType": "AUTHORIZATION",
"transactionStatus": "INITIALIZED",
"amount": 500.00,
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2"
}
Captura (CAPTURE)#
Se dispara cuando se captura una autorización.{
"transactionType": "CAPTURE",
"transactionStatus": "APPROVAL",
"amount": 500.00,
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2"
}
Anulación (VOID)#
Se dispara cuando se anula una autorización o un cargo del mismo día.{
"transactionType": "VOID",
"transactionStatus": "APPROVAL",
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2"
}
Reverso (REVERSE)#
Se dispara cuando una transacción se reversa a nivel del adquirente.{
"transactionType": "REVERSE",
"transactionStatus": "APPROVAL",
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2"
}
Reembolso (REFUND)#
Se dispara cuando se reembolsa una transacción liquidada, total o parcialmente.{
"transactionType": "REFUND",
"transactionStatus": "APPROVAL",
"amount": 250.00,
"transactionReference": "718fa526-6f41-405f-a1f5-a71db52dfdd2"
}
Verificación de la firma#
Kushki firma cada petición de webhook con una firma HMAC-SHA256. Verifícala antes de procesar el payload para asegurar su autenticidad.Cabeceras#
| Cabecera | Valor |
|---|
X-Kushki-Signature | HMAC-SHA256 del body crudo de la petición, codificado en Base64 |
X-Kushki-Timestamp | Timestamp Unix en milisegundos del momento en que se envió el evento |
Verificación (ejemplo en Node.js)#
Verifica siempre la firma antes de confiar en el payload. Rechaza cualquier petición en la que la verificación falle.
Política de reintentos#
Si tu endpoint no devuelve HTTP 2xx dentro de la ventana de timeout, Kushki reintenta la entrega con backoff exponencial:| Intento | Espera |
|---|
| 1.er reintento | 1 minuto |
| 2.º reintento | 5 minutos |
| 3.er reintento | 30 minutos |
| 4.º reintento | 2 horas |
| 5.º reintento | 8 horas |
Después de 5 intentos fallidos el evento se marca como no entregado. Puedes reenviarlo desde Console → Desarrolladores → Webhooks → Event Log.
Buenas prácticas#
| Práctica | Motivo |
|---|
Responde de inmediato con 200 | Evita timeouts; procesa de forma asíncrona |
| Guarda el payload crudo antes de procesarlo | Permite reprocesarlo si el procesamiento falla |
Usa ticketNumber como llave de idempotencia | Protege contra entregas duplicadas |
Verifica X-Kushki-Signature en cada petición | Rechaza payloads falsificados o alterados |
Revisa X-Kushki-Timestamp | Rechaza eventos con más de 5 minutos de antigüedad para prevenir ataques de repetición |
Configuración#
Configura tus endpoints de webhook en la Kushki Console:1.
Ve a Desarrolladores → Webhooks
4.
Selecciona los eventos de pagos presenciales a los que quieres suscribirte
5.
Copia el Signing Secret y guárdalo de forma segura en tu entorno
Tu URL de webhook debe ser accesible públicamente por HTTPS. No se aceptan endpoints HTTP.
¿Tienes una sugerencia sobre esta documentación? Contáctanos.