> ## Documentation Index
> Fetch the complete documentation index at: https://docs.momentco.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Lifecycle

> The lifecycle of a mandate from consent to termination

A mandate is the merchant's standing permission to collect from a customer. Like any consent, it has a beginning, a middle, and an end:

* It is **created** when the customer is offered the consent, but the merchant cannot yet collect against it.
* It becomes **active** once the customer authorises the consent and their payment method has been saved.
* It is **expired** once the consented limits are reached — either the time window has passed or the maximum number of collections has been used up.
* It is **revoked** if the customer revokes their consent — for example, through their bank app.

## Statuses

Each of those stages corresponds to a status on the mandate:

| Status    | What it means                                                                                                                          |
| --------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `DRAFT`   | The customer has been offered the consent, but hasn't yet authorised it. The merchant cannot collect.                                  |
| `ACTIVE`  | The customer has authorised the consent and their payment method is saved. The merchant can now collect against it.                    |
| `EXPIRED` | The consented time window has passed or the maximum number of consented collections has been used. No further collections are allowed. |
| `REVOKED` | The customer has revoked their consent (e.g. via their bank app). No further collections are allowed.                                  |

## Stages

<Steps>
  <Step title="The merchant offers the consent (first_in_series)">
    The merchant initiates the recurring consent by creating a payment session with `mandate_options` describing what the customer is consenting to: how much, how often, until when, and up to how many times. The customer is shown those terms during checkout.

    At this point the mandate exists in the system but is `DRAFT` — it cannot be collected against yet. This is also the only step where the customer is involved; every collection from here on runs in the background.

    ```json theme={"system"}
    POST /collect/payment_sessions

    {
      "amount": 9900,
      "currency": "ZAR",
      "type": "recurring",
      "recurring": { "series_type": "first_in_series" },
      "options": {
        "checkout_options": {
          "return_url": "https://merchant.example/return"
        },
        "mandate_options": {
          "type": "scheduled",
          "amount": 9900,
          "recurrence": {
            "type": "monthly",
            "interval_count": 1
          },
          "validity_period": {
            "start_date": "2026-01-01",
            "end_date": "2026-12-31"
          },
          "max_occurrences": 12
        }
      }
    }
    ```
  </Step>

  <Step title="The customer authorises the consent">
    The customer is taken to the hosted checkout, reviews the consent, and authorises it. The first payment runs as part of the same checkout flow, and the customer's payment method is saved for future use.

    Once both succeed, the mandate becomes `ACTIVE` and is ready to be used for future collections.
  </Step>

  <Step title="The merchant collects (next_in_series)">
    Every subsequent collection is initiated by the merchant against the existing mandate, with no involvement from the customer. Before any money moves, the platform checks that the collection falls within everything the customer originally consented to — the right amount, within the validity window, and not over the consented number of collections.

    See [Use Cases](/documentation/collect/payment-sessions/mandates/use-cases) for the most common configurations and the non-obvious behaviours each one can exhibit (weekends, short months, leap years).

    If the check passes, the payment runs and the mandate is updated to record it. If that update reveals the mandate has reached its cap or its time window has just closed, the mandate is marked as `EXPIRED` in the same flow.

    If the check fails, the collection is rejected and no payment is taken.

    **Webhook fired (per successful collection):** `payment.succeeded`
  </Step>

  <Step title="The mandate expires">
    A mandate becomes `EXPIRED` when either of two limits is reached:

    * the validity period has ended (today is past the `end_date` the customer consented to), or
    * the maximum number of successful collections has been used.

    Once `EXPIRED`, no further collections are allowed against it. The customer keeps control: they can never be charged more than they originally consented to, in time or in count.
  </Step>

  <Step title="The customer revokes the consent">
    A mandate becomes `REVOKED` when the customer cancels their consent outside of the platform — for example, by revoking it directly in their bank app (such as the Capitec app for VRP mandates).

    Once `REVOKED`, any further collection attempt is rejected. This transition is initiated by the customer, not the merchant.
  </Step>
</Steps>

### First in series

The merchant offers the consent, the customer authorises it, and the first payment runs as part of the same checkout. By the end of this flow the mandate is active and the payment method is saved.

<div style={{ display: 'flex', justifyContent: 'center' }}>
  ```mermaid theme={"system"}
  flowchart TD
    A([first_in_series session created]) --> B[Mandate DRAFT]
    B --> C[Customer approves the consent]
    C --> D[Payment completed]
    D --> E[Customer payment method is saved]
    E --> F[Mandate ACTIVE]

    classDef start fill:#E8E4FF,stroke:#7C6AE0,stroke-width:1px,color:#1F1A4A;
    classDef pending fill:#F0E2BA,stroke:#B58A2B,stroke-width:1px,color:#3D2A06;
    classDef active fill:#DFF5E4,stroke:#3FA85A,stroke-width:1px,color:#0E3B1B;
    class A start;
    class B pending;
    class F active;
  ```
</div>

### Next in series

The merchant initiates a collection. The platform checks it against everything the customer consented to. If it passes, the payment runs and the mandate is updated; if the consented limit has just been reached, the mandate is marked as `EXPIRED`. If it fails, the collection is rejected and no payment is taken.

<div style={{ display: 'flex', justifyContent: 'center' }}>
  ```mermaid theme={"system"}
  flowchart TD
    A([next_in_series session]) --> B{Validate against<br/>mandate boundaries}
    B -- pass --> C[Payment executed]
    B -- fail --> D[Session rejected]
    C --> E[Mandate updated]
    E -- max_occurrences or<br/>end_date reached --> F[Mandate EXPIRED]
    G([Customer revokes consent<br/>e.g. in bank app]) --> H[Mandate REVOKED]

    classDef start fill:#E8E4FF,stroke:#7C6AE0,stroke-width:1px,color:#1F1A4A;
    classDef ok fill:#DFF5E4,stroke:#3FA85A,stroke-width:1px,color:#0E3B1B;
    classDef rejected fill:#FFE6E2,stroke:#D9534F,stroke-width:1px,color:#5A1A17;
    classDef terminal fill:#F0E2BA,stroke:#B58A2B,stroke-width:1px,color:#3D2A06;
    class A,G start;
    class C ok;
    class D rejected;
    class F,H terminal;
  ```
</div>

## Why a collection might be rejected

Every collection is checked against the consent the customer authorised. If something is off, the collection is rejected with one of the error codes below. The merchant sees the code in the API response; the customer never sees a failed charge on their statement because nothing was attempted at the bank.

| Error                                | What it means in plain English                                                                        |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------- |
| `mandate_not_yet_started`            | The merchant tried to collect before the consented start date.                                        |
| `mandate_expired`                    | The consent's time window has passed; no further collections are allowed.                             |
| `mandate_max_payments_reached`       | The maximum number of consented collections has already been used.                                    |
| `mandate_already_used`               | This particular payment has already been processed under the mandate (typically a retry safeguard).   |
| `mandate_amount_out_of_range`        | The amount falls outside the range the customer consented to.                                         |
| `mandate_amount_exceeds_limit`       | The amount is above the maximum the customer consented to.                                            |
| `mandate_recurrence_day_not_allowed` | The collection isn't happening on one of the days the customer consented to (e.g. wrong weekday).     |
| `invalid_mandate_status`             | The mandate isn't in a state where collections are allowed (e.g. still in draft, or already expired). |
| `mandate_revoked`                    | The customer has revoked their consent; no further collections are allowed.                           |
