Pruning
How and when Mono retires templates that are done, and what happens to their payment tokens.
Templates do not live forever. A template that nobody pays anymore still holds live payment tokens — Bre-B keys and QR codes registered with the network — and those cost money and add noise. Pruning is the daily sweep that retires the ones that are done and hands their tokens back.
You do not call anything to make it happen: Mono runs it for every program with payins enabled. What you control is when it triggers (the template's expiration and your program's grace periods) and what you do when it does (the payin_template_discarded webhook).
What makes a template prunable
Four rules, each recorded in prune_reason when it fires:
| Rule | A template is pruned when… | Default grace period |
|---|---|---|
expired | Its expires_at passed. | 1 day after expiry |
inactivity_without_attempts | It never received a payin and has been ready since it was created. | 30 days |
inactivity_with_attempts | It has received payins, but the last one is too old. | 90 days |
deleted | You deleted it — deletion triggers the same teardown, immediately. | — |
The grace periods are defaults, configurable per program: ask Mono to lengthen or shorten any of the three when payins is enabled for you, or later.
The teardown runs in two phases
Pruning does not just flip a state: the tokens have to be given back to the provider first, and only then is the result recorded.
- Tokens are deregistered. Mono asks each method's provider to discard the template's payment tokens. From that moment the Bre-B key and its QR stop working — no new payment can reach the template.
- The template is closed. A template in
readyorminimum_paidtransitions todiscardedand emitspayin_template_discarded. Apaidtemplate keeps itspaidstate — it is already spent — and only records the pruning fields.
While the teardown runs, three fields track it:
| Field | What it tells you |
|---|---|
prune_state | pruning while the tokens are being given back, pruned once they are. |
prune_reason | Which of the four rules fired. |
pruned_at | When the teardown completed. |
A prune that stalls — a provider confirmation that never arrives — is picked up again by the next day's sweep, so tokens never stay alive by accident.
Intents are cleaned up too
Intents have their own clock: each one is closed by its own scheduled job when its window ends, and its tokens are torn down when it reaches a final state (successful, failed, or expired). The daily sweep also looks at intents, but only as a safety net — to catch the ones whose own job never ran.
What to do about it
- Treat
payin_template_discardedas final. Stop showing that template's key or QR: payments to it will not arrive anymore. - Set
expires_atdeliberately. It is the only prune rule you control per template; the other two depend on your program's grace periods. - Do not rely on inactivity to close a campaign. If a collection is over, delete the template — you get the teardown immediately instead of waiting out the grace period.
Next steps
- Templates — the entity this page retires.
- Payment tokens — what gets handed back to the provider.
- Webhooks — the template events, including
payin_template_discarded.