Subscriptions — Reference
The Subscriptions surface is the recurring-billing plane for SGEN. It owns subscription plan definitions, customer subscription records, billing cycle scheduling, proration on plan change, dunning workflow on payment failure, and the customer-facing self-service portal that lets a subscriber view invoices, change a plan, update a payment method, or cancel. Anything that asks "is this customer on a paying plan, and what should be charged next?" traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before scripting against it, extending the plan catalog, or scoping a billing model. Customer-facing subscription walkthroughs live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Subscriptions live under the Subscriptions module in SG-Admin. The module renders four primary views — the plan catalog (every recurring offer the site sells), the subscription list (every active and inactive customer subscription), the subscription detail view (one record with invoice history, payment method, and lifecycle log), and the dunning queue (subscriptions in retry after a failed charge).
The module is paired by convention with the Payments surface. Subscriptions defines the recurring cadence; Payments handles the per-charge gateway call. Engineers reading the SG-Admin source will see the Subscriptions controller hand off to the Payments controller at charge time, then receive the gateway result and update the subscription state. The Subscriptions module owns the recurring schedule; Payments owns each individual transaction.
A second surface — the customer self-service portal — extends the model on the customer side. A subscriber visits a tokenized portal URL (issued at subscription creation, refreshable from the operator side) and sees their own subscription record. From the portal, they can view invoices, change plan (subject to per-plan eligibility rules), update payment method, pause, or cancel. The portal is a read / write surface from the customer's perspective and a read-only view from the operator's side.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Subscriptions
- URL prefix:
/sg-admin/subscriptions/ - View templates:
application/views/Admin/Subscriptions/ - Customer portal:
/account/subscriptions//
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Subscriptions [+ New subscription]│├──────────────────────────────────────────────────────────────────────┤│ Customer Plan Cycle Next charge State ││ ────────────────── ─────────── ─────── ───────────── ────────── ││ Maria Reyes Pro Monthly Monthly 2026-06-04 Active ││ James Compton Suite Year Yearly 2026-08-12 Active ││ Sandbox Demo Pro Monthly Monthly 2026-05-23 Dunning(2) ││ Carlos Lim Starter Monthly — Cancelled ││ Anna Cruz Pro Monthly Monthly — Paused ││ ││ [⋯ View] [⋯ Change plan] [⋯ Cancel] [⋯ Resend portal link] │└──────────────────────────────────────────────────────────────────────┘Actions
The Subscriptions surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List plans
Returns every subscription plan currently configured on the site. Each row carries the plan slug, display name, billing interval (monthly, quarterly, yearly), price per cycle, currency, trial length (if any), and the subscriber count currently on the plan.
Create or edit plan
Opens the plan form. Fields cover slug, display name, description, interval, price per cycle, currency, trial length, plan-change eligibility (which other plans a subscriber can move to from this plan), and feature mapping (what platform capabilities subscribers on this plan receive). Editing a plan does not retroactively change existing subscriptions — they continue on the plan terms recorded at the time they subscribed.
List subscriptions
Returns every customer subscription on the site, filterable by state (active, paused, cancelled, dunning), plan, and customer. Each row shows the customer name, plan, billing cycle, next charge date, and current state.
Create subscription
Opens an empty subscription form. Required fields: customer (identifier or new-customer create), plan (from the catalog), payment method (tokenized via the Payments surface), and start date (immediate or scheduled). On submit, the surface persists the subscription, schedules the first charge, and (if a trial is configured) records the trial end date.
Change plan
Moves an existing subscription to a different plan. The change runs proration — the unused portion of the current cycle credits against the prorated cost of the new plan for the remainder of the cycle. The next cycle then bills the new plan in full. Proration math runs in cents to avoid rounding drift. Plan-change eligibility is enforced — a subscription on a plan with restricted eligibility (some plans are no-downgrade) returns a structured rejection.
Pause subscription
Marks a subscription paused. Paused subscriptions do not bill. The pause carries an optional resume date — if set, a background sweep resumes the subscription automatically; if absent, the subscription stays paused until a manual resume.
Resume subscription
Reverses a pause. The subscription returns to the active state and the next charge is scheduled. If the resume date falls inside the original billing cycle, the cycle continues; if it falls after, a new cycle begins from the resume date.
Cancel subscription
Marks a subscription cancelled. Cancellation can be immediate (the subscription ends today, no further charges) or end-of-cycle (the subscription continues through the current cycle, no further charges after). The choice is per-cancel — the operator picks at cancel time, and the customer portal exposes the same choice.
Issue invoice
Generates an invoice record for a subscription's upcoming or current charge. The invoice carries line items (plan price, any add-ons, any proration credit, any tax), a total, a status (draft, issued, paid, failed, void), and a PDF artifact. Invoices issue automatically on the cycle date but can be issued manually for off-cycle charges.
Process charge
Submits an invoice to the Payments gateway. The gateway returns success, failure, or a deferred result; the subscription updates accordingly. On success, the subscription's next charge date advances by one cycle. On failure, the subscription enters dunning.
Run dunning step
Advances a subscription through the configured dunning sequence — a series of retry attempts at configured intervals (the default sequence is day 3, day 7, day 14 after failure). Each retry runs Process charge against the recorded payment method. On exhausted retries, the subscription is marked cancelled with a dunning failure reason.
Resend portal link
Reissues a fresh self-service portal token for a subscription and emails it to the customer. Useful when the original token has expired or the customer has lost the link. The old token is invalidated.
Refund charge
Reverses a previously processed charge. The refund routes through the Payments surface to the gateway. Refunds are recorded against the original invoice (the invoice carries the refund line item and updates to a partial-refund or fully-refunded state) and surfaced in the subscription's lifecycle log.
Data model
A subscription plan carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. |
slug | string | Plan identifier. Stable after create. |
display_name | string | Display label. |
description | string | Optional. Surfaced in plan picker and customer portal. |
interval | enum | monthly, quarterly, yearly, custom. |
price_cents | integer | Price per cycle in cents. Currency from the currency field. |
currency | string | ISO 4217 code (USD, PHP, EUR, etc.). |
trial_days | integer | Optional. Length of free trial at subscription start. |
eligible_change_targets | JSON | Array of plan slugs a subscriber can change to from this plan. |
feature_map | JSON | Map of platform feature identifier → enabled / disabled / limit value. |
is_archived | boolean | True for retired plans. Existing subscriptions on archived plans continue; new subscriptions cannot select an archived plan. |
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. |
customer_id | integer | The subscribing customer. |
plan_id | integer | Current plan. Changes on plan change; original plan retained in the lifecycle log. |
state | enum | active, paused, cancelled, dunning. |
cycle_start_at | timestamp | Start of the current billing cycle. |
next_charge_at | timestamp | Scheduled date of the next charge. |
trial_ends_at | timestamp | Optional. End of the trial period, if a trial was configured. |
payment_method_token | string | Tokenized payment method, opaque to the surface, resolved by the Payments gateway. |
portal_token | string | Tokenized self-service portal identifier. Rotatable. |
cancelled_at | timestamp | Set on cancel. Records when the cancellation was initiated. |
cancel_at_period_end | boolean | True for end-of-cycle cancels; false for immediate. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any state change. |
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. |
subscription_id | integer | Parent subscription. |
state | enum | draft, issued, paid, failed, void, partial_refund, refunded. |
line_items | JSON | Array — plan price, add-ons, proration credit, tax. |
total_cents | integer | Sum of line items. |
currency | string | ISO 4217 code. |
issued_at | timestamp | Set on issue. |
paid_at | timestamp | Set on successful charge. |
pdf_url | string | Resolves against the Media library. |
Dunning semantics: a charge failure moves the subscription to dunning state. The configured retry sequence schedules background retries at the configured intervals. Each retry runs through Process charge; on the first success, the subscription returns to active and the next cycle advances. On exhausted retries, the subscription is marked cancelled with a dunning failure reason recorded in the lifecycle log.
Portal token semantics: the portal token is the customer's authentication for the self-service surface. Tokens are long, opaque, and tied to a single subscription. Tokens can be rotated (any rotate invalidates prior tokens), are revoked on customer cancellation, and have no expiration by default — though a per-site setting can configure expiration if a tighter posture is required.
SUBSCRIPTION LIFECYCLE│▼Create (immediate or scheduled start)│▼Active ──► Cycle date arrives ──► Issue invoice ──► Process charge│ ││ ┌────┴────┐│ ▼ ▼│ success failure│ │ ││ ▼ ▼│ advance Dunning│ next_charge_at ││ │ retry sequence│ │ (day 3, 7, 14)│ │ ││ │ ┌─┴─┐│ │ ▼ ▼│ │ success cancel│ │ │ (dunning│ │ │ failure)│ ▼ ││ back to Active│├──► Operator pause / customer pause ──► Paused (no billing)├──► Operator cancel / customer cancel ──► Cancelled (immediate or end-of-cycle)└──► Plan change ──► proration adjustment on next invoicePermissions
Access to the Subscriptions surface is gated at two layers.
Layer 1 — admin gate. Every operator-side action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated operator request never reaches the Subscriptions surface. The customer portal has its own token-based authentication and bypasses the operator admin gate.
Layer 2 — per-action capability. Within SG-Admin, each Subscriptions action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List plans | ✔ | ✔ | ✔ |
| Create or edit plan | ✔ | — | — |
| List subscriptions | ✔ | ✔ | ✔ |
| View subscription | ✔ | ✔ | ✔ |
| Create subscription | ✔ | ✔ | — |
| Change plan | ✔ | — | — |
| Pause subscription | ✔ | ✔ | — |
| Resume subscription | ✔ | ✔ | — |
| Cancel subscription | ✔ | — | — |
| Issue invoice | ✔ | ✔ | — |
| Process charge | ✔ | — | — |
| Run dunning step | ✔ | — | — |
| Resend portal link | ✔ | ✔ | — |
| Refund charge | ✔ | — | — |
Money-write protection. Refunds, manual charge runs, and plan changes that decrease cycle revenue all carry a confirmation step at the form layer. The platform does not require a second operator's approval by default — but a per-site Settings flag can require a second-administrator confirmation on refunds exceeding a configurable threshold.
Gateway pass-through. Every charge run hands off to the Payments gateway. The Subscriptions surface itself never sees the raw payment method — only the gateway-issued token. Failures returned by the gateway are recorded with the gateway's failure code and a human-readable reason; the surface does not retry blindly on failures with codes that the gateway has marked as non-retriable (expired card, lost card, suspected fraud).
Audit. Every operator write — plan create, plan edit, subscription create, plan change, pause, resume, cancel, invoice issue, charge process, refund, portal link resend — emits an Activity Log entry. Customer portal writes also emit Activity Log entries, tagged with the portal source. Charge runs (success and failure) are recorded in a higher-volume billing log queryable from the Subscriptions surface. Subscription state transitions are recorded in the per-subscription lifecycle log surfaced on the subscription detail view.
PRORATION ON PLAN CHANGE│ scenario: 15 days into a 30-day monthly cycle│ current plan: Pro Monthly @ $50.00 / month│ target plan : Suite Monthly @ $80.00 / month▼┌─────────────────────────────────────────┐│ Credit on current plan (unused portion) ││ = (5000 cents / 30 days) × 15 days ││ = 2500 cents = $25.00 │└─────────────────────────────────────────┘│▼┌─────────────────────────────────────────┐│ Debit on new plan (remaining portion) ││ = (8000 cents / 30 days) × 15 days ││ = 4000 cents = $40.00 │└─────────────────────────────────────────┘│▼┌─────────────────────────────────────────┐│ Net adjustment posts to next invoice ││ = 4000 − 2500 = 1500 cents = $15.00 ││ NEXT invoice line items: ││ Suite Monthly (next full cycle) $80.00││ Proration adjustment $15.00││ Total $95.00│└─────────────────────────────────────────┘Related references
- Payments — Reference. The gateway hand-off surface. Every charge run, refund, and payment-method tokenization routes through Payments. The Subscriptions surface holds the schedule; Payments holds the transaction record.
- Users — Reference. The customer record on a subscription is a user record on the customer side of the platform. Operator and customer identities share the user table but carry different role and authentication shapes.
- Notifications — Reference. Subscription-related emails (invoice issued, charge succeeded, charge failed, dunning step run, portal link issued, cancellation confirmed) all route through the Notifications channel.
- Settings — Reference. Currency defaults, dunning sequence configuration, portal token expiration, and money-write confirmation thresholds all live under Settings.
- Roles — Reference. The capability map above resolves through the Roles catalog. Plan-edit and refund capabilities are typically restricted to Administrator-tier roles.
- Permissions — Reference. The capability identifiers (
subscriptions.manage,subscriptions.refund,subscriptions.cancel) are defined in the Permissions catalog. - Tools — Reference. Activity Log entries for subscription writes are queryable from Tools alongside the rest of the audit log.
/docs/subscriptions.