Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.spairehq.com/llms.txt

Use this file to discover all available pages before exploring further.

Seat-based pricing is for products sold to teams. One person (the billing manager) buys a number of seats and assigns them to individuals by email. Each seat holder gets their own access to the product’s benefits — the billing manager gets none. Works for both subscriptions (recurring billing per seat) and one-time purchases (perpetual seat access, no renewal).

How it works

  1. Billing manager checks out and selects the number of seats
  2. After payment, they assign seats via the customer portal or API
  3. Each assigned person receives an invitation email with a 24-hour claim link
  4. Claim link is single-use — once clicked, benefits are granted immediately
  5. Billing manager can revoke seats, resend expired invitations, and add more seats

Create a seat-based product

In Catalog → Products → New product:
  1. Set the billing cycle: Subscription (monthly/yearly) or One-time
  2. Under Pricing type, select Seat-based
  3. Set pricing tiers:
    • Min seats — the minimum a customer must purchase
    • Tiers — each tier has a max seat count and a per-seat price
Example tier setup:
SeatsPrice per seat
1–4$10/seat/month
5–9$9/seat/month
10+$8/seat/month
When a customer moves between tiers (e.g., from 4 seats to 5), the new per-seat rate applies to all seats, not just the additional ones.
Benefits are only granted when a seat is claimed — not when the billing manager purchases. The billing manager has no direct access to product benefits.

Seat statuses

StatusMeaning
pendingAssigned, invitation sent, awaiting claim
claimedTeam member accepted — benefits active
revokedAccess removed, seat available for reassignment

Assign a seat

Via the customer portal (billing manager) or the API:
await spaire.customerSeats.assign({
  subscriptionId: '<subscription_id>',
  email: 'teammate@company.com',
  metadata: {
    department: 'Engineering',
    role: 'Developer',
  },
})
Optional fields: externalCustomerId, customerId, metadata (up to 10 keys, 1 KB total). Claim links expire after 24 hours. Resend from the portal or API if they expire.

Scale seats (subscriptions)

Add seats:
  1. Update the subscription seat count
  2. Proration is calculated immediately for the current billing period
  3. New seats can be assigned right away
Remove seats:
  1. Revoke enough claimed seats to reach the target count
  2. Update the subscription to the lower seat count
  3. Reduction takes effect at the next renewal
You can’t reduce the seat count below the number of currently claimed seats. Revoke seats first.

One-time purchases

Each order is an independent seat pool. To add more seats, purchase a new order — seats from multiple orders can coexist. All seats are perpetual and never expire. Seats can be revoked (access removed) but not refunded.

Webhooks

EventWhen
subscription.createdSeat-based subscription purchased
subscription.updatedSeat count changed
order.createdSeat-based one-time purchase completed
benefit_grant.createdSeat claimed — benefits granted
benefit_grant.revokedSeat revoked — benefits removed
benefit_grant.created fires per seat claim, not at purchase time. Use this event to provision access in your application.

Limits

  • Maximum 1,000 seats per subscription
  • Seat metadata: up to 10 keys, 1 KB total
  • Claim links expire after 24 hours
  • Seats must be assigned individually (use the API for bulk assignment)

What’s next

Usage-Based Billing

Combine seat-based pricing with usage meters for hybrid billing.

Webhooks

Listen to benefit grant events to provision access in your app.