> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sitzplatzbasierte Preisgestaltung mit Add-Ons und Zahlungslinks

> Erfahren Sie, wie Sie Add-Ons für sitzplatzbasierte Preisgestaltung erstellen und Zahlungslinks mit benutzerdefinierten Add-On-Mengen mit Dodo Payments generieren.

In diesem Tutorial lernen Sie, wie Sie sitzplatzbasierte Preisgestaltung mit Dodo Payments-Add-Ons implementieren. Wir erstellen ein Abonnementprodukt mit Add-Ons für zusätzliche Sitze und zeigen Ihnen, wie Sie Zahlungslinks mit benutzerdefinierten Add-On-Mengen generieren.

<Note>
  Dieses Tutorial bietet Beispielimplementierungscode für eine Node.js/Express-Anwendung. Du kannst diesen Code für dein spezifisches Framework (Next.js, React, Vue usw.) anpassen und die Benutzeroberfläche entsprechend den Anforderungen deiner Anwendung gestalten.
</Note>

Am Ende dieses Tutorials wissen Sie, wie Sie:

* Abonnementprodukte mit sitzplatzbasierter Preisgestaltung erstellen
* Add-Ons für zusätzliche Sitze einrichten
* Zahlungslinks mit benutzerdefinierten Add-On-Mengen generieren
* Checkout-Sitzungen mit dynamischen Sitzplatzanzahlen verwalten

## Was wir erstellen

Lassen Sie uns ein Modell für sitzplatzbasierte Preisgestaltung erstellen:

* **Basisplan**: 49 \$/Monat für bis zu 5 Teammitglieder
* **Sitz-Add-On**: 2 \$/Monat pro zusätzlichem Sitz
* **Zahlungslinks**: Dynamischer Checkout mit benutzerdefinierten Sitzplatzmengen

<Info>
  Bevor wir beginnen, stelle sicher, dass du:

  * Ein Dodo Payments-Konto hast
  * Grundkenntnisse in TypeScript/Node.js besitzt
</Info>

## Schritt 1: Erstellen Sie Ihr Sitz-Add-On

Jetzt müssen wir ein Add-On erstellen, das zusätzliche Sitze darstellt. Dieses Add-On wird an unser Basisabonnement angehängt und ermöglicht es den Kunden, zusätzliche Sitze zu kaufen.

<Frame>
  <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-addons-creation.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=d2c17b4a9f2f9a1b19f537f0507656a4" alt="Erstellung eines Basis-Abonnementprodukts" style={{ maxHeight: '500px', width: 'auto' }} width="2348" height="1606" data-path="images/cookbooks/seat-based/seat-based-addons-creation.png" />
</Frame>

<Tip>
  **What we're building**: Ein Add-on, das \$2/Monat pro Sitz kostet und zu jedem Basis-Abonnement hinzugefügt werden kann.
</Tip>

<Steps>
  <Step title="Navigate to Add-Ons">
    1. Bleibe in deinem Dodo Payments-Dashboard im Bereich **Products**
    2. Klicke auf die Registerkarte **Add-Ons**
    3. Klicke auf **Create Add-On**

    Dies öffnet das Formular zur Erstellung eines Add-ons.
  </Step>

  <Step title="Enter add-on details">
    Fülle diese Werte für unser Sitz-Add-on aus:

    **Add-On Name**: `Additional Team Seat`

    **Description**: `Add extra team members to your workspace with full access to all features`

    **Price**: Enter → `2.00`

    **Währung**: Muss mit der Währung Ihres Basisabonnements übereinstimmen

    **Steuerkategorie**: Wählen Sie die geeignete Kategorie für Ihr Produkt aus.
  </Step>

  <Step title="Save your add-on">
    1. Überprüfe alle deine Einstellungen:
       * Name: Additional Team Seat
       * Price: \$2.00/month
    2. Klicke auf **Create Add-On**

    <Check>
      **Add-on erstellt!** Dein Sitz-Add-on steht jetzt zur Verfügung, um an Abonnements angehängt zu werden.
    </Check>
  </Step>
