▤ ControlPOS DevelopersEntrar al panel ↗

GUÍA DE INTEGRACIÓN · SEPTIEMBRE 2026

Un ticket digital.
Cualquier integración compatible.

Conecta tu aplicación de terminal a ControlPOS por HTTPS. Emite el comprobante después de confirmar la operación y entrega al cliente un enlace, un QR o un PDF.

1. Dar de altaCódigo del comercio → token
2. EmitirPOST /api/tickets
3. EntregarEnlace / QR / PDF
Alcance actual. Esta API emite comprobantes: no cobra, autoriza, cancela ni devuelve dinero. Los campos EMV y el código de autorización del voucher se simulan en el backend actual; no representan autorización bancaria. Antes de usarlo como voucher bancario, se necesita ampliar y validar el contrato para datos reales del adquirente.

01 / CONEXIÓN

De una terminal nueva a su primer ticket

Solicita a un administrador un comercio y terminal de pruebas. En Terminales → Códigos de alta, el administrador genera el código. La documentación no crea credenciales ni proporciona un sandbox público; usa una instancia de pruebas acordada con el administrador.

1. Canjear el código una sola vez

La serie debe ser estable y única, con un máximo de 64 caracteres. El código determina el comercio; no envíes un comercio distinto. La etiqueta ayuda a identificar fabricante, modelo y sucursal.

curl --request POST "$BASE_URL/api/terminals/enroll" \
  --header 'Content-Type: application/json' \
  --data '{"enrollmentCode":"CPE-REEMPLAZAR","serial":"MARCA-MODELO-0001","tokenLabel":"Modelo · Sucursal de pruebas"}'

Define BASE_URL con el origen de tu instancia de pruebas. El origen del servicio publicado es https://ticket.control-pos.com. No ejecutes pruebas de emisión allí sin un comercio destinado a pruebas.

{
  "terminal": { "id": "…", "serial": "MARCA-MODELO-0001" },
  "token_id": "…",
  "token": "cpt_…",
  "token_expires_at": null
}

Respuesta abreviada. Guarda el token en almacenamiento protegido por el dispositivo. Solo se muestra una vez: no lo incluyas en el APK, repositorios, capturas ni logs. Si se pierde o se expone, el administrador debe revocarlo y emitir uno nuevo. No vuelvas a canjear automáticamente un código si perdiste la respuesta: primero revisa el alta en el panel.

2. Emitir después de confirmar el pago

Este ejemplo es un ticket en efectivo. Para tarjeta agrega el bloque card descrito abajo. Crea una clave por operación y persiste el cuerpo y la clave antes de enviar.

curl --request POST "$BASE_URL/api/tickets" \
  --header 'Content-Type: application/json' \
  --header "X-Terminal-Token: $TERMINAL_TOKEN" \
  --header "Idempotency-Key: $OPERATION_KEY" \
  --data @ticket-example.json
{
  "terminalSerial": "MARCA-MODELO-0001",
  "currency": "MXN",
  "items": [{ "name": "Consumo", "qty": 1, "price": 100.00 }],
  "tip": 10.00,
  "transactionType": "venta",
  "capture": { "orderReference": "ORDEN-0001", "paymentMethod": "efectivo" }
}

La primera emisión devuelve 201. Un reintento resuelto con la misma clave y cuerpo devuelve 200 y el mismo ticket. La respuesta incluye id, folio, amount, receipt_svg, created_at y expires_at. Los importes de respuesta son cadenas: en este ejemplo, amount: "110.00".

3. Entregar el comprobante

Con el id recibido, construye BASE_URL + "/t/" + id para el enlace o contenido del QR. El PDF está en /t/{id}/pdf. Estas rutas son públicas: comparte el enlace únicamente con su destinatario. Respeta expires_at; el recibo puede dejar de estar disponible después de su vencimiento.

02 / CONTRATO HTTP

Referencia de la API

Solicitudes en JSON con nombres camelCase; respuestas del ticket en snake_case. Envía credenciales solo al origen HTTPS configurado. El token de terminal permite emitir tickets; no permite navegar el panel ni consultar los endpoints administrativos.

