Skip to main content
Seat-based billing charges customers based on the number of users on their account. Dodo Payments implements it using the add-on system: a base subscription product plus a per-seat add-on whose quantity represents the seat count.

Implementation Tutorial

Step-by-step guide with code examples.

Add-ons Documentation

Learn about the add-on system that powers seat-based billing.

Subscription Management

Manage seat-based subscriptions and plan changes.

Webhooks

Track seat changes with subscription webhooks.

What is Seat-Based Billing?

Seat-basierte Abrechnung berechnet Kunden abhängig von der Anzahl der Nutzer, die auf Ihr Produkt zugreifen. Statt einer Pauschalgebühr steigt der Preis mit der Teamgröße.

Common Use Cases

Benefits of Seat-Based Pricing

Für Ihr Unternehmen:
  • Der Umsatz steigt, wenn Ihre Kunden wachsen
  • Kunden können ihre Kosten planbar budgetieren
  • Klarer Upgrade-Pfad vom Einzelkunden über das Team bis zum Unternehmen
  • Höherer Customer Lifetime Value, wenn Teams wachsen
Für Ihre Kunden:
  • Sie zahlen nur für die Nutzer, die sie tatsächlich haben
  • Kosten lassen sich einfach verstehen und prognostizieren
  • Nutzer können nach Bedarf hinzugefügt oder entfernt werden
  • Faire Preise, die der Teamgröße entsprechen

How It Works

Dodo Payments implements seat-based billing using the Add-ons system. A seat-based subscription has two parts: The customer’s monthly total is:
Beispiel: 8 zusätzliche Seats bei einem Team Plan

Pricing Strategies

Choose the seat-based pricing strategy that fits your business:

Strategy 1: Base + Per-Seat Add-on

Include a set number of seats in the base plan, charge for additional seats.
Best for: Products where small teams can function with the base offering.

Strategy 2: Pure Per-Seat Pricing

Charge a flat rate per seat with no base fee.
Implementierung: Setzen Sie den Preis des Basistarifs auf $0 und verwenden Sie ausschließlich den Seat-Zusatz. Am besten geeignet für: Einfache, transparente Preise.

Strategy 3: Tiered Seat Pricing

Different base plans with different per-seat rates.
Implementation: Create separate products for each tier with different add-on prices. Best for: Encouraging upgrades to higher tiers; enterprise sales.

Strategy 4: Seat Bundles

Sell seats in packs rather than individually.
Implementation: Create multiple add-ons for different pack sizes. Best for: Simplifying purchasing decisions; encouraging larger commitments.

Setting Up Seat-Based Billing

Step 1: Plan Your Pricing

Before implementation, define your pricing structure:
1

Define Base Plan

Legen Sie fest, was im Basisabonnement enthalten ist:
  • Basisp reis (kann bei reiner Seat-Abrechnung $0 betragen)
  • Anzahl der enthaltenen Seats
  • In dieser Stufe verfügbare Funktionen
2

Set Seat Pricing

Determine the per-seat add-on cost:
  • Price per additional seat
  • Any volume discounts (via multiple add-ons)
  • Maximum seats allowed (if applicable)
3

Consider Billing Frequency

Align seat pricing with your billing cycle:
  • Monthly subscriptions → monthly seat charges
  • Annual subscriptions → annual seat charges (often discounted)

Step 2: Create the Seat Add-on

In your Dodo Payments dashboard:
  1. Navigate to Products → Add-Ons
  2. Click Create Add-On
  3. Configure the add-on:
Verwenden Sie beschreibende Namen für Zusätze, die auf Rechnungen verständlich sind. “Additional Team Seat” ist für Kunden, die ihre Rechnungen prüfen, klarer als “Seat Add-on”.

Step 3: Create the Base Subscription

Create your subscription product:
  1. Navigate to Products → Create Product
  2. Select Subscription
  3. Configure pricing and details
  4. In the Add-Ons section, attach your seat add-on

Step 4: Attach Add-on to Product

Link the seat add-on to your subscription:
  1. Edit your subscription product
  2. Scroll to Add-Ons section
  3. Click Add Add-Ons
  4. Select your seat add-on
  5. Save changes
Your subscription product now supports seat-based pricing. Customers can purchase any quantity of additional seats during checkout.

Managing Seats

Adding Seats to New Subscriptions

When creating a checkout session, specify the seat quantity:

Changing Seat Count on Existing Subscriptions

Use the Change Plan API to adjust seats. The addons array sets the new total seat count (not the delta).

Removing Seats

To reduce seat count, specify the lower quantity:

Removing All Additional Seats

Pass an empty addons array to remove all add-ons:

Proration for Seat Changes