</Steps>

## Schritt 2: Erstellen Sie Ihr Basisabonnementprodukt

Wir beginnen mit der Erstellung eines Basisabonnementprodukts, das 5 Teammitglieder umfasst. Dies wird die Grundlage unseres Modells für sitzplatzbasierte Preisgestaltung sein.

<Frame>
  <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-subscription.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=f17e96f3d106b88b6dc32a00be535620" alt="Erstellung eines Basis-Abonnementprodukts" style={{ maxHeight: '500px', width: 'auto' }} width="2118" height="1580" data-path="images/cookbooks/seat-based/seat-based-subscription.png" />
</Frame>

<Steps>
  <Step title="Navigate to Products">
    1. Melde dich in deinem Dodo Payments-Dashboard an
    2. Klicke in der linken Seitenleiste auf **Products**
    3. Klicke auf die Schaltfläche **Create Product**
    4. Wähle **Subscription** als Produkttyp aus

    Du solltest ein Formular sehen, in dem wir unser Basis-Abonnement konfigurieren.
  </Step>

  <Step title="Fill in the subscription details">
    Jetzt geben wir die spezifischen Details für unseren Basisplan ein:

    **Product Name**: `Motion`

    **Description**: `Where your team's documentation lives.`

    **Recurring Price**: Enter → `49.00`

    **Billing Cycle**: Select → `Monthly`

    **Currency**: Wähle deine bevorzugte Währung (z. B. `USD`)
  </Step>
</Steps>

## Schritt 3: Verbinden Sie das Add-On mit dem Abonnement

Jetzt müssen wir unser Sitz-Add-On mit dem Basisabonnement verknüpfen, damit die Kunden während des Checkouts zusätzliche Sitze kaufen können.

<Steps>
  <Step title="Attach the seat add-on">
    <Frame>
      <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-addons.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=ea4ce0d437201c92590eea6c31a14e80" alt="Anfügen von Add-ons an Abonnement" style={{ maxHeight: '500px', width: 'auto' }} width="2338" height="1196" data-path="images/cookbooks/seat-based/seat-based-addons.png" />
    </Frame>

    1. Scrollen Sie zum Abschnitt **Add-Ons**
    2. Klicken Sie auf **Add-Ons hinzufügen**
    3. Wählen Sie aus dem Dropdown-Menü Ihr Sitz-Add-On aus
    4. Bestätigen Sie, dass es in Ihrer Abonnementkonfiguration angezeigt wird
  </Step>

  <Step title="Save subscription changes">
    1. Überprüfe deine vollständige Abonnementeinrichtung:
       * Basisplan: \$49/Monat für 5 Sitze
       * Add-on: \$2/Monat pro zusätzlichem Sitz
       * Kostenloser Testzeitraum: 14 Tage
    2. Klicke auf **Save Changes**

    <Check>
      **Sitzbasierte Preisgestaltung konfiguriert!** Kunden können nun deinen Basisplan erwerben und bei Bedarf zusätzliche Sitze hinzufügen.
    </Check>
  </Step>
</Steps>

## Schritt 4: Generieren Sie Zahlungslinks mit benutzerdefinierten Add-On-Mengen

Jetzt erstellen wir eine Express.js-Anwendung, die Zahlungslinks mit benutzerdefinierten Add-On-Mengen generiert. Hier kommt die wahre Kraft der sitzplatzbasierten Preisgestaltung ins Spiel - Sie können dynamisch Checkout-Sitzungen mit beliebig vielen zusätzlichen Sitzen erstellen.

