1. Kushki One
Kushki Docs
Español
  • Español
  • English
  • Inicio
  • Inicio rápido
    • Preguntas frecuentes
    • Paso a producción
    • Política de cambios importantes del API
    • Códigos de error
    • Datos de prueba
    • Últimas novedades
  • Glosario de pagos
    • Glosario de pagos
  • Pagos únicos con tarjeta (Online)
    • Network Tokens
    • Funcionalidades por modelo de negocio
    • Marcas de tarjeta soportadas
    • Pagos en un paso
      • Cargo directo (sin token)
      • Códigos de error autenticación OTP
      • ¿Cómo funcionan los pagos con tarjeta?
      • Acepta un pago con tarjeta
      • Acepta pagos únicos con OTP
      • Códigos de error pagos únicos con tarjeta
    • Pagos en dos pasos
      • Recibe pagos con autorización y captura
      • ¿Cómo funcionan los pagos únicos con autorización y captura?
    • Pagos con Webpay Plus
      • Reserva fondos con Webpay Plus
    • Pagos con Apple Pay
      • Pruebas en Sandbox Apple Pay
      • Configuración de Apple Pay
    • Devoluciones
      • Devoluciones, anulaciones y reembolsos
    • Autenticación 3DS
      • Introducción a 3DS
      • Integración 3DS API + librería kushki.js
      • Integración 3DS con librería kushki.js
      • Integración 100% API de 3DS
      • Códigos de error autenticación 3DS
  • Pagos recurrentes con tarjeta (Online)
    • Autentica tus suscripciones con 3DS
    • Apple Pay en Suscripciones
    • Suscripciones externas a Kushki
    • Acepta pagos one click con 3DS
    • Funcionalidades por modelo de negocio
    • Códigos de error en cargos recurrentes
    • Pagos calendarizados
      • Maneja tus cargos calendarizados
      • Crea un cargo recurrente
      • ¿Cómo funcionan los cargos recurrentes con tarjeta?
    • Pagos calendarizados con Webpay OneClick
      • Reserva fondos en recurrencias con Webpay OneClick
      • Recurrencias con Webpay OneClick
    • Pagos OneClick con Webpay OneClick
      • Pagos one click con Webpay OneClick
      • Reserva fondos en pagos one click con Webpay OneClick
    • Pagos OneClick
      • ¿Cómo funcionan los pagos OneClick con autorización y captura?
      • Recibe pagos OneClick con autorización y captura
      • Genera pagos one click
  • Pagos con tarjeta presente
    • Acepta pagos con tarjeta presente
    • Datos de prueba
    • Webhooks para tarjeta presente
    • Raw card-present API
      • Script de ejemplo para cifrar información
      • Acepta pagos
      • Intercambio de claves criptográficas
      • Preguntas frecuentes
      • Códigos de error para transacciones con tarjeta presente
    • Transacciones
      • Anula un pago
      • Transacciones
    • Kushki One
      • Autenticación y Cifrado de Requests
      • Realiza cobros con Kushki One
      • Formato de montos en Kushki ONE
      • Impresión en terminal SmartPOS
      • Catálogo Unificado de Errores — Kushki ONE Connect
      • Servicios asíncronos y webhooks
    • Kushki One App de Pagos
      • Procesa un cobro
      • Devoluciones y PreAuth & Capture
      • Pago Dividido en la terminal
      • Configuración del terminal
      • Consulta tus transacciones
  • Pagos con transferencias
    • Recibe transferencias bancarias
    • Consulta el estado de una transacción
    • Bancos y detalles de operación para pagos con transferencia bancaria
  • Pagos en efectivo
    • Acepta un pago en efectivo
    • Puntos de recaudo
    • Códigos de error para transacciones declinadas en efectivo
  • Dispersión de dinero
    • Transferencia bancaria
      • ¿Cómo funciona la dispersión por transferencia bancaria?
      • Códigos de error para dispersiones por transferencia
      • Dispersa a cuentas bancarias
  • Plugins
    • Shopify
      • Shopify
      • Operación del Plugin
    • Vtex
      • Guía de integración VTEX
  • Links de pago
    • Smartlinks
  • Formularios y botones de pago
    • Introducción
    • Kajita
      • Kajitas de pago
      • ¿Cómo funciona?
    • Botón de pago
      • Genera un botón de pago
      • ¿Cómo funciona el botón de pago?
  • Administración de sucursales
    • ¿Cómo realizar el onboarding de subcomercios vía API?
  • Notificaciones
    • Buenas prácticas
    • Consulta tus webhooks
    • Webhooks para pagos únicos
      • Webhook para pagos únicos con tarjeta
      • Webhook para pagos únicos con transferencia bancaria
      • Webhook para pagos únicos con efectivo
      • Webhook para pagos con Webpay Plus
    • Webhooks para pagos recurrentes
      • Webhook para pagos recurrentes con tarjeta
      • Webhook para pagos recurrentes con Webpay OneClick
    • Webhooks para dispersiones
      • Webhook para dispersión de dinero con transferencia
    • Webhooks para botón de pagos
      • Webhooks con Botón de pago
    • Webhooks para smartlinks
      • Webhooks con Smartlinks
    • Webhooks para devoluciones
      • Webhook para devoluciones
      • Webhook para contracargos
