Ciclo de vida del recaudo
Máquina de estados para recaudos Bre-B — transiciones, webhooks y estados terminales
Un recaudo es un endpoint receptor de Bre-B — típicamente un código QR o una llave de pago compartible — que permite a uno o más pagadores enviar fondos a tu cuenta tenant. Desde el momento en que lo creas, el recaudo se mueve por una secuencia determinística de estados. Cada transición mapea a un evento de webhook, así que tu integración puede rastrear el progreso sin polling. Esta guía explica qué significa cada estado, qué hace que un recaudo se mueva entre ellos y cómo distinguir el éxito terminal de la falla terminal.
Diagrama de estados
Estados de un vistazo
| Estado | ¿Terminal? | Evento de webhook |
|---|---|---|
created | No | collection.created |
ready | No | collection.ready |
minimum_paid | No | collection.minimum_paid |
paid | Sí | collection.paid |
discarded | Sí | collection.discarded |
failed | Sí | collection.failed |
Los intentos de pago se rastrean por separado
Los intentos de pago individuales contra un recaudo ready o minimum_paid tienen su propia
máquina de estados (successful, rejected, failed) y emiten sus propios eventos —
collection.attempt_successful
y
collection.attempt_unsuccessful.
Un intento fallido no saca al recaudo de su estado actual — solo incrementa el contador
failed_attempts del recaudo.
Recorrido detallado
1. created
Estado inicial. Un recaudo entra a este estado tan pronto como
create collection
acepta tu request. La fila del recaudo existe en nuestro sistema y tiene un id
que puedes usar para búsquedas, pero la llave Bre-B subyacente todavía no fue
registrada con el directorio central (DICE), así que aún no puede aceptar pagos.
Los errores de validación nunca llegan a este estado
Si el request falla la validación síncrona — por ejemplo, los límites de monto son inválidos o el formato de la llave está mal formado — la API devuelve una respuesta 4xx y el recaudo no se persiste. Nunca pasará por esta máquina de estados y no se disparará ningún webhook.
Qué pasa después: el sistema registra la llave Bre-B con DICE. Esto típicamente se completa en segundos.
2. ready
La llave Bre-B fue registrada exitosamente con DICE y el arreglo keys del
recaudo está poblado con la llave activa. El recaudo ya está vivo y puede
aceptar pagos entrantes — los pagadores pueden escanear el QR o enviar a la llave.
Siguientes estados:
- →
minimum_paid(solo recaudos multi-uso) una vez que elpaid_amountacumulado alcanza o supera eltotal_minimum_amount. - →
paiduna vez que elpaid_amountacumulado alcanza eltotal_maximum_amount. Para recaudos de un solo uso esto pasa en el primer pago exitoso. - →
discardedsi el recaudo se borra, expira o se auto-descarta por inactividad antes de ser pagado.
3. minimum_paid
Aplica solo a recaudos multi-uso que definen tanto un mínimo como un
máximo. El paid_amount acumulado cruzó
total_minimum_amount, lo que significa que el recaudo cumplió su objetivo soft pero
sigue abierto a pagos adicionales hasta total_maximum_amount.
Este estado es útil para escenarios de pago parcial — por ejemplo, una recolección por objetivo que cumplió su meta pero sigue aceptando contribuciones hasta un tope duro.
Siguientes estados:
- →
paiduna vez quepaid_amountalcanzatotal_maximum_amount. - →
discardedpor expiración o inactividad.
4. paid (terminal)
El recaudo fue pagado por completo. paid_amount es igual a
total_maximum_amount. El recaudo ya no acepta pagos y no
ocurren más transiciones de estado.
5. discarded (terminal)
El recaudo fue removido del conjunto activo. El campo state_reason
te dice por qué:
deleted— removido explícitamente vía delete collection.expired— el recaudo pasó suexpires_atsin alcanzar un estado terminal de pagado.inactivity— el recaudo estuvo inactivo lo suficiente como para ser auto-descartado por el sistema.
No ocurren más transiciones de estado.
6. failed (terminal)
El recaudo no pudo ser usable. Esto pasa cuando el registro de la llave
Bre-B falla entre created y ready. El campo state_reason
lleva la causa — valores comunes incluyen key_already_registered,
key_registration_failed y key_canceled.
Los recaudos fallidos no aceptan pagos y nunca vuelven a transicionar. Para recuperar, crea un nuevo recaudo (típicamente con otra llave).
Trabajando con estados en tu integración
- Trata cada estado no terminal como transitorio. Un recaudo en
createdaún no es usable — esperareadyantes de mostrar el QR o la llave a los pagadores. - Trabaja con webhooks, no con polling. Cada transición de estado emite un webhook
con el nuevo estado y, donde aplique, un
state_reason. Verifica cada webhook (ver Verificación de firma de webhook) y actualiza tu registro local de forma idempotente — el mismo estado puede ser reintentado por nuestros workers. - Maneja entrega fuera de orden. Las entregas de webhook son at-least-once. Si
ves
paidantes queminimum_paid, conserva el estado más reciente e ignora el anterior. Una regla simple: si el recaudo ya está en un estado terminal localmente, ignora los webhooks no terminales. - Distingue el estado del recaudo del estado del intento. Un recaudo
readypuede tener muchos eventoscollection.attempt_unsuccessfulsin dejar el estadoready. Surface los fallos de intento por separado del estado del recaudo en tu UI y lógica de conciliación. - Tres estados son finales.
paid,discardedyfailedson los únicos estados terminales. Una vez que un recaudo alcanza cualquiera de ellos, nunca volverá a moverse.