Sign in →

Subscriptions

Manage the full subscription lifecycle — from trial through active, paused, past-due, and cancellation — with Aforo's 9-state machine.

Updated 2026-06-15Suggest edits

Subscriptions

A subscription links a customer to an offering for a billing period. Aforo tracks the full lifecycle with a 9-state machine, automatic dunning, phase history, and version pinning.

Subscription States

CREATED → TRIALING → ACTIVE → PAST_DUE → PAUSED → EXPIRING_SOON → EXPIRED
                   ↘                   ↘
                    CANCELLED        SUSPENDED
StateDescription
CREATEDInitial state. No billing has started.
TRIALINGFree trial in progress. No charges yet.
ACTIVEBilling is live. Usage accrues and invoices generate.
PAST_DUEPayment failed. Dunning process begins.
PAUSEDOperator-initiated pause. Usage tracking stops.
EXPIRING_SOONNear end of term. Renewal pending.
SUSPENDEDEscalated from PAST_DUE after max dunning attempts.
EXPIREDTerm ended, not renewed.
CANCELLEDTerminal state. No recovery possible.

Phase History

Every state change creates a phase record — an immutable audit trail of when the subscription was in each state, which offering it was on, and why it transitioned.

This enables accurate revenue recognition, dispute resolution, and compliance reporting.

Dunning

When a payment fails, Aforo automatically runs dunning:

  1. Attempt 1 — Retry immediately. Status → PAST_DUE.
  2. Attempt 2 — Retry after 3 days.
  3. Attempt 3 — Retry after 7 days.
  4. Escalation — After max attempts, status → SUSPENDED. Operator notified.

Configure dunning retry intervals in Settings → Billing Config.

Migrations

Plan migrations keep the subscription ID stable across plan changes (Stripe parity). The subscription is updated in-place, preserving:

  • Customer ID
  • createdAt timestamp (for tenure calculations)
  • Billing anchor day
  • Trial remaining days (if migrating from trial)

Scheduled Migrations

Schedule a migration to fire at a future date without operator intervention:

curl -X PUT https://pricing.aforo.ai/api/v1/subscriptions/{id}/schedule-migration \
  -H "Authorization: Bearer $AFORO_API_KEY" \
  -H "X-Tenant-Id: $TENANT_ID" \
  -d '{
    "targetOfferingId": "off_enterprise",
    "migrateAt": "2026-05-01T00:00:00Z",
    "reason": "Annual contract renewal"
  }'

Migration with Pro-ration

When migrating mid-period, Aforo computes three refund surfaces:

  1. Calendar pro-ration — Unused days of the current period at base fee
  2. Wallet refund — Remaining prepaid balance (PREPAID/HYBRID only)
  3. Per-metric quota — Unused included quota, valued at overage rate
curl -X POST https://pricing.aforo.ai/api/v1/subscriptions/{id}/migrate-with-full-proration \
  -d '{
    "targetOfferingId": "off_starter",
    "reason": "Customer downgrade request",
    "consumedPerMetric": { "metric_api_calls": 45000 },
    "autoSettleRefund": true
  }'

Set autoSettleRefund: true to automatically draft a credit note for the refund amount.

Retire-Safety

Before retiring a product, Aforo checks for active subscriptions. If any exist:

  1. List them: GET /api/v1/products/{id}/active-subscriptions
  2. Migrate each: POST /api/v1/subscriptions/{id}/migrate
  3. Confirm retirement with the token returned from the check

RETIRED is a terminal product state. All customer subscriptions must be migrated before retirement is allowed.

Version Pinning

When a subscription is created, Aforo records the exact versions of:

  • The rate plan (pricing)
  • The product (spec, configuration)

These pins ensure existing customers are never affected by pricing or product config changes until you explicitly migrate them.