<Steps>
  <Step title="Set up your project">
    Erstelle ein neues Node.js-Projekt und installiere die benötigten Abhängigkeiten:

    ```bash theme={null}
    mkdir seat-based-pricing
    cd seat-based-pricing
    npm init -y
    npm install dodopayments express dotenv
    npm install -D @types/node @types/express typescript ts-node
    ```

    Erstelle eine `tsconfig.json`-Datei:

    ```json theme={null}
    {
      "compilerOptions": {
        "target": "ES2020",
        "module": "commonjs",
        "outDir": "./dist",
        "rootDir": "./src",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
      }
    }
    ```
  </Step>

  <Step title="Create your environment file">
    Erstelle eine `.env`-Datei mit deinem Dodo Payments-API-Schlüssel:

    ```bash theme={null}
    DODO_PAYMENTS_API_KEY=your_actual_dodo_api_key_here
    ```

    <Warning>
      Veröffentliche deinen API-Schlüssel niemals im Versionskontrollsystem. Füge `.env` zu deiner `.gitignore`-Datei hinzu.
    </Warning>
  </Step>

  <Step title="Implement the checkout session creation">
    Erstelle eine `src/server.ts`-Datei mit folgendem Code:

    <CodeGroup>
      ```typescript server.ts expandable theme={null}
      // Add this new endpoint for dynamic seat quantities
      import 'dotenv/config';
      import DodoPayments from 'dodopayments';
      import express, { Request, Response } from 'express';

      const app = express();

      // Initialize the Dodo Payments client
      const client = new DodoPayments({
        bearerToken: process.env.DODO_PAYMENTS_API_KEY,
        environment: 'test_mode'
      });

      async function createCheckoutSession(seatCount: number) {
        try {
          const session = await client.checkoutSessions.create({
            // Products to sell - use IDs from your Dodo Payments dashboard
            product_cart: [
              {
                product_id: 'pdt_7Rl9OWT2Mz4wwUTKz74iZ', // Replace with your actual product ID
                quantity: 1,
                addons: [
                  {
                    addon_id: 'adn_eKQbNakKrivDpaxmI8wKI', // Replace with your actual addon ID
                    quantity: seatCount
                  }
                ]
              }
            ],
            
            // Pre-fill customer information to reduce friction
            customer: {
              email: 'steve@example.com',
              name: 'Steve Irwin',
            },
            // Where to redirect after successful payment
            return_url: 'https://example.com/checkout/success',
          });

          // Redirect your customer to this URL to complete payment
          console.log('Checkout URL:', session.checkout_url);
          console.log('Session ID:', session.session_id);
          
          return session;
          
        } catch (error) {
          console.error('Failed to create checkout session:', error);
          throw error;
        }
      }

      // Example usage in an Express.js route
      app.post('/create-checkout/:seatCount', async (req: Request, res: Response) => {
        try {
          const seatCount = parseInt(req.params.seatCount);
          const session = await createCheckoutSession(seatCount);
          res.json({ checkout_url: session.checkout_url });
        } catch (error) {
          res.status(500).json({ error: 'Failed to create checkout session' });
        }
      });

      // Add this line after your other middleware
      app.use(express.static('public'));

      // Add this route to serve the demo page
      app.get('/', (req, res) => {
        res.sendFile(__dirname + '/../public/index.html');
      });

      app.listen(3000, () => {
        console.log('Server is running on port 3000');
      });
      ```
    </CodeGroup>
  </Step>

  <Step title="Add a simple web interface">
    Erstelle eine `public/index.html`-Datei für einfache Tests:

    <CodeGroup>
      ```html index.html expandable theme={null}
      <!DOCTYPE html>
      <html>
      <head>
          <title>Seat-Based Pricing Demo</title>
          <style>
              body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
              .form-group { margin: 20px 0; }
              label { display: block; margin-bottom: 5px; font-weight: bold; }
              input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
              button { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
              button:hover { background: #0056b3; }
              .result { margin-top: 20px; padding: 15px; background: #f8f9fa; border-radius: 4px; }
          </style>
      </head>
      <body>
          <h1>Seat-Based Pricing Demo</h1>
          <p>Generate checkout links with custom seat quantities:</p>
          
          <div class="form-group">
              <label for="seatCount">Number of Additional Seats:</label>
              <input type="number" id="seatCount" value="3" min="0" max="50">
          </div>
          
          <button onclick="createCheckout()">Generate Checkout Link</button>
          
          <div id="result" class="result" style="display: none;">
              <h3>Checkout Link Generated!</h3>
              <p><strong>Seat Count:</strong> <span id="seatCountDisplay"></span></p>
              <p><strong>Total Cost:</strong> $<span id="totalCost"></span>/month</p>
              <p><strong>Checkout URL:</strong></p>
              <a id="checkoutUrl" href="#" target="_blank">Click here to checkout</a>
          </div>

          <script>
              async function createCheckout() {
                  const seatCount = document.getElementById('seatCount').value;
                  
                  try {
                      const response = await fetch(`/create-checkout/${seatCount}`, {
                          method: 'POST'
                      });
                      
                      const data = await response.json();
                      
                      if (response.ok) {
                          document.getElementById('seatCountDisplay').textContent = seatCount;
                          document.getElementById('totalCost').textContent = data.total_cost;
                          document.getElementById('checkoutUrl').href = data.checkout_url;
                          document.getElementById('result').style.display = 'block';
                      } else {
                          alert('Error: ' + data.error);
                      }
                  } catch (error) {
                      alert('Error creating checkout session');
                  }
              }
          </script>
      </body>
      </html>
      ```
    </CodeGroup>

    <Check>
      **Weboberfläche erstellt!** Du hast jetzt eine einfache Benutzeroberfläche, um verschiedene Sitzanzahlen zu testen.
    </Check>
  </Step>

  <Step title="Serve static files">
    Füge dies zu deiner `src/server.ts` hinzu, um die HTML-Datei bereitzustellen:

    ```typescript theme={null}
    // Add this line after your other middleware
    app.use(express.static('public'));

    // Add this route to serve the demo page
    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/../public/index.html');
    });
    ```

    <Check>
      **Statische Dateien konfiguriert!** Besuche `http://localhost:3000`, um deine Demo-Oberfläche zu sehen.
    </Check>
  </Step>
