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
Todos los endpoints comparten la misma estructura de request y respuesta, sin importar cómo conectes tu caja con la terminal. Lo único que cambia entre topologías es el base URL.
| Topología | Base URL |
|---|---|
| Red Local (LAN / Wi-Fi) | http://{TERMINAL_IP}:6868/terminal/v1 |
| Nube (Internet) — UAT | https://uat-cloudt.kushkipagos.com/terminal/v1/{terminalSerial} |
| Nube (Internet) — Producción | https://cloudt.kushkipagos.com/terminal/v1/{terminalSerial} |
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 |
| Anulación | /void | ✅ | ✅ | Anula una transacción el mismo día, antes del corte |
| Devolución | /refund | ✅ | — | Devuelve fondos de una transacción ya liquidada |
| 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 de la venta
Estos campos aplican a /charge. La terminal gestiona los diálogos con el tarjetahabiente y ignora el campo cuando la funcionalidad no está habilitada en el DMS.
| Campo | Tipo | Qué hace |
|---|---|---|
amount.tip | entero | Agrega propina al total |
cashback_amount | entero | Retiro de efectivo adicional a la compra. Envía 0 si no aplica |
query_deferred | booleano | Con true, la terminal ofrece opciones de cuotas al tarjetahabiente |
En /re_authorization dispones además de omit_card: con true, la operación se ejecuta sin pedir la tarjeta.
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.
Anulación y devolución
| Operación | Cuándo la usas |
|---|---|
Anulación (/void) | El mismo día de la transacción, antes del horario de corte del procesador |
Devolución (/refund) | Cuando la transacción ya se liquidó, o si pasó el horario de corte |
Autenticación
Incluye estos headers en cada request:
| Header | Valor |
|---|---|
Authorization | Firma HMAC-SHA256 del cuerpo del request, codificada en Base64, usando tu Business-Code como llave |
timestamp | Unix timestamp en milisegundos |
Ejemplo de venta directa
Cobro de 120.00 COP sin desglose de impuestos.
- 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