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

# Subscriptions

> Recurring revenue on autopilot

## Recurring Revenue. Automated.

Customers subscribe. We handle billing cycles, renewal recovery, and lifecycle management. You focus on your product.

***

## How It Works

```
Customer subscribes → Billing cycle → Auto-charge → Repeat
```

If a renewal charge is not collected successfully, the subscription enters `past_due`. This is a recovery state, not an immediate termination state. The system can keep the subscription in a grace or retry window while the customer updates payment details.

***

## Subscription Plan Structure

In Waffo Pancake, each **separately purchasable subscription option** is an independent subscription product.

The most common distinction is billing interval, such as:

* monthly
* yearly

If you offer both monthly and yearly billing, you would normally create **two subscription products**.

| Business offer | Waffo model            |
| -------------- | ---------------------- |
| Monthly plan   | 1 subscription product |
| Yearly plan    | 1 subscription product |

***

## Subscription States

| Status      | Description                                                        |
| ----------- | ------------------------------------------------------------------ |
| `pending`   | Awaiting first payment                                             |
| `active`    | Live and billing normally                                          |
| `trialing`  | In free trial period                                               |
| `past_due`  | Renewal charge not collected, in recovery or grace period          |
| `canceling` | Cancellation requested, access continues until current period ends |
| `canceled`  | Will not renew after current period                                |
| `expired`   | Subscription has reached the end of its term                       |
| `closed`    | Never activated — payment timed out                                |

***

## Billing Intervals

| Interval  | Frequency       | Best For             |
| --------- | --------------- | -------------------- |
| Weekly    | Every 7 days    | Usage-heavy products |
| Monthly   | Every month     | Standard SaaS        |
| Quarterly | Every 3 months  | B2B software         |
| Yearly    | Every 12 months | Committed customers  |

***

## Free Trials

Reduce signup friction. Let customers try before they commit.

### Configure Trials

When creating a subscription product, enable the trial toggle and set the number of days in the Dashboard.

### Platform-Level Trial Protection

Waffo Pancake acts as the Merchant of Record and automatically prevents trial abuse:

| Layer                  | How It Works                                                                                                                      |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **Platform (Pancake)** | Tracks each consumer's trial history across all merchants. Calculates the maximum available trial days for each new subscription. |
| **Merchant**           | Can pass `requested_trial_days` when creating an order via API to customize the trial length per customer.                        |

**How the two layers interact:**

* If the merchant requests ≤ the platform maximum → the merchant's requested value is used
* If the merchant requests > the platform maximum → falls back to the platform maximum
* If the merchant doesn't specify → the full platform maximum is used

### Buyer Identity & Trial Protection

Trial eligibility is tracked by `buyerIdentity` — a stable identifier you provide via [authenticated checkout](/integrate/sdks#authenticated-checkout-recommended). The platform uses this to detect repeat trial claims across sessions.

<Warning>
  Without `buyerIdentity` (anonymous checkout), trial eligibility checks are skipped entirely. Any buyer can claim unlimited trials by changing their email address.
</Warning>

<Tip>
  7-14 day trials work best. Too short = not enough time to evaluate. Too long = forgotten.
</Tip>

***

## Renewal Recovery

When a renewal charge is not collected successfully, the subscription transitions to `past_due`. This usually means the subscription is in a retry or grace window while the customer updates their payment method, not that access is terminated immediately.

Common handling includes:

* notifying the customer to update payment details
* keeping access active during a grace period
* retrying collection based on the dunning policy

<Note>
  Treat `past_due` as "renewal requires recovery", not simply "payment failed and service stopped".
</Note>

***

## Managing Subscriptions

### Cancel

Cancellation is always effective at the end of the current billing period. When a cancellation is requested, the subscription enters the `canceling` intermediate state. The customer retains access until the current billing period ends, at which point the status transitions to `canceled`.

```bash theme={"system"}
POST /v1/actions/subscription-order/cancel-order
{
  "orderId": "ORD_5dXBtmF2HLlHfbPNm0Wcnz"
}
```

Response includes `currentPeriodEnd` so you know when access expires. The returned status will be `canceling` (or `canceled` if the period has already ended).

<Note>
  There is no immediate cancellation option. Customers always retain access through the end of their paid period. The `canceling` → `canceled` transition happens automatically when the current billing period expires.
</Note>

### Resume Subscription

If a subscription is still in `canceling`, the customer can resume it before the current period ends.

After resuming:

* the subscription returns to `active`
* access continues without interruption
* future renewals continue on the original billing cycle

<Note>
  Resuming applies to subscriptions that were canceled but have not reached the end of the current period yet. It is effectively an undo for cancellation, not a brand-new purchase.
</Note>

### Upgrade/Downgrade

| Scenario            | Behavior                                              |
| ------------------- | ----------------------------------------------------- |
| Upgrade mid-cycle   | Takes effect immediately                              |
| Downgrade mid-cycle | Takes effect at the end of the current billing period |

```bash theme={"system"}
POST /v1/actions/subscription-order/change-product
{
  "orderId": "550e8400-e29b-41d4-a716-446655440000",
  "targetProductId": "target-product-uuid"
}
```

<Warning>
  This endpoint currently returns 501 (Not Implemented). Upgrade/downgrade functionality is planned but not yet available.
</Warning>

## Metrics

### MRR (Monthly Recurring Revenue)

```
Weekly subscription:    $10 × 4.33 = $43.30 MRR
Monthly subscription:   $29 × 1 = $29 MRR
Annual subscription:    $290 ÷ 12 = $24.17 MRR
```

### Key Metrics

| Metric | What It Tells You         |
| ------ | ------------------------- |
| MRR    | Monthly recurring revenue |
| Churn  | % subscriptions canceled  |
| LTV    | Customer lifetime value   |
| ARPU   | Average revenue per user  |

***

## Webhooks

Subscribe to subscription lifecycle events via webhooks. Configure webhook endpoints in **Settings --> Webhooks**.

<Warning>
  Specific webhook event names are not listed here as they may change. Refer to the webhook configuration in your Dashboard for the current list of available events.
</Warning>

Webhook payloads use standard Waffo Pancake conventions:

* IDs are UUID v4 format
* Amounts as display format strings
* Timestamps in ISO 8601 UTC
* Billing frequency uses the `billingPeriod` field (e.g., `monthly`, `yearly`)

***

## Customer Portal

Let customers manage their own subscriptions:

* View details
* Update payment method
* Change plans
* Cancel
* Resume subscription
* Download invoices

<Card title="Customer Portal" icon="user" href="/features/customer-portal">
  Self-service subscription management.
</Card>

***

## Best Practices

<AccordionGroup>
  <Accordion title="Offer annual discounts">
    15-20% off yearly = lower churn + better cash flow.
  </Accordion>

  <Accordion title="Don't cut access immediately">
    A missed renewal charge does not need to mean instant cancellation. Give the customer time to recover the subscription.
  </Accordion>

  <Accordion title="Send reminders">
    Trial ending. Upcoming charge. No surprises.
  </Accordion>
</AccordionGroup>