HomeMexico 🇲🇽Ecuador 🇪🇨Chile 🇨🇱
Colombia 🇨🇴Peru 🇵🇪
HomeMexico 🇲🇽Ecuador 🇪🇨Chile 🇨🇱
Colombia 🇨🇴Peru 🇵🇪
Status
Soporte / Support
Español
  • Español
  • English
  1. Kushki One

Impresión en terminal SmartPOS

🚧 Early Release — Beta
Este producto está en acceso temprano. Los parámetros, estructuras de respuesta y comportamientos pueden cambiar sin previo aviso. No uses esta versión en producción sin coordinarlo previamente con el equipo de integraciones de Kushki.
La Print API te da control total sobre la impresora térmica integrada en las terminales Kushki ONE. Imprime cualquier contenido desde tu sistema de caja —antes, durante o después de una transacción, o sin relación con ninguna— sin instalar drivers, SDK ni configurar hardware de tu lado.

Requisitos#

Antes de empezar
Una terminal Sunmi P3 o P2 SE con impresora térmica integrada, vinculada a tu comercio.
Tu Business-Code para firmar los requests.
El terminalSerial del dispositivo si integras por Nube.

Cómo funciona#

El ciclo de impresión tiene dos partes: un request síncrono que encola el trabajo y una notificación asíncrona que te informa cuando terminó.
Diagrama de secuencia de la Print API de Kushki ONE
1.
Tu sistema de caja construye un arreglo commands con el diseño del ticket.
2.
Envías el request de creación del trabajo. La terminal responde 202 Accepted de inmediato.
3.
La impresión se ejecuta de forma asíncrona en el hardware.
4.
Conoces el resultado final por webhook o consultando el estado.
Los payloads y los headers son idénticos en todas las topologías. Las rutas no: el base URL termina en la terminal, y cada ruta lleva su propio prefijo.
TopologíaBase URL
Red Local (LAN / Wi-Fi)http://{TERMINAL_IP}:6868/terminal/v1 o https://{TERMINAL_IP}:6869/terminal/v1
Nube (Internet) — UAThttps://uat-cloudt.kushkipagos.com/terminal/v1/{terminalSerial}
Nube (Internet) — Producciónhttps://cloudt.kushkipagos.com/terminal/v1/{terminalSerial}
Rutas por topología
En Red Local encolas con POST /terminal/v1/print y consultas con GET /terminal/v1/print_job. En Nube encolas con POST /sync/print y consultas con POST /sync/print_job. Revisa la sección Consulta el estado para el detalle de cada método.

Autenticación#

La impresión usa el mismo mecanismo que las operaciones de pago — hash + cifrado, el único que tiene Kushki ONE:
ElementoValor
AuthorizationBasic seguido del hash SHA-512. El prefijo Basic es obligatorio
timestampUnix timestamp en segundos, dentro de ±5 minutos de la hora del servidor
CuerpoEl sobre cifrado {"data": "<iv_hex>:<ciphertext_hex>"}
El array commands que se muestra en esta página es el texto plano que se cifra, no lo que viaja por la red. El flujo completo está en Autenticación y cifrado de requests.
Red Local y Localhost: envía el header encrypted_http_communication
En Red Local y Localhost, cada request lleva además el header encrypted_http_communication: true, en UAT y en producción. Nube no lo requiere. Detalle en Autenticación y cifrado de requests.
La consulta de estado es un GET en red local
En red local consultas el estado con GET, así que el valor cifrado viaja como query param data y no puede ir ningún otro parámetro: el print_job_id va dentro del payload cifrado.

Casos de uso#

