Realiza cobros con Kushki One
La Payment API te permite procesar cobros presenciales con tarjeta desde tu sistema de caja hacia una terminal Kushki ONE en modo semi-integrado. La terminal gestiona toda la interacción con el tarjetahabiente y el chip EMV: tu sistema envÃa el monto y recibe el resultado.
Requisitos
Cómo funciona
Los payloads y los headers son idénticos entre topologÃas. Las rutas no — cambian cuatro cosas, y están listadas debajo de los base URL.
| TopologÃa | Base URL |
|---|---|
| Red Local (LAN / Wi-Fi) | http://{TERMINAL_IP}:6868/terminal/v1 o https://{TERMINAL_IP}:6869/terminal/v1 |
| Nube (Internet) — UAT | https://uat-cloudt.kushkipagos.com/terminal/v1/{terminalSerial} |
| Nube (Internet) — Producción | https://cloudt.kushkipagos.com/terminal/v1/{terminalSerial} |
Qué cambia entre Nube y red local, más allá del base URL:
| Diferencia | Red Local | Nube |
|---|---|---|
| Ruta de la consulta en lÃnea | /transaction_search_online | /sync/transaction_search_online |
Método de /abort | GET, en ambos modos | POST, solo sÃncrono |
| Abort asÃncrono | Disponible | No existe |
| Rutas de impresión | /terminal/v1/print | /{terminalSerial}/sync/print |
Modos sÃncrono y asÃncrono
Cada operación que requiere interacción con la terminal existe en dos variantes, bajo prefijos de ruta distintos.
| Modo | Prefijo | Comportamiento | Dónde llega el resultado |
|---|---|---|---|
| SÃncrono | /sync/ | Mantiene la conexión abierta hasta que el adquirente responde | En la respuesta HTTP |
| AsÃncrono | /async/ | Responde de inmediato con un acuse TERMINAL_ACKNOWLEDGED. No bloquea | Solo por webhook |
Operaciones disponibles
| Operación | Ruta | SÃncrono | AsÃncrono | Qué hace |
|---|---|---|---|---|
| Venta | /charge | ✅ | ✅ | Cobro inmediato: autoriza y captura en un solo paso |
| Autorización | /authorization | ✅ | ✅ | Reserva fondos sin capturarlos |
| Captura | /capture | ✅ | ✅ | Cobra los fondos de una autorización aprobada |
| Re-autorización | /re_authorization | ✅ | ✅ | Extiende el monto o la vigencia de una autorización activa |
| Post propina | /pos_tip | ✅ | ✅ | Agrega propina a una transacción ya autorizada |
| Reversa | /void | ✅ | ✅ | Reversa una transacción: anulación dentro del dÃa calendario, devolución pasado el corte |
| Cancelar | /abort | ✅ | ✅ | Cancela una operación en curso en la terminal |
| Consulta en lÃnea | /transaction_search_online | ✅ | — | Consulta el historial en el adquirente |
| Consulta local | /transaction_search_local | ✅ | — | Consulta el historial almacenado en la terminal |
Conceptos clave
client_transaction_id
Identificador UUID v4 que genera tu sistema de caja. Funciona como clave de idempotencia: si la terminal ya procesó ese identificador, detecta el duplicado y evita el doble cobro.
Genera uno nuevo por cada venta. ReutilÃzalo solo cuando estés reintentando exactamente la misma operación tras un fallo de red.
transaction_reference
Identificador que genera Kushki y devuelve en la respuesta de cada transacción aprobada, dentro de rawResponse. Es el vÃnculo entre operaciones del mismo ciclo de vida.
Estructura del monto
El objeto amount se envÃa en unidades mÃnimas de la moneda, como número entero. La cantidad de decimales depende del paÃs.
Campos opcionales, por operación
Estos son los únicos campos opcionales, y cada uno pertenece a operaciones especÃficas. Se comportan igual en sÃncrono y asÃncrono.
| Campo | Tipo | Aplica a | Qué hace |
|---|---|---|---|
amount.tip | entero | /charge y /authorization | Agrega propina. Se puede fijar desde la preautorización, no solo al cobrar |
cashback_amount | entero | /charge | Retiro de efectivo adicional a la compra. EnvÃa 0 si no aplica |
deferred / query_deferred | objeto / booleano | /charge | Cuotas. El campo y su forma cambian por paÃs — ver abajo |
omit_card | booleano | /capture, /re_authorization y /void | Con true la operación se ejecuta sin pedir la tarjeta |
metadata | objeto | /charge, /authorization y /pos_tip | Trazabilidad libre: reference, customer_email, device |
En /pos_tip, amount.tip no es un campo opcional — es el monto de la operación.
omit_card es lo que hace funcionar el caso de hotelerÃa: extender o capturar una preautorización cuando el cliente ya no está en el mostrador.
Las cuotas cambian por paÃs
Los dos campos son mutuamente excluyentes y nunca viajan juntos:
| PaÃs | Campo | Forma | Máximo |
|---|---|---|---|
| México | query_deferred | Booleano. La terminal ofrece Meses Sin Intereses al tarjetahabiente después de leer la tarjeta; tu POS no elige los meses | — |
| Chile | deferred | months, más credit_type: "03" para cuotas comercio — string, no número | 12 con credit_type, 48 sin él |
| Colombia | deferred | Solo months. credit_type no aplica | 48 |
| Perú | deferred | Solo months. credit_type no aplica | 2–48, todas las redes |
Si una capacidad no está habilitada para tu terminal, la terminal ignora el campo en vez de rechazar el request — asà que un 200 no prueba que la propina se aplicó. Para habilitarla, escribe a soporte@kushkipagos.com.
Cómo leer el status HTTP
Flujos de pago
Venta directa
El flujo más común en retail. La terminal activa el lector al recibir el request y espera a que el tarjetahabiente complete la interacción.
POST /sync/charge → 200 OK (approved: true)
Pre-autorización y captura
Úsalo cuando el monto final no se conoce al momento de la interacción: hoteles, estaciones de servicio, restaurantes de cuenta abierta.
POST /sync/authorization → guarda transaction_reference↓ (horas o dÃas después)POST /sync/capture → con el transaction_reference guardado
Puedes intercalar /re_authorization para ampliar el monto reservado o extender el plazo antes de capturar. EnvÃa subtotal_iva0: 0 para extender solo la vigencia.
Vigencia de la autorización
| Tipo de tarjeta | Vigencia desde la autorización |
|---|---|
| Débito (Visa / Mastercard) | 7 dÃas |
| Crédito (Visa / Mastercard) | 28 dÃas |
La captura puede llegar hasta el 110% del total autorizado, sumando la autorización y todas las re-autorizaciones no canceladas. Se permite una sola captura por ciclo.
Propina posterior
Agrega una propina a una transacción ya autorizada. Úsalo cuando el tarjetahabiente decide el monto después del cobro inicial. EnvÃa el valor en amount.tip junto al transaction_reference original.
Reversa
Hay un solo endpoint de reversa, /void, y el sistema decide en qué se convierte la operación según cuándo la llamas. El corte es a las 23:59 hora local en los cuatro paÃses: dentro del mismo dÃa calendario la reversa es una anulación; a partir de la medianoche entra al ciclo de devolución y tarda dÃas hábiles.
Espera al menos 1 minuto después de la transacción original antes de reversarla, o falla sin motivo aparente.
El tipo que devuelve la búsqueda de transacciones dice qué terminó pasando:
| Tipo | Qué significa |
|---|---|
VOID | Llamaste /void el mismo dÃa calendario. Anulación — el tarjetahabiente no ve el cargo |
REFUND | Llamaste /void después del corte. Entró al ciclo de devolución y tarda dÃas hábiles |
REVERSE | No lo pediste. Lo genera la plataforma sola cuando falla la comunicación con la terminal |
Autenticación
Kushki ONE usa un solo mecanismo — hash + cifrado — y es el mismo en Nube, red local y localhost: Authorization: Basic <SHA512>, timestamp en segundos, y el cuerpo como el sobre cifrado {"data":"<iv_hex>:<cipher_hex>"}.
Todos los payloads de esta página son el texto plano que se cifra, no lo que viaja por la red. El flujo completo, la cadena de derivación de claves y el árbol de diagnóstico están en Autenticación y cifrado de requests.
Ejemplo de venta directa
Cobro de 12000 unidades mÃnimas sin desglose de impuestos. Lo que representa depende de los decimales del paÃs — revisa Formato de montos en Kushki ONE antes de tu primera integración.
- Javascript
- Python
const payload = {amount: {iva: 0, subtotal_iva: 0, subtotal_iva0: 12000,extra_taxes: { airport_tax: 0, iac: 0, ice: 0, travel_agency: 0 },},client_transaction_id: crypto.randomUUID(),};const res = await fetch(`${BASE_URL}/sync/charge`, {method: "POST",headers: buildHeaders(payload),body: JSON.stringify(payload),});const data = await res.json();console.log(data.approved, data.rawResponse.transaction_reference);
import uuid, requestspayload = {"amount": {"iva": 0, "subtotal_iva": 0, "subtotal_iva0": 12000,"extra_taxes": {"airport_tax": 0, "iac": 0, "ice": 0, "travel_agency": 0},},"client_transaction_id": str(uuid.uuid4()),}res = requests.post(f"{BASE_URL}/sync/charge",headers=build_headers(payload), json=payload)data = res.json()print(data["approved"], data["rawResponse"]["transaction_reference"])
Buenas prácticas
- Genera un
client_transaction_idúnico por venta y reutilÃzalo solo en reintentos de la misma operación. - Persiste el
transaction_referenceen cuanto recibas la respuesta de autorización o cobro. - Verifica que los campos de
amountsumen el total esperado antes de enviar el request. - Registra el
client_transaction_idy el código HTTP de cada operación para facilitar la conciliación y el soporte. - Usa
/abortsolo mientras una transacción está activa en la terminal. Llamarlo después de que completó devuelve409 Conflict. - Firma exactamente los mismos bytes que envÃas: serializa una vez, firma esa cadena y envÃa esa misma cadena.
Servicios asÃncronos y webhooks
Integra el modo asÃncrono: estados del ciclo de vida, estructura de los eventos y polÃtica de reintentos de entrega.
Catálogo de errores
Consulta los modelos de error, códigos por categorÃa y acciones correctivas para todos los endpoints.
Chile
Ecuador
Mexico
Peru