Plantillas
La definición reutilizable de cómo entra el dinero a una subcuenta.
Una plantilla responde una sola pregunta: ¿cómo entran los pagos a esta subcuenta? La creas una vez (como abrir un punto de recaudo para una billetera, una campaña o un cliente) y queda ahí como la definición permanente de lo que esperas recibir. Los pagadores pagan, y cada pago entrante se verifica contra la plantilla antes de quedar registrado como un pago.
En una plantilla nunca manejas el dinero: es pura configuración. El dinero llega después, como pagos creados contra ella.
La creación es idempotente sobre external_id: repetir la petición devuelve la plantilla existente en vez de crear un duplicado.
Qué puede hacer una plantilla
La plantilla es la entidad más capaz de Recaudos. Todo lo de abajo es opcional más allá de lo básico. Cada capacidad tiene su propia sección o página:
- Recibir un pago o muchos:
usage_mode(un solo uso o multiuso). - Servir recargas o recaudos:
type(recarga o recaudo). - Emitir aquello a lo que paga el pagador: el token de pago de cada método aceptado; para Bre-B, una llave y un QR opcional.
- Acotar los montos: por pago y acumulados (límites y contadores).
- Restringir quién puede pagar:
expected_payers. - Alojar intenciones de pago: con llaves por intención de pago, para que cada pago llegue identificado de antemano.
- Configurar cada pago que produce: trigger de acreditación, metadata y sobreescrituras de cargos (configuración heredada).
- Ofrecer un checkout: integra API-only con tu propia UI, o usa el checkout hospedado de Mono, apuntado a una de tus marcas y pidiendo los campos extra que necesites (checkout hospedado o API-only).
- Rastrear su propio progreso:
paid_amount,pending_amounty los contadoressuccessful_payins/failed_payins. - Expirar y limpiarse sola: expiración (como fecha
expires_ato duraciónexpires_in, mutuamente excluyentes al crear) y pruning.
Recarga o recaudo
El campo type declara el propósito de la plantilla:
| Tipo | Propósito | Caso típico |
|---|---|---|
topup | Un usuario final carga dinero a su propia subcuenta. | Recarga de billetera con llave permanente. |
collection | Tu negocio recauda dinero de clientes hacia una subcuenta. Valor por defecto. | Checkout, facturación, donaciones. |
Un solo uso o multiuso
usage_mode define cuántos pagos acepta la plantilla:
single_use: exactamente un pago exitoso. El primer pago mueve la plantilla apaid, y una plantilla single-use pagada es historia cerrada: no se puede actualizar ni reabrir.multiple_use: cualquier número de pagos, limitado solo por los totales acumulados (abajo) y la expiración.
Ciclo de vida
created: la plantilla fue aceptada y persistida, pero sus tokens de pago todavía se están preparando, así que aún no puede recibir pagos. El setup es asíncrono: para Bre-B conkey_per: "template"(el valor por defecto), la plantilla espera encreatedhasta que la red confirma la llave.ready: la plantilla puede recibir pagos.payment_tokenslleva una entrada por cada método aceptado que emite token: para Bre-B, la llave y el QR cuando se pidió. Los métodos que no necesitan token no tienen entrada ahí.minimum_paid: elpaid_amountacumulado alcanzótotal_minimum_amount. La plantilla sigue aceptando pagos hastatotal_maximum_amount. Un update que suba el mínimo por encima de lo ya pagado la devuelve aready.paid: se alcanzó el máximo acumulado, o la plantillasingle_userecibió su pago. Una plantillamultiple_usepuede reabrirse (de vuelta areadyominimum_paid) si un update sube o eliminatotal_maximum_amount.discarded: la plantilla fue podada (expiración o inactividad) o eliminada, y sus tokens de pago fueron dados de baja.prune_reasonexplica cuál fue el caso.failed: el setup de los tokens de pago agotó sus reintentos (por ejemplo, falló el registro de la llave Bre-B).state_reasonexplica por qué.
Cada razón detrás de una plantilla failed o discarded está en Errores de plantilla.
Las transiciones de estado causadas por un update (subir o bajar los totales) viajan dentro del webhook payin_template_updated con los valores anteriores. Los webhooks de estado separados no se envían en ese caso. Todas las demás transiciones emiten su propio webhook.
Límites de monto y contadores
Dos pares de límites, todos denominados en la currency de la plantilla:
| Campo | Alcance | Efecto |
|---|---|---|
minimum_payin_amount / maximum_payin_amount | Cada pago | Un pago fuera del rango se rechaza (amount_below_minimum / amount_exceeds_maximum). |
total_minimum_amount / total_maximum_amount | Acumulado | Mueven los estados minimum_paid y paid. |
La plantilla también mantiene contadores: paid_amount (acumulado recaudado), pending_amount (autorizado, en vuelo) y los conteos successful_payins / failed_payins.
Restringir quién puede pagar
expected_payers es una lista opcional de documentos de identidad (tipo y número). Cuando está definida, solo esos pagadores pueden pagar la plantilla: un pago de cualquier otra persona se rechaza con payer_not_allowed. Para Bre-B, el documento del pagador llega con el pago mismo, así que la verificación no le exige nada al pagador más allá de pagar desde su propio banco.
Configuración por método
method_params lleva la configuración de cada método aceptado. Para co_breb: si se genera un QR (create_qr), un alias personalizado de llave (custom_key_value), si la llave se crea por plantilla o por intención de pago (key_per) y los datos de comercio del QR. El detalle vive en Tokens de pago y Bre-B.
Configuración que hereda cada pago
payin_data guarda la configuración que hereda cada pago creado desde la plantilla:
subaccount_disbursement_trigger: cuándo se acredita la subcuenta:on_approval(apenas el proveedor aprueba) uon_funds_delivery(cuando el dinero llega a su cuenta destino). Ver Crédito a la subcuenta.metadata: se adjunta a cada pago, para tu propia conciliación.fee_override: sobreescrituras de cargos por plantilla. Ver Cargos.redirect_url: adonde vuelve el pagador tras pagar en el checkout hospedado. Ver Checkout hospedado o API-only.
Una intención de pago creada desde la plantilla puede sobreescribir estos valores para su propio pago.
Checkout hospedado o API-only
Una plantilla soporta dos modos de integración para el lado que ve el pagador:
- API-only: tu producto es dueño de toda la experiencia del pagador: lees el token de pago de la plantilla o de la intención de pago y muestras la llave o el QR en tu propia app, página o recibo. Todos los flujos de estas guías funcionan así.
- Checkout hospedado por Mono: Mono sirve la página de pago por ti: un checkout hospedado donde el pagador completa el pago, renderizado con la marca a la que apunta la plantilla. Comparte el
checkout_urlde la plantilla, o elurlde una intención de pago, y el pagador paga ahí sin que construyas una pantalla de pago.
Estos campos controlan el checkout hospedado:
| Campo | En | Qué es |
|---|---|---|
checkout_url | Plantilla (respuesta) | La URL del checkout hospedado de la plantilla. |
url | Intención de pago (respuesta) | La página hospedada donde el pagador completa esa intención de pago específica. |
redirect_url | payin_data | Adonde se redirige al pagador tras completar un pago en el checkout hospedado. Si se omite, se usa la página de voucher por defecto de Mono. |
form_customization | Plantilla | Cómo se personaliza el checkout para esta plantilla: la marca con la que se renderiza y los campos extra que le pide al pagador. |
redirect_url y form_customization solo tienen efecto en el checkout hospedado; una integración API-only no los necesita.
Qué lleva form_customization
Dos cosas, y ninguna de las dos es el branding en sí:
| Campo | Tipo | Qué es |
|---|---|---|
brand_id | string | null | La marca con la que el checkout se renderiza para esta plantilla. null significa que usa su presentación por defecto. |
custom_fields | array | null | Los campos que el checkout le pide al pagador además del monto: una lista ordenada, no un objeto libre. |
El objeto form_customization completo vuelve null cuando la plantilla no tiene ni marca ni campos personalizados.
Cada entrada de custom_fields es un campo tipado:
| Propiedad | Qué hace |
|---|---|
label | El nombre del campo que ve el pagador. Obligatorio. |
type | Qué escribe el pagador: text (por defecto), number, boolean o date. |
default_value | Valor que se muestra pre-llenado en el formulario. |
required | Si el pagador está obligado a llenarlo. Por defecto false. |
editable | Si el pagador puede cambiar el valor pre-llenado. Por defecto true. |
{
"form_customization": {
"brand_id": "cpitplb_5tgliBmzjZ6mpQPRbQjfKj",
"custom_fields": [
{
"label": "Número de orden",
"type": "text",
"default_value": "ORD-1042",
"editable": false
},
{ "label": "Fecha de entrega", "type": "date", "required": true }
]
}
}Marcas
Una marca es el aspecto reutilizable que viste tu checkout hospedado: un nombre, el texto del botón de pago, un color de acento, un logo y el mensaje que se muestra en el voucher después de pagar. Le pertenece a ti, no a una plantilla en particular. Varias plantillas pueden apuntar a la misma marca, y cambiar la marca las cambia todas a la vez. Una de tus marcas es la predeterminada, la que se usa cuando una plantilla nueva no nombra ninguna.
Las marcas se administran hoy desde el dashboard de Core, no por API: brand_id es la única parte de ellas que aparece en el contrato de Recaudos, y es una referencia a una marca que ya existe en tu cliente. Las marcas se resuelven dentro de tu propio alcance, así que un brand_id que no sea tuyo se rechaza.
Actualizar y eliminar
Los updates reconocen la presencia de cada campo: un campo omitido conserva su valor, un null explícito limpia uno anulable. payin_data y form_customization se fusionan campo por campo, pero un campo que contiene una lista se reemplaza completo. Enviar custom_fields cambia la lista entera, no hay fusión campo a campo dentro de ella, y lo mismo aplica a expected_payers. Poner form_customization en null limpia los campos personalizados y desvincula la marca. custom_merchant_name queda fijo en la creación y no se puede actualizar. Una plantilla no se puede actualizar mientras sigue en created, una vez discarded o failed, siendo una single-use ya consumida, o mientras está siendo podada. Cada update exitoso emite payin_template_updated con los valores anteriores de los campos que cambiaron.
La eliminación es un soft delete: la plantilla deja de aceptar pagos y su external_id queda libre para reutilizarse. Solo se permite cuando la plantilla no retiene dinero (paid_amount y pending_amount en cero) y no está en estado created, discarded ni failed.
Pruning
Las plantillas no viven para siempre: un barrido diario retira las que ya cumplieron (expiradas, inactivas o eliminadas) y le devuelve sus tokens de pago al proveedor. Qué reglas se disparan, los periodos de gracia que puedes configurar y qué significa el webhook payin_template_discarded para tu integración están en Pruning.
Modelo de datos
El schema completo, con las formas de petición y respuesta, vive en la referencia de API de plantillas.
Siguientes pasos
- Tokens de pago: la llave y el QR que emite la plantilla.
- Intenciones de pago: declarar cada pago esperado individualmente.
- Recaudar con una plantilla: el flujo de extremo a extremo.