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 heredada que todavía apunta a la cuenta LIVE se rechaza con 403 terminal_test_key_requires_sandbox, antes de crear el checkout o mover dinero. Las llaves TEST solo se aceptan cuando la solicitud ya está aislada dentro de un Sandbox; ese flujo no contacta hardware ni procesadores reales.
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_commands con 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
payment_intent.succeeded con el resultado.
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.
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-KEY y envía el ID ac_... de la cuenta hija en X-ACCOUNT-ID.
- Obtén el
terminal_id pú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 un external_id único de tu sistema. La respuesta incluye el id del comando (tsc_...), checkout_id, status y terminal_availability.
El checkout, el pago y la factura se crean bajo la cuenta hija. La
plataforma recibe payment_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: