Business-Code para firmar los requests.terminalSerial del dispositivo si integras por Nube.
commands con el diseño del ticket.202 Accepted de inmediato.| 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} |
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.| Elemento | Valor |
|---|---|
Authorization | Basic seguido del hash SHA-512. El prefijo Basic es obligatorio |
timestamp | Unix timestamp en segundos, dentro de ±5 minutos de la hora del servidor |
| Cuerpo | El sobre cifrado {"data": "<iv_hex>:<ciphertext_hex>"} |
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.encrypted_http_communication: true, en UAT y en producción. Nube no lo requiere. Detalle en Autenticación y cifrado de requests.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.| Caso de uso | Descripción |
|---|---|
| Comprobante de pago | Venta directa, captura de pre-autorización, devolución o anulación |
| Cupón de descuento | Código para la próxima compra del cliente |
| Código QR | Contraseña de Wi-Fi, enlace de fidelización, recibo digital, información de producto |
| 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 | Comprobante impreso de una cancelación o devolución |
| Reimpresión | Vuelve a imprimir un ticket anterior con el mismo printJobId |
| Contenido libre | Texto, imagen, QR o código de barras, sin necesidad de una transacción |
commands.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
commands | arreglo | ✅ | Lista ordenada de comandos de impresión |
printJobId | texto | — | Clave de idempotencia. Si lo omites, se genera un UUID |
externalReference | texto | — | Referencia libre de tu integración, por ejemplo Mesa-14 |
webhookUrl | texto | — | URL que recibirá el resultado cuando el trabajo termine |
skipIfBusy | booleano | — | Con true, devuelve 409 de inmediato si la cola está ocupada. Por defecto false |
| Tipo | Descripción |
|---|---|
text | Línea de texto con tamaño, alineación, negrita, cursiva y subrayado |
columns | Fila multicolumna con anchos proporcionales, ideal para producto y 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 o JPG en Base64. Usa algorithm: BINARIZATION para logotipos |
qr | Genera un código QR en el hardware de la impresora |
barcode | Genera un código de barras CODE128 en el hardware |
type es obligatoria en cada comando: es el discriminador que define su estructura.align, dividerType, errorLevel, algorithm) van siempre en mayúsculas.data:image/png;base64,.{
"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" }
]
}{
"printJobId": "TICKET-190209",
"status": "PENDING",
"message": "Impresión encolada correctamente"
}| Código | Significado |
|---|---|
202 Accepted | Trabajo encolado. Devuelve el printJobId y estado PENDING |
400 Bad Request | Payload mal formado o valor de enumerado desconocido |
409 Conflict | Ya existe un trabajo en PENDING o IN_PROGRESS |
webhookUrl al encolar, la terminal hace un POST hacia esa URL cuando el trabajo cambia a COMPLETED o FAILED.{
"printJobId": "TICKET-190209",
"status": "COMPLETED",
"externalReference": "Mesa-14"
}{
"printJobId": "TICKET-190209",
"status": "FAILED",
"externalReference": "Mesa-14",
"errorCode": "OUT_OF_PAPER",
"errorMessage": "La impresora está sin papel."
}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.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.GET /terminal/v1/print_job?print_job_id=TICKET-190209POST /terminal/v1/{terminalSerial}/sync/print_job{
"print_job_id": "TICKET-190209"
}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.status sea COMPLETED o FAILED.{
"printJobId": "TICKET-190209",
"status": "COMPLETED"
}status | Descripción |
|---|---|
PENDING | En cola, esperando turno |
IN_PROGRESS | El driver está enviando comandos a la impresora |
COMPLETED | Ticket impreso y cortado correctamente |
FAILED | Error físico durante la impresión. Revisa errorCode |
PENDING ni IN_PROGRESS. Si necesitas seguir esos estados intermedios, usa la consulta de estado.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.TER-004 con type: TERMINAL, y por HTTP como un 409.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.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.printJobId propio para poder reimprimir el mismo ticket y para descartar duplicados en tu sistema.externalReference para vincular el ticket con tu orden, mesa o factura.2xx al webhook antes de procesarlo. Un endpoint lento hace que pierdas la notificación.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.