Skip to main content
A subscription is a named billing slot that links a billable model to a plan through a payment gateway. Each subscription record tracks its current status, the gateway’s own identifier, the quantity (for per-seat plans), and any applied coupon. Understanding how subscriptions transition between statuses is key to building reliable billing logic in your application.

Subscription lifecycle

A subscription begins in one of two states depending on whether the plan has a trial period, then progresses through the following transitions:
created

  ├── trial_days > 0 ──► trialing ──► active
  │                                     │
  └── trial_days = 0 ──► active ────────┤

                            ┌────────────┤
                            │            │
                          grace       past_due
                            │            │
                         canceled     canceled

                                       active  (payment recovered)
All status transitions are validated by SubscriptionStatus::canTransitionTo(). Attempting an invalid transition (e.g., from canceled back to active) throws an exception. Use resumeSubscription() to restore a grace-period subscription to active.

SubscriptionStatus enum values

StatusDescription
activeSubscription is current and paid
trialingWithin the free trial period; not yet charged
past_duePayment failed; dunning retries are in progress
graceSubscription was canceled but the period has not yet ended
pausedManually paused; billing is suspended
canceledSubscription has ended
incompleteInitial payment never completed (e.g., 3D Secure abandoned)

Checking subscription status

The ManagesBilling trait adds helper methods directly to your billable model:
$user->subscribed();               // has any active or trialing subscription
$user->subscribed('default');      // has a specific named subscription
$user->onTrial('default');         // named subscription is in trial period
$user->onGracePeriod('default');   // canceled but grace period not yet expired
Use $user->subscribed() as the default gate for paid features. It returns true for both active and trialing statuses, which is usually what you want during a free trial.

Query scopes

The Subscription model ships with scopes for filtering by status:
use Pixelworxio\Subscribd\Models\Subscription;

Subscription::active()->get();
Subscription::pastDue()->get();
Subscription::paused()->get();
These are useful in admin panels, reporting pages, or anywhere you need to operate on a set of subscriptions filtered by status.

Pausing and resuming

use Pixelworxio\Subscribd\Actions\PauseSubscription;

// Pause
app(PauseSubscription::class)->execute($subscription);

// Resume (works for both paused and grace-period subscriptions)
Subscribd::for($user)->resume();

Multiple named subscriptions

A single billable can hold independent subscriptions simultaneously. Each subscription has a name that defaults to 'default'. Use the name option when subscribing to create additional slots:
Subscribd::for($user)->subscribe('starter', ['name' => 'default']);
Subscribd::for($user)->subscribe('extra-storage', ['name' => 'storage']);
Status checks and cancellations target a specific name:
$user->subscribed('storage');
$user->onGracePeriod('storage');

Subscribd::for($user)->cancel('storage');
Multiple subscriptions are independent — canceling 'storage' does not affect 'default'. Entitlements can be checked across all active slots at once using forAll(). See Entitlements for details.

Canceling a subscription

// Cancel at the end of the current billing period (default)
Subscribd::for($user)->cancelSubscription();

// Cancel immediately — no grace period
Subscribd::for($user)->cancelSubscription('default', immediately: true);
The global default cancel behavior is set in config:
'cancel_policy' => 'at_period_end',  // 'at_period_end' | 'immediately'