Skip to main content

Plans

Plans are the foundation of Subscribd’s billing model. They’re defined in config/subscribd.php and synced to the subscribd_plans database table via php artisan subscribd:install. Version-controlling your plan definitions in config means plan changes are code-reviewed and deployable like any other application change.

Defining a plan

// config/subscribd.php
'plans' => [
    'pro' => [
        'name'          => 'Pro',
        'description'   => 'Everything you need to grow.',
        'rule'          => 'flat',           // 'flat' | 'per_unit' | 'tiered' | 'metered'
        'amount'        => 4900,             // in minor units (cents)
        'interval'      => 'month',          // 'day' | 'week' | 'month' | 'year'
        'interval_count' => 1,
        'is_recurring'  => true,
        'trial_days'    => 14,
        'features' => [
            'projects'    => 10,
            'api_calls'   => 50000,
            'team_seats'  => 5,
            'exports'     => true,
        ],
    ],
],

Required fields

FieldTypeDescription
namestringDisplay name shown in UI
rulestringPricing rule: flat, per_unit, tiered, or metered
amountintPrice in minor currency units (e.g. cents for USD)
intervalstringBilling cycle: day, week, month, or year

Optional fields

FieldTypeDefaultDescription
descriptionstringnullPlan description for display
interval_countint1Number of intervals per billing period
is_recurringbooltrueSet false for lifetime or one-time plans (excluded from MRR/ARR)
trial_daysint0Free trial length in days
featuresarray[]Feature keys and limits; true for boolean access, integer for limits
trial_requires_payment_methodbooltrueSet false to start trials without collecting a card
cancel_policystringconfig defaultat_period_end, immediately, or immediately_with_refund

Pricing rules

The rule field maps to a pricing class that controls how charges are calculated.

Flat rate

A single recurring charge regardless of usage or quantity:
'starter' => [
    'rule'     => 'flat',
    'amount'   => 1900,
    'interval' => 'month',
],

Per unit

Charge per seat, user, or any countable unit:
'team' => [
    'rule'     => 'per_unit',
    'amount'   => 500,       // per unit per month
    'interval' => 'month',
    'features' => ['seats' => null],  // null = no cap
],

Tiered

Price changes at volume breakpoints:
'growth' => [
    'rule'     => 'tiered',
    'interval' => 'month',
    'tiers'    => [
        ['from' => 0,    'to' => 10,   'unit_price' => 500],
        ['from' => 11,   'to' => 50,   'unit_price' => 400],
        ['from' => 51,   'to' => null, 'unit_price' => 300],
    ],
],

Metered

Charge based on actual usage reported at the end of each billing period:
'api' => [
    'rule'     => 'metered',
    'interval' => 'month',
    'amount'   => 0,         // base charge
    'features' => [
        'api_calls' => ['unit_price' => 1, 'included' => 10000],
    ],
],

Plan items

PlanItems are composable add-ons that attach to a plan. Each item has a key, an included_quantity, and a unit_price for overages. They’re defined in the database via the Filament admin panel or via the plan:item Artisan command, and sync to subscribd_plan_items. When a subscription is created, Subscribd hydrates one SubscriptionItem record per active PlanItem on the plan. Customers can select per-item quantities at checkout via the PlanPicker Livewire component.
// Creating a subscription with PlanItem quantity overrides
$user->subscription()->create($proPlan, [
    'plan_items' => [
        'extra_projects' => 3,
        'api_add_on'     => 1,
    ],
]);

Free plans

Set amount to 0 to create a free plan. Subscribd automatically routes zero-cost subscriptions through the null gateway — no payment method is required and no gateway API call is made:
'free' => [
    'name'     => 'Free',
    'rule'     => 'flat',
    'amount'   => 0,
    'interval' => 'month',
    'features' => ['projects' => 1, 'api_calls' => 1000],
],

Lifetime plans

Set is_recurring to false for one-time charges that never renew. Lifetime plans are excluded from MRR and ARR calculations:
'lifetime' => [
    'name'         => 'Lifetime',
    'rule'         => 'flat',
    'amount'       => 39900,
    'interval'     => 'month',   // interval is required but ignored for one-time charges
    'is_recurring' => false,
],

Syncing plans to the database

After modifying config/subscribd.php, run:
php artisan subscribd:install
This upserts the subscribd_plans table from config. Existing subscriptions are unaffected — the plan record is updated in place, not replaced. You can also manage plans directly in the Filament admin panel at /subscribd/admin.

Next steps