Skip to navigation

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

  1. Tu sistema envía POST /api/terminal_session_commands con el monto, moneda y terminal.
  2. Recurrente crea un checkout y un comando en estado pending.
  3. La terminal levanta el comando y lo pasa a dispatched.
  4. El cliente paga en la terminal.
  5. Recibes un webhook intent.succeeded con el resultado; las cuentas anteriores al cambio también conservan payment_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:

  1. 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.
  2. 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.
  3. 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).
  4. 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 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:

codeQué revisar
connected_account_not_foundLa cuenta que enviaste no está conectada a la tuya (o es nieta, no hija directa).
terminal_not_foundLa terminal no está asociada a la cuenta que va a cobrar.
connected_account_mismatchEnviaste account_id de una hermana distinta a la del header X-ACCOUNT-ID.
recipient_not_foundEl recipient_id de un transfer_setup no es tu cuenta ni una hija conectada.

Authentication

X-SECRET-KEYstring

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

This endpoint expects an object.
terminal_idstringRequired

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.

currencyenumRequired
Moneda del cobro
Allowed values:
external_idstringRequired

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.

amount_in_centsintegerOptional

Monto a cobrar en centavos. Envía amount_in_cents, amount o items — solo uno.

amountdoubleOptional

Monto a cobrar en unidades (ej. 50.00). Alternativa a amount_in_cents.

itemslist of objectsOptional

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.

descriptionstringOptional

(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.

installmentsenumOptional

Número de meses sin intereses. Solo válido con currency: GTQ. Valores permitidos por defecto [3, 6, 12, 18] (puede variar por cuenta).

Allowed values:
show_post_payment_screensbooleanOptionalDefaults to true

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.

print_receiptbooleanOptionalDefaults to false

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.

tax_idstringOptional

(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.

application_fee_amountintegerOptional

(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.

transfer_setupslist of objectsOptional

(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

Comando creado exitosamente
idstringOptional

ID público aleatorio del comando

external_idstringOptional

ID único de tu sistema dentro de la cuenta autenticada

statusenumOptional
Estado del comando
finalbooleanOptional

true cuando el comando alcanzó un resultado definitivo y ya no puede cambiar

terminal_idstringOptional
ID de la terminal POS
amount_in_centsintegerOptional

Monto en centavos. Para un cobro con items, la suma de los items.

currencyenumOptional
Moneda del cobro
Allowed values:
installmentsinteger or nullOptional

Meses sin intereses solicitados, o null si el cobro va sin cuotas

descriptionstring or nullOptional

Concepto del cobro enviado al crear el comando, o null si no se envió uno

show_post_payment_screensbooleanOptional

Indica si el comando solicita mostrar las pantallas post-pago de NIT, correo y teléfono

print_receiptbooleanOptional

Indica si el comando solicita imprimir automáticamente el comprobante de pago

tax_idstring or nullOptional

NIT del comprador enviado con el cobro, o null si no se envió uno

terminal_availabilityenumOptional
Disponibilidad observada de la terminal para recibir comandos
Allowed values:
checkout_idstringOptional
ID del checkout generado
checkout_urlstringOptionalformat: "uri"

URL del checkout (la terminal usa esta URL internamente)

checkout_statusenumOptional
Estado actual del checkout asociado
cancellation_requested_atdatetime or nullOptional

Momento en que se solicitó detener un comando ya despachado

canceled_atdatetime or nullOptional

Momento en que la cancelación se volvió definitiva

Errors

403
Forbidden Error
404
Not Found Error
409
Conflict Error
422
Unprocessable Entity Error