Endpoints necesarios para integrar una terminal
Método y rutaAutenticaciónResultado
POST /api/terminals/enrollCódigo en el cuerpo; sin tokenTerminal y credencial
POST /api/ticketsX-Terminal-Token o Authorization: Bearer201 nuevo / 200 reintento
GET /t/{id}Enlace público; sin tokenVista del comprobante
GET /t/{id}/pdfEnlace público; sin tokenPDF

Cuerpo de emisión

CampoRegla
terminalSerial *Serie registrada, 1–64 caracteres; debe corresponder al token.
items *Entre 1 y 200 conceptos. name: 1–120 caracteres; qty: positivo, hasta 3 decimales y 6 enteros; price: no negativo, hasta 2 decimales y 10 enteros.
currencyTres letras mayúsculas; por defecto MXN. No convierte monedas.
tipNo negativa, hasta 2 decimales y 10 enteros; por defecto 0. Total = suma de conceptos + propina.
transactionTypeventa (por defecto), devolucion, cancelacion, check_in, checkout. Describe el comprobante; no ejecuta la operación financiera.
cardOpcional. brand: visa, mastercard, amex, card; type: credito, debito; last4: exactamente 4 dígitos; entryMode: chip (por defecto), contactless, swipe, manual.
captureOpcional. orderReference (64), cashier (80), operationNumber (32), batchNumber (32), affiliation (32 caracteres). installments: entero 2–48; paymentMethod: efectivo, tarjeta, transferencia, otro; capturedAt: fecha y hora ISO 8601 UTC. transaccionId (UUID) y rrn (12): autorización que ya dio el switch; obligatorios en ventas con tarjeta, si faltan o no coinciden con RRN, terminal e importe el servidor responde 409 AUTHORIZATION_NOT_FOUND (reintentable, no crea ticket).
receiptTemplateCódigo opcional, hasta 64 caracteres. Una plantilla inexistente rechaza la emisión.

* Obligatorio. No envíes PAN completo, CVV, PIN ni datos de banda. No añadas impuestos o descuentos como campos nuevos: el contrato actual no los calcula.

"card": { "brand": "visa", "type": "debito", "last4": "1234", "entryMode": "contactless" },
"capture": {
  "operationNumber": "000123", "batchNumber": "001",
  "affiliation": "AFILIACION", "paymentMethod": "tarjeta",
  "capturedAt": "2026-09-04T18:00:00Z"
}

Fragmento para una operación de prueba con tarjeta. Captura los valores reales de la transacción desde la aplicación de pagos; no inventes datos faltantes.

Plantillas disponibles

voucher-venta, voucher-devolucion, voucher-cancelacion, estancia-check-in, estancia-checkout, consumo-restaurante y detalle-retail. La disponibilidad final depende de la configuración del comercio.

03 / ADAPTADORES

Integrar otras marcas de terminales

La API no depende de una marca. La aplicación anfitriona adapta el resultado del pago, la identidad del dispositivo y la entrega del comprobante. Cada modelo requiere validar sistema operativo, permisos, distribución de aplicaciones y acceso al SDK del fabricante.

Android

Integra el módulo Kotlin o llama directamente a HTTPS. Obtén la serie con la API autorizada del fabricante; solicita permiso de red y ejecuta las peticiones fuera del hilo de interfaz.

Otros sistemas

Usa un cliente HTTPS/JSON nativo o un servicio intermediario autorizado. Si el equipo no permite aplicaciones externas, acuerda con su proveedor una integración desde el sistema de caja.

Impresión

Implementa un adaptador para el SDK de impresora del modelo. Renderiza texto o imagen al ancho soportado; un SVG no es un comando de impresora. Si no hay impresora, entrega QR o enlace.

Qué debe resolver el adaptador

  1. Obtener la serie y recuperar el token protegido.
  2. Recibir del sistema de pagos el resultado confirmado y mapear importes, moneda, referencia y tarjeta enmascarada.
  3. Guardar una operación pendiente con cuerpo y clave estables.
  4. Emitir, guardar el id y la fecha de vencimiento; mostrar QR, abrir PDF o imprimir.
  5. Resolver falta de papel, desconexión o reimpresión usando el ticket existente.

