Skip to main content
Seat-based pricing lets you sell products where one person buys seats and hands them out to their team. Each seat holder gets their own benefits: license keys, Discord roles, file downloads, or anything else you offer.

Before you build

  • Ruba organization with seat-based pricing enabled
  • Ruba SDK installed (npm install @getruba/sdk or pip install ruba-sdk), make sure it’s the latest version
  • Basic grasp of Ruba products and subscriptions

Build sequence

This guide covers both subscription and one-time purchase seat-based products. The flow is the same; the only difference is in scaling and billing.

Step 1: Create a seat-based product

1

Navigate to Products

Open the dashboard and create a new product.
2

Configure pricing

Under Pricing:
  • Product type: Subscription (recurring) or One-time (perpetual licenses)
  • Pricing type: Seat-based
  • Tiering model: Choose how seats are priced (see below)
Fixed price per seat (default): every seat costs the same flat rate. Enter a single price per seat.Graduated: seats are priced per tier range independently. Each tier’s seats are billed at that tier’s rate and the totals are summed. Example with 1–10 seats at $10 and 11+ at $8: buying 14 seats = 10 × $10 + 4 × $8 = $132.Volume discounts: the per-seat price is set by the total seats purchased, and that rate applies to all seats. Example with the same tiers: buying 14 seats = 14 × $8 = $112 (all seats at the 11+ rate).
3

Add benefits

Configure benefits that seat holders will receive (license keys, file downloads, Discord roles, etc.). Remember: benefits are granted on seat claim, not at purchase.

Step 2: Checkout

The checkout automatically prices things based on your tiers.

Step 3: Seat management

After purchase, the billing manager can assign and manage seats right from the Customer Portal, with no custom UI needed. The portal offers:
  • Assign seats to team members by email
  • Revoke seats to strip access and free up seats for reassignment
  • Resend invitations for pending seats
  • Adjust seat count on subscriptions (add or reduce)
Ruba automatically fires invitation emails to assigned team members with a secure claim link. The moment a member claims their seat, benefits are granted immediately.
Invitation emails go out automatically when seats are assigned. The claim flow is fully managed by Ruba: members click the link, claim their seat, and get immediate access to benefits.

API-driven seat assignment

If you want to manage seat assignment programmatically (e.g., auto-assigning seats when users sign up), use the Customer Seats API:
Use immediate_claim: true when you manage your own user authentication and want to bypass the email invitation flow. Benefits are granted immediately without the member needing to click a claim link.

Step 4: Handle benefit grants

Listen for benefit webhooks to sync access in your system. Remember: use grant.member to identify the recipient, not grant.customer_id (which is the buyer).
Always verify webhook signatures before processing events. The example below omits verification for brevity.

Step 5: Scale seats

Subscriptions: modify the seat count:
You cannot reduce seats below the number of currently assigned seats (both pending and claimed). Revoke seats first before reducing the count.
One-time purchases: buy a new order:

Operating rules

  • Use grant.member everywhere (not grant.customer_id) to identify who has access
  • Use seat metadata to store department, role, or cost center for your own tracking
  • Communicate clearly to billing managers about seat assignment: if using the default Ruba confirmation page, their seat is auto-claimed; if using a custom success URL, they’ll need to assign themselves a seat through the portal

Understanding the model

Before writing any code, there are three entities to grasp. They reshape how you think about every API call, webhook, and portal flow.

Customer, Member, and CustomerSeat

With standard Ruba products, one person buys and one person uses, they are the same person. With seat-based products, buying and using are separate concerns, modeled through three distinct entities:
  • A Customer is the billing entity, who pays. They own subscriptions, orders, and payment methods. On the first seat-based purchase, the customer is permanently upgraded to type: "team", which turns on members and team management.
  • A Member is a person under a customer, who uses. Each member has their own email, role (owner, billing_manager, or member), and receives benefit grants independently. The person who purchases the product is created as an owner member. Both owner and billing_manager roles can manage seats, update or cancel the subscription, and manage payment methods. The owner role may pick up additional management capabilities down the road.
  • A CustomerSeat is the link between a product and a member. It tracks assignment status (pending, claimed, revoked), holds the invitation token, and carries optional metadata.

Why this split matters

This three-entity model gives you flexibility that a plain “buyer = user” model can’t:
  • Members persist across products. The same member can hold seats from different subscriptions or orders under the same customer.
  • Roles control portal access. Owners and billing managers see full team management. Regular members see only their own benefits.
  • Benefits track to people, not purchases. Always use grant.member to identify who has access: grant.customer_id is always the billing entity, not the end user.

What this means for your integration

  • Benefit grants reference a member, not just a customer. Always use grant.member to identify who received the benefit.
  • Webhooks include a member object on seat and grant events. Use it instead of customer_id to identify the end user.
  • Benefits are not granted at purchase time. Seats must be assigned and claimed before benefits are granted. (Exception: when using the default Ruba confirmation page, the buyer’s seat is auto-claimed.)

Member sessions and portal

To give a member access to the customer portal, create a customer session with a member_id to scope the view:
  • Billing managers (owner/billing_manager role) see full team management: assigning seats, managing members, and viewing seat utilization.
  • Members see only their own benefits and account details.

Webhook events

On subscription cancellation, each seat is revoked individually. A subscription with 5 seats and 3 benefits produces 1 + 5 + 15 = 21 webhook events. Make sure your handlers are idempotent.

Subscriptions vs one-time purchases

Current boundaries

  • Seats must be assigned individually (use API for bulk)
  • Claim links expire after 24 hours
  • Maximum 1,000 seats per subscription
  • Metadata limited to 10 keys and 1KB per seat

Diagnose the integration

Continue the build