</Steps>

## Schritt 5: Testen Sie Ihre Implementierung

Lassen Sie uns unsere Implementierung der sitzplatzbasierten Preisgestaltung testen, um sicherzustellen, dass alles korrekt funktioniert.

<Steps>
  <Step title="Start your server">
    1. Stelle sicher, dass du deine `.env`-Datei mit dem korrekten API-Schlüssel hast
    2. Aktualisiere die Produkt- und Add-On-IDs in deinem Code mit den tatsächlichen Werten aus deinem Dodo Payments-Dashboard
    3. Starte deinen Server:

    ```bash theme={null}
    npm run dev
    ```

    <Check>
      Dein Server sollte erfolgreich starten und "Server running on [http://localhost:3000](http://localhost:3000)" anzeigen
    </Check>
  </Step>

  <Step title="Test the web interface">
    <Frame>
      <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-billing-ui.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=37d166d8e76b0bfbb4959bc9a3eff1f8" alt="Erstellung eines Basis-Abonnementprodukts" style={{ maxHeight: '500px', width: 'auto' }} width="1806" height="1416" data-path="images/cookbooks/seat-based/seat-based-billing-ui.png" />
    </Frame>

    1. Öffne deinen Browser und gehe zu `http://localhost:3000`
    2. Du solltest die Demo-Oberfläche für sitzbasierte Preisgestaltung sehen
    3. Probiere verschiedene Sitzanzahlen aus (0, 3, 10 usw.)
    4. Klicke für jede Anzahl auf "Generate Checkout Link"
    5. Überprüfe, ob die Checkout-URLs korrekt generiert werden
  </Step>

  <Step title="Test a checkout session">
    1. Generiere einen Checkout-Link mit 3 zusätzlichen Sitzen
    2. Klicke auf die Checkout-URL, um den Dodo Payments-Checkout zu öffnen
    3. Überprüfe, ob der Checkout Folgendes anzeigt:
       * Basisplan: \$49/Monat
       * Zusätzliche Sitze: 3 × 2 Dollar = \$6/Monat
    4. Schließe den Testkauf ab

    <Check>
      Der Checkout sollte die korrekte Preisaufschlüsselung anzeigen und dir ermöglichen, den Kauf abzuschließen.
    </Check>
  </Step>

  <Step title="Listen for webhooks and update your DB">
    Damit deine Datenbank mit Änderungen an Abonnements und Sitzanzahlen synchron bleibt, musst du Webhook-Ereignisse von Dodo Payments abhören. Webhooks benachrichtigen dein Backend, wenn ein Kunde den Checkout abschließt, sein Abonnement aktualisiert oder die Sitzanzahl ändert.

    Befolgen Sie die offizielle Dodo Payments-Webhooks-Anleitung für Schritt-für-Schritt-Anweisungen zum Einrichten von Webhook-Endpunkten und zum Verarbeiten von Ereignissen:

    <Card title="Dodo Payments Webhooks Documentation" icon="bell" href="/developer-resources/webhooks">
      Erfahre, wie du Webhook-Ereignisse sicher empfängst und verarbeitest, um Abonnements und Sitzverwaltung zu steuern.
    </Card>
  </Step>