When a seat change is applied mid-cycle, Dodo Payments calculates the immediate charge in three steps:
The credit amount depends on the proration mode you choose. The charge is always a full cycle.
Die Gebühr gilt immer für einen vollständigen Abrechnungszyklus. Nur das Guthaben variiert je nach Modus. Deshalb entspricht der berechnete Betrag nur selten “neue Seats × Preis × verbleibende Tage”.Bei prorated_immediately sinkt das Guthaben im Verlauf des Zyklus, sodass dieselbe Seat-Änderung umso mehr kostet, je später sie vorgenommen wird. Bei difference_immediately und full_immediately hängt das Guthaben nicht vom Zeitpunkt ab, daher kosten diese beiden Modi an jedem Tag des Zyklus gleich viel.

How Each Mode Credits

Bei difference_immediately zahlt der Kunde nur die Differenz zwischen dem Preis des alten und des neuen Tarifs. Daher stammt der Name, und deshalb ist der Betrag unabhängig davon gleich, wann im Zyklus die Änderung vorgenommen wird. If the credit is larger than the new cycle charge, the difference is held as subscription-scoped credit and applied automatically to future renewals.
prorated_immediately, difference_immediately und full_immediately setzen den Abrechnungszyklus auf das Änderungsdatum zurück. Die nächste Verlängerung wird auf den Tag verankert, an dem die Seat-Änderung angewendet wird. Nur do_not_bill behält das ursprüngliche Verlängerungsdatum bei (die neue Seat-Anzahl wird bei der nächsten Verlängerung vollständig berechnet, ohne Gebühr zum Zeitpunkt der Änderung).
do_not_bill applies the seat change immediately, not at renewal. The new seat count takes effect as soon as the call succeeds, but nothing is charged until the next renewal.Beim Hinzufügen von Seats kann der Kunde sie für den Rest des aktuellen Zyklus kostenlos nutzen. Wenn am ersten Tag eines 30-tägigen Zyklus 5 Seats zu je $10 hinzugefügt werden, erhält der Kunde 5 Seats für 29 Tage kostenlos; der höhere Betrag wird erstmals am ursprünglichen Verlängerungsdatum berechnet.Beim Entfernen von Seats gilt das Gegenteil: Die Seats werden sofort entzogen, und für den bereits bezahlten Teil des Zyklus wird kein Guthaben gewährt.Use do_not_bill when that is what you intend, such as a courtesy upgrade or a sales-agreed trial of extra seats.

Worked Example: Adding 5 Seats

One scenario run through all four modes, so the numbers are directly comparable.
In allen drei sofort wirksamen Modi erhält der Kunde im Austausch für die heutige Zahlung einen vollständigen neuen Monat für $130.

Why Timing Matters for prorated_immediately

The same change costs more the later in the cycle it is made, because less of the current cycle is left to credit back.
The customer receives a full new month in every row. Only the split between “already paid for” and “paying now” changes. Damit eine Seat-Änderung unabhängig vom Zeitpunkt immer gleich viel kostet, verwenden Sie difference_immediately.

Worked Example: The “Surprising Charge”

This is the case that most often surprises merchants. Adding a small seat add-on late in the cycle can produce a charge much larger than the add-on’s price.
Das Hinzufügen eines Seats für $10/Monat kostet mit prorated_immediately $55.00. Dem Kunden wird ein vollständiger neuer Monat für $60 berechnet und das im alten Monat verbleibende Guthaben von $5 gutgeschrieben; außerdem wird das Verlängerungsdatum zurückgesetzt. Damit kleine untermonatige Erweiterungen genau den Seat-Preis und nichts weiter kosten, verwenden Sie difference_immediately.

Worked Example: Removing Seats (Downgrade)

When the new plan costs less than the credit, the excess is held as subscription credit and applied automatically to future renewals of this subscription. It is not added to the Customer Wallet and is not a credit entitlement.
Das Guthaben umfasst das gesamte Abonnement, den Basistarif und alle Zusätze, nicht nur die Seats, die entfernt werden.

Reading the Preview Response

previewChangePlan returns the exact line items that will be billed. Each line item has a proration_factor:
Das bedeutet: $50 Basistarif und 3 × $10 Zusatz werden zu 50 % gutgeschrieben, ein vollständiger Basistarif von $50 wird berechnet und 8 × $10 Zusatz werden berechnet. Guthaben = $40, Gebühr = $130, Netto = $90.
Proration is calculated to the second based on the exact time of the change, not rounded to the nearest day. The worked examples above use round day-boundary numbers for clarity.
Choosing a proration mode for seat changes
  • difference_immediately — Der Kunde zahlt die Preisdifferenz, unabhängig davon, wann die Änderung vorgenommen wird. Am planbarsten für Teams, die ihre Seat-Anzahl häufig anpassen, und am einfachsten in Ihrer Benutzeroberfläche zu erklären.
  • prorated_immediately — Dem Kunden wird nur die verbleibende Zeit des aktuellen Zyklus gutgeschrieben. Je später im Zyklus die Änderung vorgenommen wird, desto höher sind die Kosten.
  • full_immediately — Der Kunde zahlt für einen vollständigen neuen Zyklus, ohne Guthaben für ungenutzte Zeit.
  • do_not_bill — Die Seat-Änderung wird sofort wirksam, aber jetzt wird nichts berechnet. Hinzugefügte Seats sind bis zur nächsten Verlängerung kostenlos; entfernte Seats werden ohne Guthaben entzogen. Das Verlängerungsdatum bleibt erhalten, und ab dieser Verlängerung wird die neue Seat-Anzahl vollständig berechnet. Der einzige Modus, der den Abrechnungszyklus nicht zurücksetzt.
