Seat-Based Billing

Seat-based billing charges organizations based on the number of team members. The price scales automatically as members join or leave.

Plan Configuration

Seat billing uses the TYPE_PER_SEAT plan type with two key fields:

  • included_seats — Number of seats included in the base price (e.g. 3 seats included in the base $49/mo plan)
  • extra_seat_price — Price in cents for each additional seat beyond the included amount
Plan::create([
    'name'             => 'Team',
    'type'             => Plan::TYPE_PER_SEAT,
    'price'            => 4900,         // $49/mo base
    'included_seats'   => 3,            // 3 seats included
    'extra_seat_price' => 1200,         // $12/mo per extra seat
]);

Seat Calculation

The Plan model provides helper methods for calculating seat quantities:

// How many extra seats are needed beyond the included amount
$plan->extraSeats($totalMembers);
// Returns: max(0, $totalMembers - $this->included_seats)

// The quantity value to send to the payment gateway
$plan->seatQuantityForGateway($totalMembers);
// Returns the number the gateway uses for billing

For example, a plan with 3 included seats and an organization with 5 members results in 2 extra seats billed.

Automatic Seat Sync

The SeatSyncService automatically updates the gateway subscription quantity whenever the team size changes. It is triggered when:

  • A new member joins the organization
  • A member is removed from the organization
  • An invitation is accepted

The service recalculates the total seat count and calls the payment gateway to update the subscription quantity. The gateway then prorates the charge for the current billing period.

// SeatSyncService is called automatically on team changes
$seatSync->sync($organization);

// Internally:
// 1. Count current organization members
// 2. Calculate gateway quantity via $plan->seatQuantityForGateway()
// 3. Update the subscription quantity on the payment gateway

How It Works End-to-End

  • Organization subscribes to a per-seat plan with 3 included seats
  • The base price covers those 3 seats
  • When a 4th member joins, SeatSyncService fires and updates the gateway to bill for 1 extra seat
  • When a member leaves, the seat count is reduced and the gateway adjusts accordingly
  • Proration is handled by the payment gateway (credit for unused time, charge for new seats)