# Recurrence

A mandate that becomes a template for repeated payments, with per-occurrence and cumulative caps and the references card networks now require for merchant-initiated transactions. Planned.

Status: Planned · Updated: 2026-09-13
For: agent, finance
Source: https://enruta.ai/docs/recurrence

Planned for November 2026 as an object; execution of the repeat payments on a rail follows each adapter in 2027. Nothing on this page is callable yet: `request_payment` has no `recurrence` argument and policies have no recurrence field today.

> Status: planned. The object below is the design the release will follow; field names may still change before it ships and the changelog will say so.

## The object

A mandate with `recurrence` becomes a template: each occurrence issues a child mandate and a record with `recurrence_occurrence: n`, decided through the main flow every time.

| Field | Meaning |
|---|---|
| `frequency` | `on_demand` · `daily` · `weekly` · `biweekly` · `monthly` · `quarterly` · `annually` |
| `max_occurrences`, `end_date` | `end_date` is required |
| `per_occurrence_max`, `cumulative_max` | Two caps; `cumulative_consumed` is kept by Enruta in the template’s mandate account |
| `amount_variance{type, tolerance_pct}` | `fixed` or `variable` |
| `initial_cit_ref{rail, transaction_id, tlid, network_txn_id}` | Carried on every merchant-initiated occurrence; what the card networks require from October 2026 (Mastercard TLID, 2026-10-23) |
| `network_recurring_ref` | The network’s recurring reference written back |
| `consent_text_hash` | The hash of the “will keep charging until cancelled” text the person accepted |
| `cancel_url`, `manage_url` | Self-service for the person |
| `next_occurrence_at`, `last_occurrence_record_id` |  |

## State

```text
template: issued ─▶ active ─▶ completed   (max_occurrences reached, or end_date)
                          └─▶ cancelled
each occurrence: the main flow, decided every time
```

| Situation | Result |
|---|---|
| One occurrence above `per_occurrence_max` | `step_up` |
| Cumulative above `cumulative_max` | `deny` |
| The merchant changes the price beyond `amount_variance` | `pause_and_notify` |

## Example

A freight agent pays the same carrier about $2,000 a week, never more than 10 % above: `recurrence { weekly, per_occurrence_max: "2200.00", cumulative_max: "30000.00", amount_variance { variable, 10 }, end_date: 2027-03-31 }`. Week seven asks for $2,350: above `per_occurrence_max`, so `step_up`; the controller approves, the record carries `recurrence_occurrence: 7`, the credential carries `initial_cit_ref`, and the merchant’s PSP fills the TLID from it.

## What exists today

- Every payment is a single mandate; an agent that pays weekly requests weekly, and each request is decided and sealed on its own.
- The mandate account and `refill_policy` already exist, so a template’s ledger has somewhere to live.
- Policies carry `mode: bounded` for autonomy inside a boundary without a step-up ([Autonomy levels](https://enruta.ai/docs/autonomy-levels)); a bounded template is where recurrence will attach.