Seats granted through do_not_bill are not credited on a later plan change, because they were never billed. If you add 5 seats with do_not_bill and then change to 3 seats, the customer is billed for 3 seats in full with no credit for the 5 they were holding.
Always call previewChangePlan and show the returned amount before confirming. See the Proration Guide for detailed comparisons.

Preview Before Changing

Always preview proration before making changes:

Tracking Seats with Webhooks

Monitor seat changes by listening to subscription webhooks:

Relevant Events

Webhook Handler Example

The addons array in the webhook payload contains the current addon quantities. Sum them to get the total seat count. If your base plan includes seats (e.g. 5 included), add that to the addon total in your application logic.

Enforcing Seat Limits

Your application must enforce seat limits. Dodo Payments tracks billing, but you control access.
Strictly prevent adding users beyond the seat count.

Advanced Patterns

Different Seat Types

Offer different seat types with different pricing:
Implementation: Create separate add-ons for each seat type.

Annual Seat Discounts

Offer discounted annual seat pricing:
Implementation: Create separate products for monthly and annual plans with different add-on prices.

Minimum Seat Requirements

Require a minimum number of seats for certain plans:

Best Practices

Pricing Best Practices

  • Clear Communication: Show per-seat pricing prominently on your pricing page
  • Included Seats: Consider including a few seats in the base price to reduce friction
  • Volume Discounts: Offer lower per-seat rates for larger teams to win enterprise deals
  • Annual Incentives: Discount annual plans to improve cash flow and retention

Technical Best Practices

  • Cache Seat Counts: Cache subscription seat counts locally to avoid API calls on every request
  • Sync Regularly: Periodically sync your local seat count with Dodo Payments via API
  • Handle Failures: If a seat change fails, show clear error messages and retry options
  • Audit Trail: Log all seat changes for billing disputes and compliance

User Experience Best Practices

  • Feedback in Echtzeit: Zeigen Sie die Kostenauswirkungen sofort an, wenn Seats angepasst werden
  • Bestätigungsschritte: Fordern Sie vor Änderungen der Abrechnung eine Bestätigung an
  • Transparenz bei anteiligen Abrechnungen: Erklären Sie anteilige Gebühren klar, bevor Sie sie anwenden
  • Einfache Downgrades: Erschweren Sie die Reduzierung von Seats nicht (das schafft Vertrauen)

Troubleshooting

Symptom: Your app shows a different seat count than the subscription.Causes:
  • Webhook not received or processed
  • Race condition during seat change
  • Cached data not updated
Solutions:
  1. Implement webhook handlers for subscription.plan_changed
  2. Add a “Sync with billing” button that fetches current subscription
  3. Set cache TTL to ensure regular refresh
Symptom: Customer confused by mid-cycle charge amount.Cause: Using prorated_immediately late in the billing cycle (see The Surprising Charge example above).Lösungen:
  1. Verwenden Sie vor Änderungen immer previewChangePlan
  2. Zeigen Sie eine klare Aufschlüsselung: “Das Hinzufügen von X Seats kostet heute $Y”
  3. Wechseln Sie zu difference_immediately, wenn die Gebühr immer der Preisdifferenz entsprechen soll
Symptom: Seat add-on not available during checkout.Causes:
  • Add-on not attached to product
  • Add-on archived or deleted
  • Currency mismatch between product and add-on
Solutions:
  1. Verify add-on is attached in product settings
  2. Check add-on status in Add-Ons dashboard
  3. Ensure currencies match exactly
Symptom: Customer wants to reduce seats but has users assigned.Solutions:
  1. Show which users must be removed before reducing seats
  2. Implement a workflow: Remove users → Reduce seats
  3. Consider a grace period before enforcing seat reduction

Seat-Based Pricing Tutorial

Complete implementation guide with code.

Add-ons

Understand the add-on system in depth.

Plan Changes & Proration

Handle subscription modifications.

Subscription Webhooks

Track subscription events.
Zuletzt geändert am 26. September 2026