Impresión en terminal SmartPOS
Impresión en terminal SmartPOS
La Print API te da control total sobre la impresora térmica integrada en los terminales Kushki ONE (Sunmi P3, Sunmi P2 SE). Puedes imprimir cualquier contenido desde tu sistema de caja — antes, durante o después de una transacción, o completamente independiente de una — sin necesidad de drivers, SDKs ni configuración de hardware en tu lado.
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ó.
- Tu sistema de caja construye un arreglo
commandscon el diseño del ticket. - Envías el request de creación del trabajo — la terminal responde 202 Accepted de forma inmediata.
- La impresión se ejecuta de forma asíncrona en el hardware.
- Conoce el resultado final (
COMPLETEDoFAILED) de dos formas:- Webhook (push): la terminal notifica a la
webhookUrlque definiste en el request. - Polling (pull): consulta el estado activamente con
GET /terminal/v1/print_job?print_job_id={id}.
- Webhook (push): la terminal notifica a la
La estructura del request y la respuesta es idéntica en ambos modos de conexión. Lo que varía es únicamente 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}/sync |
| Nube (Internet) — Producción | https://cloudt.kushkipagos.com/terminal/v1/{terminalSerial}/sync |
Casos de uso
La API no está limitada a comprobantes de pago. Cualquier contenido que tu negocio necesite entregar en papel puede dispararse desde tu sistema de caja:
| Caso de uso | Descripción |
|---|---|
| Comprobante de pago | Cobro directo, captura de pre-autorización, devolución o anulación |
| Cupón de descuento | Imprime un código de descuento para la próxima compra del cliente |
| Código QR | Contraseña de Wi-Fi, enlace a programa de fidelización, recibo digital, información de producto |
| Mensaje de agradecimiento | Mensaje de marca personalizado al final del recibo |
| Fidelización y promociones | Saldo de puntos, niveles de recompensa, ofertas especiales |
| Pre-cuenta o resumen de orden | Ticket de cocina o resumen de mesa antes del cobro final |
| Constancia de reverso o anulación | Comprobante impreso de una cancelación o reembolso |
| Reimpresión | Vuelve a imprimir cualquier ticket anterior usando el mismo printJobId |
| Contenido libre | Cualquier texto, imagen, QR o código de barras — sin necesidad de una transacción |
Anatomía de un ticket
Cada sección visual del recibo corresponde a un tipo de comando en el arreglo commands. La siguiente imagen muestra cómo mapear el diseño del ticket a los comandos de la API:
Tipos de comandos
| Tipo | Descripción |
|---|---|
text | Línea de texto con tamaño, alineación, negrita, cursiva y subrayado |
columns | Fila multi-columna con anchos proporcionales — ideal para producto + precio |
divider | Línea separadora a todo el ancho (SOLID, DOTTED o EMPTY) |
feed | Avanza el papel N líneas en blanco |
space | Inserta espacio vertical preciso en píxeles |
cut | Activa la cuchilla de corte (se ignora de forma segura en terminales sin cuchilla) |
image | Imprime una imagen PNG/JPG en Base64 — usa algorithm: BINARIZATION para logos |
qr | Genera un código QR directamente en el hardware de la impresora |
barcode | Genera un código de barras CODE128 directamente en el hardware |
Ejemplo completo
El siguiente ejemplo construye un recibo completo: logo de comercio, encabezado, items de la orden, total, QR y corte automático. Consulta la referencia API para mayor información.
{"printJobId": "TICKET-190209","externalReference": "Mesa-14","webhookUrl": "https://api.tunegocio/webhook/print-events","skipIfBusy": false,"commands": [{"type": "image","base64Image": "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAK...","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": "text","text": "Fecha: 17/03/2024 14:32\n","align": "LEFT","size": 20},{ "type": "divider", "dividerType": "SOLID" },{"type": "columns","columns": [{ "text": "2x Combo Hamburguesa", "weight": 2, "align": "LEFT" },{ "text": "$30.000", "weight": 1, "align": "RIGHT" }]},{"type": "columns","columns": [{ "text": "1x Jugo Natural", "weight": 2, "align": "LEFT" },{ "text": "$8.000", "weight": 1, "align": "RIGHT" }]},{ "type": "divider", "dividerType": "SOLID" },{"type": "columns","columns": [{ "text": "TOTAL", "weight": 2, "align": "LEFT" },{ "text": "$38.000", "weight": 1, "align": "RIGHT" }]},{"type": "qr","content": "https://tunegocio/recibo/TICKET-190209","dotSize": 6,"errorLevel": "M","align": "CENTER"},{ "type": "feed", "lines": 3 },{ "type": "cut" }]}
Envía el request desde tu backend o línea de comandos:
- Bash
- Javascript
- Python
curl -X POST http://TERMINAL_IP:6868/terminal/v1/print \-H "Content-Type: application/json" \-d @body.json
const res = await fetch("http://TERMINAL_IP:6868/terminal/v1/print", {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify(payload),});console.log(res.status); // 202
import requestsres = requests.post("http://TERMINAL_IP:6868/terminal/v1/print",json=payload)print(res.status_code) # 202
La terminal responde de forma inmediata con 202 Accepted:
{"printJobId": "TICKET-190209","status": "PENDING"}
Resultado del trabajo
Tienes dos mecanismos para conocer el resultado final de un trabajo de impresión. Puedes usar uno o ambos en paralelo.
Opción A — Webhook (push)
Si enviaste un webhookUrl al encolar el trabajo, la terminal ejecuta 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."}
Consulta la referencia API para mayor información sobre este webhook.
Opción B — Polling (pull)
Úsalo cuando tu sistema no puede recibir conexiones entrantes desde la terminal, o como respaldo al webhook.
Red Local: GET /terminal/v1/print_job?print_job_id={id}
Nube: POST /terminal/v1/{terminalSerial}/sync/print/job_status?print_job_id={id}
Consulta cada 2–3 segundos. Detén el polling cuando status sea COMPLETED o FAILED.
{"printJobId": "TICKET-190209","status": "COMPLETED"}
Consulta la referencia API para mayor información sobre este endpoint.
Los posibles valores de errorCode en caso de fallo son: OUT_OF_PAPER,
COVER_OPEN, COVER_INCOMPLETE, PAPER_JAM, BUSY, PRINTER_HOT,
MOTOR_HOT, CUTTER_ERROR, OFFLINE, UNKNOWN_ERROR.
Acepta cobros con Kushki One
Realiza cobros con Kushki One
Errores de impresora
Consulta el catálogo de errores
Chile
Colombia
Ecuador
Peru