> ## 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.

# Dynamic Pricing Checkout with Pay What You Want

> Create checkout sessions with variable pricing using Pay What You Want. Set a minimum price, pass dynamic amounts via API, or let customers choose their price.

Pay What You Want (PWYW) lets you offer variable pricing for a single product without creating multiple product entries. You set a minimum price in the dashboard, then pass dynamic amounts when creating checkout sessions, or let customers choose their price.

This approach works for:

* Variable pricing without managing multiple products
* Customer-driven pricing where buyers choose their amount
* Programmatic price control where you set the amount via API
* Flexible pricing models for digital products, donations, or experimental launches

<Warning>
  Pay What You Want is only available for one-time payment products. It cannot be used with subscriptions. The product's base currency must be USD, GBP, or EUR.
</Warning>

## Prerequisites

* A one-time payment product with Pay What You Want enabled in the dashboard
* The product ID (e.g., `pdt_123abc456def`)
* An API key from **Developer → API Keys**

## Enable Pay What You Want on a Product

In the Dodo Payments dashboard:

<Steps>
  <Step title="Go to Products">
    Navigate to **Products** and select the one-time payment product you want to configure.
  </Step>

  <Step title="Enable Pay What You Want">
    In the **Pricing** section, toggle **Pay What You Want** on.
  </Step>

  <Step title="Set the minimum price">
    Enter the **Minimum Price** customers must pay. This is required.
  </Step>

  <Step title="Set a suggested price (optional)">
    Optionally set a **Suggested Price** to guide customers. There is no maximum price setting. To cap the amount you charge, enforce the cap in your own code before you create the session.
  </Step>

  <Step title="Save">
    Click **Update Product** and note your product ID for use in checkout sessions.
  </Step>
</Steps>

<Tip>
  You can find your product ID in the dashboard under **Products** → **View Details**, or by using the [List Products API](/api-reference/products/get-products).
</Tip>

## Create a Checkout Session with a Fixed Amount

When you pass an `amount` in the product cart, the checkout uses that exact amount as the unit price, as long as it's at or above the product's minimum price.

The `amount` field uses the smallest currency unit: cents for USD, pence for GBP, cents for EUR. For example, `1500` = \$15.00 or €15.00.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import DodoPayments from 'dodopayments';

  const client = new DodoPayments({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  });

  const session = await client.checkoutSessions.create({
    product_cart: [
      {
        product_id: 'pdt_123abc456def',
        quantity: 1,
        amount: 1500, // $15.00 in cents
      }
    ],
    return_url: 'https://yoursite.com/success',
    metadata: {
      pricing_tier: 'custom'
    }
  });

  console.log('Checkout URL:', session.checkout_url);
  ```

  ```python Python theme={null}
  import os
  from dodopayments import DodoPayments

  client = DodoPayments(
      bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"),
  )

  session = client.checkout_sessions.create(
      product_cart=[
          {
              "product_id": "pdt_123abc456def",
              "quantity": 1,
              "amount": 1500,  # $15.00 in cents
          }
      ],
      return_url="https://yoursite.com/success",
      metadata={
          "pricing_tier": "custom"
      }
  )

  print(f"Checkout URL: {session.checkout_url}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://test.dodopayments.com/checkouts \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "product_cart": [
        {
          "product_id": "pdt_123abc456def",
          "quantity": 1,
          "amount": 1500
        }
      ],
      "return_url": "https://yoursite.com/success"
    }'
  ```
</CodeGroup>

<Info>
  The `amount` field is ignored for products without Pay What You Want enabled. It only applies to one-time payments.
</Info>

## Let Customers Choose Their Price

Omit the `amount` field to show a price input on checkout. Customers can enter any amount at or above your product's minimum price.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const session = await client.checkoutSessions.create({
    product_cart: [
      {
        product_id: 'pdt_123abc456def',
        quantity: 1,
        // No amount field — customer chooses
      }
    ],
    return_url: 'https://yoursite.com/success',
  });
  ```

  ```python Python theme={null}
  session = client.checkout_sessions.create(
      product_cart=[
          {
              "product_id": "pdt_123abc456def",
              "quantity": 1,
              # No amount field — customer chooses
          }
      ],
      return_url="https://yoursite.com/success",
  )
  ```

  ```bash cURL theme={null}
  curl -X POST https://test.dodopayments.com/checkouts \
    -H "Authorization: Bearer $DODO_PAYMENTS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "product_cart": [
        {
          "product_id": "pdt_123abc456def",
          "quantity": 1
        }
      ],
      "return_url": "https://yoursite.com/success"
    }'
  ```
</CodeGroup>

## Use Payment Links with Dynamic Amounts

Static payment links for Pay What You Want products accept a `paymentAmount` query parameter that fixes the amount charged. Unlike the Checkout Sessions API, this parameter uses major currency units (e.g., `12.5` for \$12.50).

```text theme={null}
https://checkout.dodopayments.com/buy/pdt_123abc456def?paymentAmount=15.00
```