</Steps>

## Fehlersuche

Häufige Probleme und deren Lösungen:

<AccordionGroup>
  <Accordion title="Checkout creation failing">
    **Mögliche Ursachen:**

    * Ungültige Produkt-ID oder Add-On-ID
    * Der API-Schlüssel hat nicht ausreichende Berechtigungen
    * Add-On ist nicht korrekt mit dem Abonnement verknüpft
    * Netzwerkverbindungsprobleme

    **Lösungen:**

    1. Überprüfe, ob Produkt- und Add-On-IDs in deinem Dodo Payments-Dashboard vorhanden sind
    2. Stelle sicher, dass das Add-On korrekt an das Abonnement angehängt ist
    3. Prüfe, ob der API-Schlüssel Berechtigungen zum Erstellen von Checkout-Sessions hat
    4. Teste die API-Konnektivität mit einer einfachen GET-Anfrage
  </Accordion>
</AccordionGroup>

## Herzlichen Glückwunsch! Sie haben die sitzplatzbasierte Preisgestaltung implementiert

Sie haben erfolgreich ein System für sitzplatzbasierte Preisgestaltung mit Dodo Payments erstellt! Hier ist, was Sie erreicht haben:

<CardGroup cols={2}>
  <Card title="Base Subscription">
    Ein Abonnementprodukt mit 5 inbegriffenen Sitzen zu \$49/Monat erstellt
  </Card>

  <Card title="Seat Add-ons">
    Add-ons für zusätzliche Sitze zu \$2/Monat pro Sitz konfiguriert
  </Card>

  <Card title="Checkout">
    Eine API erstellt, die Checkout-Sitzungen mit benutzerdefinierten Sitzanzahlen generiert
  </Card>

  <Card title="Web Interface">
    Eine einfache Weboberfläche zum Testen unterschiedlicher Sitzanzahlen erstellt
  </Card>
</CardGroup>

<Info>
  Dieses Beispiel demonstriert nur eine minimale Implementierung der sitzbasierten Preisgestaltung. Für den produktiven Einsatz solltest du eine robuste Fehlerbehandlung, Authentifizierung, Datenvalidierung, Sicherheitsmaßnahmen hinzufügen und die Logik an die Anforderungen deiner Anwendung anpassen.
</Info>
