Skip to main content

Feature Grants

Coupons can do more than apply discounts — they can grant additional feature access or increase plan limits for the duration the coupon is active. This is useful for promotions, beta invites, or time-limited upgrades without a full plan change.

Creating a feature-granting coupon

use Pixelworxio\Subscribd\Models\Coupon;

$coupon = Coupon::create([
    'code'               => 'BETAACCESS',
    'type'               => 'feature_grant',
    'feature_grants'     => [
        'exports'   => true,      // grants boolean feature
        'projects'  => 50,        // increases project limit to 50
        'support'   => 'priority', // overrides string value
    ],
    'duration_in_months' => 1,    // feature access expires after 1 month
    'max_redemptions'    => 200,
    'expires_at'         => now()->addMonth(),
    'applies_to_plans'   => ['free', 'starter'],
]);

How feature grants work

When an active subscription has a feature-granting coupon:
  1. Entitlements::for($user)->allows('exports') checks the base plan first.
  2. If the base plan does not grant the feature, active coupon grants are checked.
  3. The most permissive value wins — a coupon that sets projects: 50 overrides a plan that sets projects: 5.
use Pixelworxio\Subscribd\Facades\Entitlements;

// User is on 'starter' plan (exports: false, projects: 5)
// with 'BETAACCESS' coupon active (exports: true, projects: 50)

Entitlements::for($user)->allows('exports');   // true  — granted by coupon
Entitlements::for($user)->limit('projects');   // 50    — overridden by coupon

Combining with discounts

A coupon can apply both a discount and a feature grant simultaneously:
Coupon::create([
    'code'               => 'PROLAUNCH',
    'type'               => 'percent',
    'amount'             => 30,
    'feature_grants'     => [
        'priority_support' => true,
    ],
    'duration_in_months' => 6,
]);

Expiry behaviour

When the coupon expires or is removed, feature grants are revoked. Entitlement checks return to the base plan values on the next request. No action is required — the entitlement layer always reads the current coupon state.

Next steps