Manage Seats

Selling to teams means your product must handle members joining and leaving while keeping billing and access in sync with every change. Salable makes this straightforward by splitting seat management into two controls you handle independently: the quantity on the per-seat Line Item, and the users who fill those seats.

Add, remove or replace team members

Grantees belong to the Group attached to the Subscription Plan, and you manage them with POST /api/groups/{id}/grantees. The body is an array of actions, each with a type, so you can apply several changes in one call. Each add is validated against the Group's current membership, not the batch's net result, so a remove in the same request does not free a seat for an add. To swap a member when the Group is already at its seat limit, use a single replace action, which frees and fills the seat together.

Add a member

Salable creates the Grantee if it's new, or attaches an existing one:

import { Salable } from '@salable/sdk';
const salable = new Salable(process.env.SALABLE_SECRET_KEY);
 
await salable.api.groups.byId('grp_01HXACMETEAM').grantees.post([
    {
        type: 'add',
        granteeId: 'user_charlie',
        name: 'Charlie Brown'
    }
]);

Remove a member

import { Salable } from '@salable/sdk';
const salable = new Salable(process.env.SALABLE_SECRET_KEY);
 
await salable.api.groups.byId('grp_01HXACMETEAM').grantees.post([
    {
        type: 'remove',
        granteeId: 'user_dana'
    }
]);

Replace a member

Replace one member with another in a single step, keeping the seat filled.

import { Salable } from '@salable/sdk';
const salable = new Salable(process.env.SALABLE_SECRET_KEY);
 
await salable.api.groups.byId('grp_01HXACMETEAM').grantees.post([
    {
        type: 'replace',
        granteeId: 'user_dana',
        newGranteeId: 'user_charlie',
        name: 'Charlie Brown'
    }
]);
FieldDescription
typeThe action to run: add, remove, or replace.
granteeIdYour identifier for the Grantee. On replace, the Grantee being removed.
newGranteeIdThe Grantee to add in their place. Required for replace.
nameOptional. A display name for the Grantee, used by add and replace.

A successful call returns 204 No Content. An add creates the Grantee if it's new, or attaches the existing one; adding a Grantee who's already in the Group returns a 400. The whole request is in a single transaction, so if any action fails, whether from validation or the database write, none of the changes are applied and you can fix the offending action and resend the entire batch.

Note You can't have more Grantees than the Subscription Plan has seats. If the Group is already full, raise the seat count first (below), then add the member. A Group subscribed only to non-per-seat Plans is capped at a single Grantee (the limit doesn't apply to an unsubscribed Group, which can hold several Grantees before checkout).

Adjust the seat count

When a team needs more seats than the Subscription currently pays for, raise the count before adding members. To change the seat count, update the quantity field on the Plan's per-seat Subscription Plan Line Item. For Stripe Subscriptions, the new quantity will be synced with its billing and invoiced based on the proration option selected.

import { Salable } from '@salable/sdk';
const salable = new Salable(process.env.SALABLE_SECRET_KEY);
 
await salable.api.subscriptionPlanLineItems.byId('spli_01HXACMESEATS').put({
    quantity: 15,
    proration: 'create_prorations' // only for Stripe Subscriptions
});

The proration behaviour (create_prorations, always_invoice, or none) controls how Stripe bills the mid-cycle change. It's required for a Stripe Subscription and rejected for a Salable Only one, where seats change with no billing to settle. See Subscriptions & Billing for what each value does.

Important The new quantity must sit within the per-seat Line Item's minimum and maximum, and it can't be lower than the number of Grantees currently in the Group. To drop below the current headcount, remove those Grantees first, then lower the seats.

  • Groups How Groups, Memberships, and seats fit together, including how seat counts limit Group size when a Group holds several Plans.
  • Subscriptions & Billing The proration behaviours in depth and how mid-cycle seat changes are billed.