<Warning>
  `paymentAmount` uses major currency units (`15.00` is \$15.00). The Checkout Sessions API field `product_cart[].amount` uses the smallest currency unit (`1500` is \$15.00). See the [Integration Guide](/developer-resources/integration-guide#static-payment-links) for more details.
</Warning>

## Common Patterns

### Tiered Pricing by Customer Segment

Charge different amounts to different customer types using the same product:

```typescript theme={null}
async function createCheckoutForSegment(segment: string) {
  const amounts: Record<string, number> = {
    student: 1000,    // $10.00
    regular: 2500,    // $25.00
    premium: 5000,    // $50.00
  };

  return client.checkoutSessions.create({
    product_cart: [
      {
        product_id: 'pdt_123abc456def',
        quantity: 1,
        amount: amounts[segment],
      }
    ],
    return_url: 'https://yoursite.com/success',
    metadata: { segment },
  });
}
```

### Quantity-Based Pricing

Adjust the unit price based on quantity purchased. The `amount` is a per-unit price, and the total is `amount` × `quantity`:

```typescript theme={null}
async function createCheckoutWithQuantity(quantity: number) {
  const basePrice = 2000; // $20.00 per unit
  let discount = 0;

  if (quantity >= 5) {
    discount = 0.20; // 20% off
  } else if (quantity >= 2) {
    discount = 0.10; // 10% off
  }

  const unitAmount = Math.round(basePrice * (1 - discount));

  return client.checkoutSessions.create({
    product_cart: [
      {
        product_id: 'pdt_123abc456def',
        quantity,
        amount: unitAmount, // Charged per unit
      }
    ],
    return_url: 'https://yoursite.com/success',
  });
}
```

### Promotional Pricing

Apply time-limited pricing:

```typescript theme={null}
async function createCheckoutWithPromo() {
  const isPromoActive = checkIfPromotionActive(); // Your logic
  const regularPrice = 3000; // $30.00
  const promoPrice = 2000;   // $20.00

  return client.checkoutSessions.create({
    product_cart: [
      {
        product_id: 'pdt_123abc456def',
        quantity: 1,
        amount: isPromoActive ? promoPrice : regularPrice,
      }
    ],
    return_url: 'https://yoursite.com/success',
    metadata: {
      pricing_type: isPromoActive ? 'promotional' : 'regular',
    },
  });
}
```

Use metadata to track why specific amounts were chosen (e.g., `pricing_tier`, `discount_code`, `user_segment`). This helps you analyze pricing patterns and customer behavior.

## Validate Amounts

Check that the amount is at or above your product's minimum price before you create a checkout session. `maxAmount` is your own business cap; Dodo Payments has no maximum price setting.

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function createValidatedCheckout(
    productId: string,
    amountInCents: number,
    minAmount: number,
    maxAmount: number | null
  ) {
    if (amountInCents < minAmount) {
      throw new Error(
        `Amount ${amountInCents} is below minimum ${minAmount}`
      );
    }

    if (maxAmount !== null && amountInCents > maxAmount) {
      throw new Error(
        `Amount ${amountInCents} exceeds maximum ${maxAmount}`
      );
    }

    return client.checkoutSessions.create({
      product_cart: [
        {
          product_id: productId,
          quantity: 1,
          amount: amountInCents,
        }
      ],
      return_url: 'https://yoursite.com/success',
    });
  }
  ```

  ```python Python theme={null}
  def create_validated_checkout(
      product_id: str,
      amount_in_cents: int,
      min_amount: int,
      max_amount: int | None
  ):
      if amount_in_cents < min_amount:
          raise ValueError(
              f"Amount {amount_in_cents} is below minimum {min_amount}"
          )

      if max_amount is not None and amount_in_cents > max_amount:
          raise ValueError(
              f"Amount {amount_in_cents} exceeds maximum {max_amount}"
          )

      return client.checkout_sessions.create(
          product_cart=[
              {
                  "product_id": product_id,
                  "quantity": 1,
                  "amount": amount_in_cents,
              }
          ],
          return_url="https://yoursite.com/success",
      )
  ```
</CodeGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Amount is being ignored">
    Verify that:

    * The product has Pay What You Want enabled in the dashboard
    * The product is a one-time payment product, not a subscription
    * The amount is in the correct format (smallest currency unit: cents for USD, pence for GBP, cents for EUR)
  </Accordion>

  <Accordion title="Amount is below the minimum price">
    The API rejects checkout sessions where the amount is below your product's minimum price. Validate amounts before creating sessions, or omit the `amount` field to let customers choose.
  </Accordion>

  <Accordion title="Customer can't enter their own price">
    If the price input field doesn't appear, ensure you've omitted the `amount` field from the product cart. When `amount` is provided, the checkout uses that exact amount.
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="Checkout Sessions API" icon="code" href="/api-reference/checkout-sessions/create">
    Complete API reference for checkout sessions.
  </Card>

  <Card title="Checkout Sessions Guide" icon="cart-shopping" href="/developer-resources/checkout-session">
    Explore advanced checkout session features and customization options.
  </Card>

  <Card title="Pay What You Want Feature" icon="dollar-sign" href="/features/pay-what-you-want">
    Learn more about the Pay What You Want pricing model.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.