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

# Postpaid Billing

> The default billing mode. Monigo aggregates a period's usage, finalizes an invoice, and collects payment through your connected payment provider — with automatic dunning retries when a charge fails.

**Postpaid billing** is how Monigo works out of the box. The customer consumes usage during a billing period, and at period end Monigo aggregates that usage, generates an invoice, finalizes the amounts, and then collects payment through your connected payment provider. The customer pays *after* the usage has happened — in arrears.

This is the right default for most products:

* SaaS with a card on file that you charge at the end of each cycle
* Usage-based products billed monthly in arrears
* Customers you trust to pay after consumption rather than pre-funding an account

If instead you want the customer to pre-fund a balance and have it debited at billing time, see [Prepaid Billing](/guides/prepaid-billing). To debit a wallet continuously as usage accrues, see [Real-Time Billing](/guides/realtime-billing).

<Info>
  Postpaid is the default `billing_mode` for every plan. You don't have to set anything — it's what you get when you omit `billing_mode`. Payout plans always use the postpaid flow.
</Info>

## How it works

```mermaid theme={null}
flowchart TD
    A[Period Ends] --> B[Usage Aggregated<br>+ Pricing Applied]
    B --> C[Draft Invoice Generated]
    C --> D[Invoice Finalized<br>amounts locked]
    D --> E[/invoice.finalized webhook fired/]
    E --> F[Charge Attempted<br>via Payment Provider]

    F --> G{Payment Succeeds?}

    G -->|YES| H[Invoice Marked 'paid']
    H --> I[Period Advances]
    I --> J[/invoice.paid webhook fired/]

    G -->|NO| K[Invoice Stays 'finalized']
    K --> L[/payment.failed webhook fired/]
    L --> M[Dunning Retries<br>day 1 · day 4 · day 7]
    M --> N{Recovered?}
    N -->|YES| H
    N -->|NO| O[Subscription Suspended]
    O --> P[/subscription.suspended webhook fired/]

    style A fill:#1F2937,color:#fff,stroke:#374151
    style B fill:#F3F4F6,color:#1F2937,stroke:#D1D5DB
    style C fill:#F3F4F6,color:#1F2937,stroke:#D1D5DB
    style D fill:#F3F4F6,color:#1F2937,stroke:#D1D5DB
    style E fill:#DCFCE7,color:#14532D,stroke:#16A34A
    style F fill:#F3F4F6,color:#1F2937,stroke:#6B7280
    style G fill:#F3F4F6,color:#1F2937,stroke:#6B7280
    style H fill:#DCFCE7,color:#14532D,stroke:#16A34A
    style I fill:#DCFCE7,color:#14532D,stroke:#16A34A
    style J fill:#16A34A,color:#fff,stroke:#14532D
    style K fill:#FEF3C7,color:#92400E,stroke:#F59E0B
    style L fill:#FEF3C7,color:#92400E,stroke:#F59E0B
    style M fill:#FEF3C7,color:#92400E,stroke:#F59E0B
    style N fill:#F3F4F6,color:#1F2937,stroke:#6B7280
    style O fill:#FEE2E2,color:#991B1B,stroke:#EF4444
    style P fill:#FEE2E2,color:#991B1B,stroke:#EF4444
```

Everything in this flow runs automatically once a subscription's period ends — you don't trigger any of it by hand.

***

## Setting up a postpaid plan