La API no se limita a comprobantes de pago. Cualquier contenido que tu negocio necesite entregar en papel se dispara desde tu sistema de caja.
Caso de usoDescripción
Comprobante de pagoVenta directa, captura de pre-autorización, devolución o anulación
Cupón de descuentoCódigo para la próxima compra del cliente
Código QRContraseña de Wi-Fi, enlace de fidelización, recibo digital, información de producto
Fidelización y promocionesSaldo de puntos, niveles de recompensa, ofertas especiales
Pre-cuenta o resumen de ordenTicket de cocina o resumen de mesa antes del cobro final
Constancia de reversoComprobante impreso de una cancelación o devolución
ReimpresiónVuelve a imprimir un ticket anterior con el mismo printJobId
Contenido libreTexto, imagen, QR o código de barras, sin necesidad de una transacción
El arreglo commands es un lienzo en blanco
No estás limitado a ninguna plantilla ni formato predefinido. Combina texto, imágenes, códigos QR, códigos de barras, columnas y separadores en el orden que tu negocio necesite.

Anatomía de un ticket#

Cada sección visual del recibo corresponde a un tipo de comando dentro del arreglo commands.
Anatomía de un ticket y su mapeo a comandos de la Print API

Estructura del request#

CampoTipoRequeridoDescripción
commandsarreglo✅Lista ordenada de comandos de impresión
printJobIdtexto—Clave de idempotencia. Si lo omites, se genera un UUID
externalReferencetexto—Referencia libre de tu integración, por ejemplo Mesa-14
webhookUrltexto—URL que recibirá el resultado cuando el trabajo termine
skipIfBusybooleano—Con true, devuelve 409 de inmediato si la cola está ocupada. Por defecto false

Tipos de comandos#

TipoDescripción
textLínea de texto con tamaño, alineación, negrita, cursiva y subrayado
columnsFila multicolumna con anchos proporcionales, ideal para producto y precio
dividerLínea separadora a todo el ancho: SOLID, DOTTED o EMPTY
feedAvanza el papel N líneas en blanco
spaceInserta espacio vertical preciso en píxeles
cutActiva la cuchilla de corte. Se ignora de forma segura en terminales sin cuchilla
imageImprime una imagen PNG o JPG en Base64. Usa algorithm: BINARIZATION para logotipos
qrGenera un código QR en el hardware de la impresora
barcodeGenera un código de barras CODE128 en el hardware
Reglas de los comandos
La propiedad type es obligatoria en cada comando: es el discriminador que define su estructura.
Los valores de tipo enumerado (align, dividerType, errorLevel, algorithm) van siempre en mayúsculas.
Las imágenes se envían como Base64 puro, sin el prefijo data:image/png;base64,.

Ejemplo completo#

Este request construye un recibo con logotipo, encabezado, ítems, total, código QR y corte automático.
{
  "printJobId": "TICKET-190209",
  "externalReference": "Mesa-14",
  "webhookUrl": "https://api.tunegocio.com/webhook/print-events",
  "skipIfBusy": false,
  "commands": [
    { "type": "image", "base64Image": "iVBORw0KGgoAAAANSUhEUg...", "align": "CENTER", "width": 300, "algorithm": "BINARIZATION" },
    { "type": "text", "text": "RESTAURANTE EL BUEN SABOR\n", "align": "CENTER", "size": 32, "bold": true },
    { "type": "text", "text": "NIT: 900.123.456-7\n", "align": "CENTER", "size": 22 },
    { "type": "divider", "dividerType": "DOTTED" },
    { "type": "columns", "columns": [
        { "text": "2x Combo Hamburguesa", "weight": 2, "align": "LEFT" },
        { "text": "30,000.00 COP", "weight": 1, "align": "RIGHT" } ] },
    { "type": "columns", "columns": [
        { "text": "1x Jugo Natural", "weight": 2, "align": "LEFT" },
        { "text": "8,000.00 COP", "weight": 1, "align": "RIGHT" } ] },
    { "type": "divider", "dividerType": "SOLID" },
    { "type": "columns", "columns": [
        { "text": "TOTAL", "weight": 2, "align": "LEFT" },
        { "text": "38,000.00 COP", "weight": 1, "align": "RIGHT" } ] },
    { "type": "qr", "content": "https://tunegocio.com/recibo/TICKET-190209", "dotSize": 6, "errorLevel": "M", "align": "CENTER" },
    { "type": "feed", "lines": 3 },
    { "type": "cut" }
  ]
}
Envía el request desde tu back-end:
JavaScript
Python
La terminal responde de inmediato:
{
  "printJobId": "TICKET-190209",
  "status": "PENDING",
  "message": "Impresión encolada correctamente"
}
CódigoSignificado
202 AcceptedTrabajo encolado. Devuelve el printJobId y estado PENDING
400 Bad RequestPayload mal formado o valor de enumerado desconocido
409 ConflictYa existe un trabajo en PENDING o IN_PROGRESS

