Skip to main content
Per-seat billing ties the recurring charge directly to the number of active seats or members. As a team grows, the bill grows proportionally — making it a natural fit for collaboration tools, CRMs, project managers, and any product where each person consumes a discrete, distinct unit of value. Subscribd implements per-seat plans with rule: 'per_unit', and provides two mechanisms to keep the seat count accurate: an automatic quantity resolver and a manual update action.

Define a per-seat plan

Add the plan to config/subscribd.php. Set rule to 'per_unit' and price to the per-seat amount in minor currency units. Leave the seats feature as null — the quantity field on the subscription drives the bill, not a hard limit.
config/subscribd.php
'plans' => [
    'team_monthly' => [
        'name'           => 'Team',
        'rule'           => 'per_unit',
        'price'          => 800,        // $8.00 per seat/month
        'currency'       => 'USD',
        'interval'       => 'month',
        'interval_count' => 1,
        'features'       => [
            'seats'      => null,       // unlimited, quantity drives the price
            'support'    => 'standard',
        ],
    ],
],
After defining the plan, sync it to the database:
php artisan subscribd:plan sync

Auto-sync seat count via a quantity resolver

Register a quantity resolver in AppServiceProvider::boot(). Whenever Subscribd needs the current seat count for the team_monthly plan, it calls this closure and syncs the value to the gateway automatically.
app/Providers/AppServiceProvider.php
use Pixelworxio\Subscribd\Pricing\QuantityResolverRegistry;

app(QuantityResolverRegistry::class)->register(
    'team_monthly',
    fn ($team, $plan) => $team->members()->where('active', true)->count(),
);
The resolver receives the billable model and the resolved Plan model as arguments. You can use any query or calculation that returns an integer — active members, licensed seats, provisioned accounts, and so on.

Manually push a quantity change

When a member joins or leaves and you need to update the seat count immediately — for example, from an event listener or a controller action — use the UpdateQuantity action:
use Pixelworxio\Subscribd\Actions\UpdateQuantity;

app(UpdateQuantity::class)->execute($subscription, $team->members()->count());
UpdateQuantity pushes the new quantity to the gateway and updates the local Subscription record. The change takes effect on the next invoice unless your gateway applies proration for mid-cycle quantity increases.

When to use per-seat vs flat-rate

ScenarioRecommended model
Every user gets identical access, team size rarely changesFlat-rate
Cost should grow linearly with active membersPer-seat
You want to enforce a seat limit and upsell beyond itPer-seat with entitlement checks
Pricing by features consumed, not headcountTiered or metered
You can combine per-seat billing with entitlement checks. Set a numeric seats value in features to enforce a hard cap, then use Subscribd::entitlements()->for($team)->limitOf('seats') to gate new member invitations.