PAX, Ingenico, Newland, SUNMI y otros fabricantes: este flujo es una guía de adaptación, no una declaración de compatibilidad certificada. Se requiere probar cada modelo y versión con su SDK y restricciones de distribución. Los SDK de pagos e impresión de terceros no se incluyen.

04 / OPERACIÓN CONFIABLE

Recuperar una emisión sin duplicarla

Usa Idempotency-Key de hasta 120 caracteres, única por operación dentro de la terminal. Guarda esa clave y el JSON en una cola durable antes del primer intento. Tras timeout, corte de red o respuesta 5xx, reintenta con la misma clave y cuerpo, espera creciente y variación aleatoria. El SDK no implementa la cola ni los reintentos por ti.

RespuestaAcción del integrador
400 · datos inválidosRevisar code, error y details cuando estén presentes. Corregir datos; no reintentar en bucle.
401 / 403Revisar token, vigencia y serie. Para el alta, revisar código con el administrador. Detener reintentos automáticos.
404Revisar recurso, id y vencimiento del ticket.
409 · idempotencia_en_procesoEsperar y repetir el mismo cuerpo y clave.
409 · idempotencia_cuerpo_distintoDetener y conciliar la operación; no generar otra clave automáticamente para el mismo cobro.
409 · idempotencia_ticket_purgadoRevisión operativa: el ticket ya no está disponible; evitar una emisión nueva automática.
429Respetar Retry-After, en segundos. Los límites son configurables por instancia.
5xx / timeout / sin redConservar pendiente y reintentar la emisión con límites y backoff; nunca repetir el cobro por un fallo del ticket.

Para soporte, conserva X-Request-Id o traceId, fecha, serie, versión de app y código de error. Omite tokens y datos sensibles. Un fallo al imprimir se resuelve reimprimiendo el ticket guardado, sin volver a emitir ni cobrar.

05 / HERRAMIENTAS

Recursos para tu equipo

Contrato OpenAPI

Esquemas de alta, emisión y entrega pública. Impórtalo en tu cliente de API.

Descargar JSON ↓

Colección Postman

Variables vacías para tu instancia, código y token. La emisión crea datos reales en el entorno que configures.

Descargar colección ↓

Ejemplo de ticket

Cuerpo de referencia para la solicitud de inicio rápido. Sustituye la serie por la del equipo.

Descargar ejemplo ↓

SDK Android · código fuente

Módulo Kotlin y aplicación de ejemplo. Requiere compilar y validar con tu modelo; no es un AAR certificado.

Descargar SDK y ejemplo ↓

Inicialización del SDK

ControlPOSDigitalReceiptsSDK.init(
    baseUrl = "https://ticket.control-pos.com",
    terminalToken = tokenGuardado
)

El ZIP incluye el README, el módulo digital-receipts-sdk y app-sample. El SDK HTTP es independiente del fabricante y no reemplaza su SDK de pagos o impresora. Revisa los modelos disponibles antes de usar campos ampliados de la API; para el contrato completo puedes integrar HTTPS directamente.

06 / ACEPTACIÓN

Antes de habilitar un modelo

Ejecuta estas pruebas en el entorno acordado y registra modelo, firmware, versión de app, fecha y evidencia. Esta lista no equivale a una certificación bancaria.

  • Alta: serie y comercio correctos; código inválido rechazado.
  • Token: guardado tras reinicio; token revocado y serie ajena rechazados.
  • Ticket: conceptos, moneda, propina, total y últimos cuatro dígitos correctos.
  • Red: pérdida de respuesta y reinicio de la app recuperan el mismo id, sin duplicar tickets.
  • Conflicto: misma clave con distinto cuerpo se detiene para revisión.
  • Entrega: QR legible en pantalla, enlace y PDF accesibles; manejo de ticket vencido.
  • Impresora: ancho correcto, acentos, QR, falta de papel y reimpresión sin nueva emisión.
  • Operación: errores visibles, reintentos limitados y logs sin credenciales.
  • Pago: ticket fallido nunca vuelve a cobrar; datos bancarios reales requieren una ampliación validada del contrato.
¿Qué entregar al administrador? Fabricante y modelo, versión del sistema, mecanismo de distribución, serie de pruebas, SDK de pagos/impresión utilizado y resultados de esta lista. Con ello se decide la habilitación del modelo.