Resultado del trabajo#

Tienes dos mecanismos para conocer el resultado final. Puedes usar uno o ambos en paralelo.

Opción A: webhook#

Si enviaste webhookUrl al encolar, la terminal hace un POST hacia esa URL cuando el trabajo cambia a COMPLETED o FAILED.
Trabajo exitoso
{
  "printJobId": "TICKET-190209",
  "status": "COMPLETED",
  "externalReference": "Mesa-14"
}
Fallo de hardware
{
  "printJobId": "TICKET-190209",
  "status": "FAILED",
  "externalReference": "Mesa-14",
  "errorCode": "OUT_OF_PAPER",
  "errorMessage": "La impresora está sin papel."
}
Este webhook no se reintenta
Si tu servidor no responde con un código 2xx en 5 segundos, la terminal no reintenta: continúa su flujo para no bloquear la impresora. Responde rápido, haz tu endpoint idempotente y usa la consulta de estado como respaldo en flujos donde perder la confirmación sea costoso.
Este comportamiento es distinto al del webhook de transacciones, que sí reintenta con retroceso exponencial.
El campo es webhookUrl
No lo confundas con events_webhook_url, que corresponde al webhook de transacciones. Los dos canales usan nombres de parámetro distintos y no comparten política de entrega.

Opción B: consulta el estado#

Úsalo cuando tu sistema no puede recibir conexiones entrantes desde la terminal, o como respaldo del webhook.
Red Local
GET /terminal/v1/print_job?print_job_id=TICKET-190209
Nube
POST /terminal/v1/{terminalSerial}/sync/print_job
{
  "print_job_id": "TICKET-190209"
}
En Nube el identificador va en el cuerpo
La consulta por Nube usa POST y envía print_job_id en el cuerpo del request, no como parámetro de consulta en la URL. Enviarlo en la URL devuelve un error de validación.
Consulta cada 2 o 3 segundos y detén el sondeo cuando status sea COMPLETED o FAILED.
{
  "printJobId": "TICKET-190209",
  "status": "COMPLETED"
}

Estados del trabajo#

statusDescripción
PENDINGEn cola, esperando turno
IN_PROGRESSEl driver está enviando comandos a la impresora
COMPLETEDTicket impreso y cortado correctamente
FAILEDError físico durante la impresión. Revisa errorCode
El webhook solo notifica estados finales
No recibirás notificaciones de PENDING ni IN_PROGRESS. Si necesitas seguir esos estados intermedios, usa la consulta de estado.

Códigos de error de hardware#

Los valores posibles de errorCode son OUT_OF_PAPER, COVER_OPEN, COVER_INCOMPLETE, PAPER_JAM, PRINTER_HOT, MOTOR_HOT, CUTTER_ERROR, OFFLINE y UNKNOWN_ERROR. Llegan con type: TERMINAL-PRINTER en el cuerpo del error.
Una cola ocupada no es uno de ellos: llega como TER-004 con type: TERMINAL, y por HTTP como un 409.
Los endpoints de impresión sí devuelven códigos HTTP reales
A diferencia de las operaciones de pago — donde el status es siempre 200 y el resultado va en el cuerpo — la impresión responde 202 cuando el job se encola, 404 cuando el print_job_id no existe y 409 mientras la impresora está ocupada.
Y TER-004 significa dos cosas distintas: en un endpoint de impresión la impresora está ocupada y reintentas en unos segundos; en un endpoint de pago el tarjetahabiente canceló en la terminal y no debes reintentar. El endpoint que llamaste te dice cuál es.

Buenas prácticas#

Envía un printJobId propio para poder reimprimir el mismo ticket y para descartar duplicados en tu sistema.
Usa externalReference para vincular el ticket con tu orden, mesa o factura.
Responde 2xx al webhook antes de procesarlo. Un endpoint lento hace que pierdas la notificación.
Trata FAILED como una condición operativa, no como un error de tu integración: muestra el errorMessage al operador para que resuelva el problema físico.
Envía las imágenes ya binarizadas y del ancho correcto. Un logotipo pesado alarga el tiempo de impresión.
Acepta cobros con Kushki ONE
Procesa cobros presenciales y combínalos con la impresión del comprobante.
Errores de impresora
Consulta la causa y la acción recomendada para cada código de error de hardware.
Modificado en 2026-10-21 16:28:33
Anterior
Formato de montos en Kushki ONE
Siguiente
Catálogo Unificado de Errores — Kushki ONE Connect
Built with