Sigue estas recomendaciones para construir una integración presencial confiable y segura.
Idempotencia#
Envía siempre un client_transaction_id único (UUID v4) en cada transacción. Si una petición sufre un timeout o falla por un problema de red, reinténtala con el mismo client_transaction_id: Kushki devuelve el resultado original en vez de crear un cargo duplicado.{
"client_transaction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
Nunca reutilices un client_transaction_id para una transacción distinta. Eso devolvería el resultado de la transacción original en vez de procesar una nueva.
Guarda el transaction_reference#
Toda respuesta aprobada de cargo, autorización y captura incluye un transaction_reference. Guarda ese valor de inmediato: es obligatorio para hacer anulaciones, reembolsos, capturas y reautorizaciones sobre esa transacción.{
"transaction_reference": "f2f29080-0214-42c0-95a5-77ecf3434cd7"
}
Si se pierde la referencia, hay que recuperarla consultando el endpoint Query Transactions con el client_transaction_id original.
Maneja los timeouts con reversos#
Si una petición de cargo sufre un timeout y no sabes si la transacción se procesó:1.
Espera al menos 1 minuto después de la petición original.
2.
Envía un reverso con el mismo client_transaction_id para cancelar de forma segura la transacción incierta.
3.
Los reversos solo son válidos el mismo día y antes de las 22:59 hora local de México.
{
"transaction_type": "charge",
"transaction_mode": "Reverse",
"client_transaction_id": "<same-id-as-original>",
"amount": { "currency": "MXN", "subtotal_iva": 0, "subtotal_iva0": 500, "iva": 0 }
}
Anula antes del corte#
En México las anulaciones son válidas hasta las 22:59 hora local de México del mismo día de la transacción. Pasado ese corte, usa un reembolso.No intentes una anulación después de las 22:59 hora local: la petición será rechazada. Usa POST /pos/v1/refund para transacciones del mismo día pasado el corte o para transacciones de días anteriores.
Usa operaciones sin tarjeta para los flujos de back-office#
Las operaciones sin tarjeta (omit_card: true) están en fase Beta en México. Cuando estén disponibles, úsalas para:Capturas cuando el cliente ya se fue de la terminal
Reautorizaciones desde un sistema de back-office
Anulaciones o reembolsos masivos procesados al cierre del día
Cualquier operación en la que volver a leer la tarjeta no sea práctico
{
"transaction_type": "capture",
"transaction_mode": "Authorization",
"omit_card": true,
"transaction_reference": "f2f29080-0214-42c0-95a5-77ecf3434cd7",
"amount": { "currency": "MXN", "subtotal_iva": 0, "subtotal_iva0": 500, "iva": 0 }
}
Consulta siempre las opciones de MSI antes de diferir#
Antes de iniciar un cargo diferido (MSI — Meses Sin Intereses), llama a los endpoints de consulta de BIN y de opciones de MSI para verificar que la tarjeta admite diferido y obtener los meses válidos.1. POST /pos/v1/bin → check if card supports MSI
2. GET /card/v1/deferred/{bin} → get available months
3. POST /pos/v1/transaction → charge with is_deferred: true
Nunca fijes los meses de diferido en el código: varían según el BIN de la tarjeta y pueden cambiar.MSI exige un monto mínimo de transacción. Contacta a Kushki o revisa la tabla de montos mínimos de MSI antes de enviar un cargo diferido.
Los montos en MXN admiten dos decimales#
El peso mexicano admite dos decimales. Los montos se expresan en pesos (por ejemplo, 500.00 = $500 MXN)."amount": {
"currency": "MXN",
"subtotal_iva": 0,
"subtotal_iva0": 500,
"iva": 0
}
Incluye la ubicación de la terminal#
Envía pos_details.location con las coordenadas GPS de la terminal siempre que estén disponibles. Este dato mejora la detección de fraude y puede ser obligatorio para ciertas categorías de comercio."pos_details": {
"terminal_id": "PB04209860189",
"brand": "SUNMI",
"model": "P2-EU",
"has_print": true,
"location": {
"latitude": 19.4326,
"longitude": -99.1332
}
}
Buenas prácticas de webhooks#
Devuelve HTTP 200 en cuanto recibas una notificación de webhook, antes de ejecutar tu lógica de negocio. Si tu endpoint tarda demasiado, Kushki puede reintentar el envío.Diseña para la idempotencia#
Kushki almacena las notificaciones en varios servidores para lograr alta disponibilidad. En casos poco frecuentes podrías recibir la misma notificación más de una vez. Tu manejador de webhooks debe ser idempotente: procesar la misma notificación dos veces no debe producir efectos duplicados.Valida las firmas de los webhooks#
Verifica siempre la firma del webhook antes de procesar el payload, para asegurarte de que proviene de Kushki.
Política de reintentos#
Si una petición falla con un error 5xx, reinténtala con backoff exponencial:| Intento | Espera antes de reintentar |
|---|
| 1.er reintento | 1 segundo |
| 2.º reintento | 2 segundos |
| 3.er reintento | 4 segundos |
| 4.º reintento | 8 segundos |
No reintentes errores 4xx (por ejemplo, 400, 401, 403): indican un problema con la petición en sí que reintentar no va a resolver.
¿Tienes una sugerencia sobre esta documentación? Contáctanos.