Crear un comando de terminal
Envía un comando de cobro a una terminal POS. Recurrente crea un checkout y lo despacha a la terminal indicada. Si ya existe un comando activo con el mismo external_id, retorna el comando existente en vez de crear uno nuevo (idempotencia).
Cuando la terminal recibe el comando, muestra automáticamente la pantalla de cobro para que el cliente pague con tarjeta.
Usa una llave LIVE para una terminal física. Una llave TEST se rechaza con 403 terminal_test_key_requires_sandbox, antes de crear el checkout o mover dinero.
La terminal debe estar en Modo espera y reportando disponibilidad. Si no lo está, la API responde 409 con code: terminal_not_in_standby sin crear un checkout nuevo. Los reintentos con un external_id existente conservan la idempotencia y retornan el comando original. Una respuesta exitosa incluye terminal_availability.
Flujo
- Tu sistema envía
POST /api/terminal_session_commandscon el monto, moneda y terminal. - Recurrente crea un checkout y un comando en estado
pending. - La terminal levanta el comando y lo pasa a
dispatched. - El cliente paga en la terminal.
- Recibes un webhook
intent.succeededcon el resultado; las cuentas anteriores al cambio también conservanpayment_intent.succeeded.
También puedes consultar el comando con GET /api/terminal_session_commands/{random_id}. Los estados definitivos son canceled, superseded, consumed y failed; pending, dispatched y cancel_requested todavía pueden cambiar.
Idempotencia
Si envías dos requests con el mismo external_id dentro de la misma cuenta, el segundo retorna el comando original sin crear uno duplicado. Dos cuentas distintas pueden usar el mismo external_id. Esto te permite reintentar de forma segura.
Superseding
Si envías un nuevo comando a la misma terminal (con un external_id diferente), los comandos anteriores pendientes se marcan como superseded y la terminal solo procesa el más reciente.
Meses sin intereses (installments)
Si quieres que el cobro se procese en cuotas, envía installments con el número de meses. Solo aplica a cobros en GTQ y los valores permitidos son 3, 6, 12 o 18 (algunas cuentas tienen configuraciones distintas). Si la tarjeta del cliente no soporta la opción elegida, el cobro se rechaza con unsupported_installments.
Pantallas post-pago
Por defecto, después de un pago exitoso la terminal muestra las pantallas para solicitar NIT, correo y teléfono. Envía show_post_payment_screens: false para omitirlas y volver automáticamente a Modo espera. Recurrente emite la factura como C/F cuando corresponde y adelanta el webhook y los correos que normalmente esperan a que el comprador termine esas pantallas.
Si el monto y la configuración de facturación hacen obligatorio un NIT válido, Recurrente conserva las pantallas aunque envíes false.
NIT del comprador
Si tu sistema ya conoce el NIT, envíalo en tax_id. La terminal se salta la pantalla que lo pide y abre directo la de comprobantes, con la factura ya emitida a ese NIT y el comprobante listo para imprimir con el NIT incluido. Si el NIT no es válido se ignora y la pantalla se muestra igual, para que el cajero lo corrija.
Impresión automática del comprobante
Envía print_receipt: true para mandar el comprobante de pago a la impresora una vez que el cobro sea exitoso. La instrucción es best-effort: el resultado de impresión no se expone por API y una impresora sin papel, ocupada o con error no revierte el pago ni retrasa intent.succeeded.
Cuentas conectadas
Para originar el cobro desde una plataforma y registrarlo en una cuenta hija:
- Autentica el request con la llave LIVE de la plataforma en
X-SECRET-KEYy envía el IDac_...de la cuenta hija enX-ACCOUNT-ID. - Obtén el
terminal_idpúblico (trm_...) en el panel de la cuenta hija, en POS → detalle de la terminal, y guárdalo en tu configuración. Actualmente no existe un endpoint público para listar terminales. - Confirma que el dispositivo inició sesión en esa misma cuenta hija y está en Modo espera. Un pinpad emparejado con la plataforma es invisible para la hija (y viceversa).
- Envía el comando con
terminal_id, monto, moneda y unexternal_idúnico de tu sistema. La respuesta incluye eliddel comando (tsc_...),checkout_id,statusyterminal_availability.
El checkout, el pago y la factura se crean bajo la cuenta hija. La
plataforma recibe intent.succeeded con connected: true y el
account_id de la hija; si la hija también tiene un webhook endpoint,
Recurrente entrega el evento a ambos. Usa checkout.metadata.external_id
para conciliar la orden original, checkout.metadata.terminal_id para
identificar el dispositivo y tax_invoice_url para recuperar la factura
cuando exista.
Cuando algo no calza, el 404 incluye un code que identifica cuál de las tres cosas falta:
Authentication
Tu clave secreta de API.
Una llave de cuenta (sk_live_..., sk_test_...) opera sobre su propia cuenta y, con X-ACCOUNT-ID, sobre sus cuentas conectadas.
La llave también fija el ambiente: una sk_test_ solo lista y resuelve objetos de prueba (live_mode: false) y una sk_live_ solo objetos reales. Un ID del otro ambiente responde 404 (401 en /customers).
Una llave de organización (sk_org_live_..., sk_org_test_...) alcanza todas las cuentas de una organización y solo sirve para leer: saldos, movimientos y reportes. Para operar sobre una cuenta debe nombrarla con X-ACCOUNT-ID; omitirlo en una lectura devuelve todas las cuentas de la organización. Cualquier otro endpoint responde 403 con code: organization_key_unsupported.
Request
ID público trm_... de la terminal POS donde se enviará el cobro. Cópialo desde POS → detalle de la terminal en la cuenta que va a cobrar; actualmente no existe un endpoint público para listar terminales.
ID único de tu sistema para este cobro dentro de la cuenta autenticada. Se usa para idempotencia — si envías el mismo external_id dos veces en esa cuenta, no se crea un duplicado.
Monto a cobrar en centavos. Envía amount_in_cents, amount o items — solo uno.
Monto a cobrar en unidades (ej. 50.00). Alternativa a amount_in_cents.
Cobra productos existentes en vez de un monto suelto: cada item referencia un precio y el total se calcula sumando los items. No se puede combinar con amount_in_cents/amount ni con description (cada producto ya tiene nombre). Solo productos de pago único, todos en la moneda del cobro (currency). Con una cuenta conectada como comercio de registro, los precios deben pertenecer a esa cuenta.
(Opcional) Concepto del cobro, por ejemplo el número de orden de tu sistema. Aparece en el recibo del cliente y en la actividad del comercio (ej. “Pago POS por Orden #1234”). Si se omite, el cobro se muestra sin concepto, como un pago rápido. No se puede combinar con items.
Número de meses sin intereses. Solo válido con currency: GTQ. Valores permitidos por defecto [3, 6, 12, 18] (puede variar por cuenta).
Muestra las pantallas post-pago de NIT, correo y teléfono. Envía false para omitirlas y volver a Modo espera, salvo cuando un NIT válido sea obligatorio.
Imprime automáticamente el comprobante de pago después de un cobro exitoso. El resultado de impresión no cambia el estado financiero del pago.
(Opcional) NIT del comprador, cuando tu sistema ya lo tiene. La terminal se salta la pantalla del NIT y va directo a la de comprobantes: Recurrente emite la factura con este NIT y el comprobante lo lleva impreso. Un NIT inválido se ignora y la pantalla se muestra igual para que el cajero lo corrija.
(Opcional) Comisión de plataforma en centavos. Requiere que el cobro sea a nombre de una cuenta conectada (modelo directo): cuando el cobro se completa, Recurrente transfiere este monto del balance de la cuenta conectada al de tu plataforma. La comisión se puede revertir al reembolsar con refund_application_fee: true, y se incluye en la facturación diaria de comisiones (DTE) si la conexión la tiene habilitada. No se puede combinar con un transfer_setups de purpose: platform_commission.
(Opcional) Transferencias para enrutar fondos a una cuenta conectada tras un cobro exitoso (modelo destino). El destinatario debe ser tu cuenta o una cuenta conectada. Para cobrar una comisión de plataforma usa application_fee_amount en su lugar.
Response
ID público aleatorio del comando
ID único de tu sistema dentro de la cuenta autenticada
true cuando el comando alcanzó un resultado definitivo y ya no puede cambiar
Monto en centavos. Para un cobro con items, la suma de los items.
Meses sin intereses solicitados, o null si el cobro va sin cuotas
Concepto del cobro enviado al crear el comando, o null si no se envió uno
Indica si el comando solicita mostrar las pantallas post-pago de NIT, correo y teléfono
Indica si el comando solicita imprimir automáticamente el comprobante de pago
NIT del comprador enviado con el cobro, o null si no se envió uno
URL del checkout (la terminal usa esta URL internamente)
Momento en que se solicitó detener un comando ya despachado
Momento en que la cancelación se volvió definitiva