Because postpaid is the default, you can simply omit `billing_mode`. It's shown explicitly below for clarity:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.monigo.co/v1/plans \
    -H "Authorization: Bearer mk_live_..." \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Metered API",
      "currency": "NGN",
      "plan_type": "collection",
      "billing_period": "monthly",
      "billing_mode": "postpaid"
    }'
  ```

  ```go Go theme={null}
  plan, err := client.Plans.Create(ctx, monigo.CreatePlanParams{
      Name:          "Metered API",
      Currency:      "NGN",
      PlanType:      "collection",
      BillingPeriod: "monthly",
      BillingMode:   "postpaid", // optional — this is the default
  })
  ```

  ```ts TypeScript theme={null}
  const plan = await client.plans.create({
    name: "Metered API",
    currency: "NGN",
    plan_type: "collection",
    billing_period: "monthly",
    billing_mode: "postpaid", // optional — this is the default
  });
  ```
</CodeGroup>

Postpaid works with every `billing_period` (`daily`, `weekly`, `monthly`, `quarterly`, `annually`) and every pricing model. See [Pricing Models](/guides/pricing-models) for the full set.

***

## The billing cycle at period end

When a postpaid period closes, Monigo runs these steps automatically:

1. **Aggregates usage** — all events ingested during the period are rolled up per metric.
2. **Calculates the invoice total** — each price rule is applied to its metric's aggregated value; VAT is added if configured.
3. **Generates a draft invoice** — one line item per metric/price pair.
4. **Finalizes the invoice** — amounts are locked, status moves to `finalized`, and `invoice.finalized` fires.
5. **Attempts collection** — Monigo charges the customer through your connected payment provider.
6. **Advances the period** — the subscription moves to its next billing period.

For the period-level view of this, see [Billing Cycle](/concepts/billing-cycle).

***

## The happy path: payment succeeds

When collection succeeds, the invoice moves to `paid`, `paid_at` is stamped, and an `invoice.paid` webhook fires.

The resulting invoice will have:

| Field          | Value                                            |
| -------------- | ------------------------------------------------ |
| `status`       | `"paid"`                                         |
| `paid_at`      | Timestamp of the successful charge               |
| `wallet_debit` | `false` (unless a wallet covered it — see below) |

How Monigo collects, in order:

1. **Wallet** — if the customer has a wallet with enough balance, it's debited first.
2. **Saved card** — otherwise the default card on file (captured from prior successful charges) is charged.
3. **Payment link** — if there's no chargeable card, Monigo emails the customer a hosted payment link to settle the invoice.

<Info>
  A card is added to the customer's file automatically the first time they pay through a provider — there's no separate "save card" step. Subsequent invoices can then be charged without customer interaction.
</Info>

***

## Handling failed payments

If collection fails (insufficient funds, expired card, provider decline), the invoice **stays `finalized`** and a `payment.failed` webhook fires. Monigo then begins **dunning** — it automatically retries collection on a fixed schedule:

| Attempt | When                     |
| ------- | ------------------------ |
| Retry 1 | 1 day after the failure  |
| Retry 2 | 4 days after the failure |
| Retry 3 | 7 days after the failure |

```json payment.failed theme={null}
{
  "event": "charge.failed",
  "data": {
    "reference": "pay_abc123",
    "amount": 500000,
    "currency": "NGN"
  }
}
```

If any retry succeeds, the invoice moves to `paid` and `invoice.paid` fires — the dunning sequence ends there.

<Tip>
  Use the `payment.failed` webhook to nudge the customer early — an email or in-app banner asking them to update their card often recovers the payment before the dunning retries are exhausted.
</Tip>

***

## When dunning is exhausted

If all three retries fail, Monigo suspends the subscription and fires `subscription.suspended`:

```json subscription.suspended theme={null}
{
  "customer_id": "01924f1e-...",
  "customer_name": "Acme Corp",
  "subscription_id": "01924f1e-...",
  "invoice_id": "01924f1e-...",
  "amount": "5000.000000",
  "currency": "NGN"
}
```

A suspended subscription stops accruing billable usage. To recover it, have the customer settle the outstanding invoice (update their card and retry the charge, or pay the hosted link), then resume the subscription:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.monigo.co/v1/subscriptions/<subscription_id>/resume \
    -H "Authorization: Bearer mk_live_..."
  ```

  ```go Go theme={null}
  sub, err := client.Subscriptions.Resume(ctx, subscriptionID)
  ```

  ```ts TypeScript theme={null}
  const sub = await client.subscriptions.resume(subscriptionId);
  ```
</CodeGroup>

<Warning>
  Don't void a `finalized` invoice just to stop dunning — voiding cancels the charge entirely and the customer is never billed for that period. Use it only when the customer genuinely should not be charged. See [Invoice Lifecycle](/guides/invoice-lifecycle).
</Warning>

***

## Webhook events

| Event                    | When fired                                            |
| ------------------------ | ----------------------------------------------------- |
| `invoice.finalized`      | Period closed; amounts locked, collection starting    |
| `payment.success`        | A charge succeeded at the provider                    |
| `invoice.paid`           | Invoice settled; `paid_at` set                        |
| `payment.failed`         | A charge attempt failed (dunning begins/continues)    |
| `subscription.suspended` | All dunning retries exhausted; subscription suspended |

Register a webhook endpoint in the [Webhooks guide](/integrations/webhooks) to receive these events and verify their signatures.

***

## Customer portal

In the customer portal, postpaid subscriptions show the customer their invoices (draft, finalized, paid, void), the estimated total for the current open period, and their saved payment methods. When an invoice is unpaid, the portal surfaces a **Pay now** action backed by your payment provider — no code required on your side.

***

## Comparing the billing modes

|                    | Postpaid (default)         | Prepaid                      | Real-time                        |
| ------------------ | -------------------------- | ---------------------------- | -------------------------------- |
| `billing_mode`     | `"postpaid"`               | `"prepaid"`                  | `"realtime"`                     |
| When charged       | At period end, in arrears  | At period end, from wallet   | Continuously (\~5s), from wallet |
| Invoice created    | As `draft`, then finalized | Directly as `paid`           | One `paid` summary at period end |
| Payment collection | Provider (card/bank/link)  | Debited from wallet          | Debited from wallet              |
| Failed payment     | Dunning retries → suspend  | Subscription paused          | Subscription paused              |
| Recovery           | Settle invoice → resume    | Top up → auto-resume         | Top up → auto-resume             |
| Best for           | SaaS with card-on-file     | APIs with credit/token packs | AI agents, pay-as-you-go usage   |

***

## Related

* [Billing Cycle](/concepts/billing-cycle) — how periods work and when billing runs
* [Invoice Lifecycle](/guides/invoice-lifecycle) — draft → finalized → paid → void
* [Subscription Lifecycle](/guides/subscription-lifecycle) — pause, resume, suspend, and cancel
* [Prepaid Billing](/guides/prepaid-billing) — wallet debited at period end
* [Real-Time Billing](/guides/realtime-billing) — wallet debited continuously as usage accrues
* [Webhooks](/integrations/webhooks) — receiving billing events
