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

# Next.js Adaptor

> Add Dodo Payments checkout, Customer Portal, and webhook route handlers to a Next.js App Router project with the @dodopayments/nextjs package.

The `@dodopayments/nextjs` package gives your Next.js App Router project three route handlers. `Checkout` returns checkout URLs, `CustomerPortal` sends a customer to the Customer Portal, and `Webhooks` verifies webhook events and routes them to your code. The package supports Next.js 14, 15, and 16.

<CardGroup cols={2}>
  <Card title="Checkout Handler" icon="cart-shopping" href="#checkout-route-handler">
    Create checkout URLs with static, dynamic, and checkout session flows.
  </Card>

  <Card title="Customer Portal" icon="user" href="#customer-portal-route-handler">
    Let customers manage their subscriptions and details.
  </Card>

  <Card title="Webhooks" icon="bell" href="#webhook-route-handler">
    Receive and process Dodo Payments webhook events.
  </Card>
</CardGroup>

## Installation

<Steps>
  <Step title="Install the Package">
    Run this command in your project root:

    ```bash theme={null}
    npm install @dodopayments/nextjs
    ```

    The package also requires Zod 3.25 or Zod 4 as a peer dependency.
  </Step>

  <Step title="Set Up Environment Variables">
    Create a `.env` file in your project root. Create the API key under **Developer → API Keys** and the webhook secret under **Developer → Webhooks** in the dashboard:

    ```env theme={null}
    DODO_PAYMENTS_API_KEY=your-api-key
    DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
    DODO_PAYMENTS_RETURN_URL=https://yourdomain.com/checkout/success
    DODO_PAYMENTS_ENVIRONMENT="test_mode" # or "live_mode"
    ```

    `DODO_PAYMENTS_RETURN_URL` is where customers land after checkout. If you don't pass an environment, the handlers use `live_mode`.

    <Warning>
      Never commit your `.env` file or secrets to version control.
    </Warning>
  </Step>
</Steps>

## Route Handler Examples

<Info>
  All examples assume you use the Next.js App Router.
</Info>

<Tabs>
  <Tab title="Checkout Handler">
    <Info>
      Use this handler to add Dodo Payments checkout to your app. A `GET` handler serves static checkout. A `POST` handler serves checkout sessions, or dynamic checkout when you set `type: "dynamic"`.
    </Info>

    <CodeGroup>
      ```typescript Next.js Route Handler expandable theme={null}
      // app/checkout/route.ts
      import { Checkout } from "@dodopayments/nextjs";

      export const GET = Checkout({
        bearerToken: process.env.DODO_PAYMENTS_API_KEY,
        returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
        environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
        type: "static", // optional, defaults to 'static'
      });

      export const POST = Checkout({
        bearerToken: process.env.DODO_PAYMENTS_API_KEY,
        returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
        environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
        type: "session", // for checkout sessions, or "dynamic" for dynamic checkout
      });
      ```
    </CodeGroup>

    <CodeGroup>
      ```bash Static Checkout cURL Example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/checkout?productId=pdt_123'
      ```
    </CodeGroup>

    <CodeGroup>
      ```bash Dynamic Checkout cURL Example expandable theme={null}
      curl --request POST \
      --url https://example.com/checkout \
      --header 'Content-Type: application/json' \
      --data '{
      "billing": {
        "city": "Austin",
        "country": "US",
        "state": "TX",
        "street": "123 Main St",
        "zipcode": "78701"
      },
      "customer": {
        "email": "customer@example.com",
        "name": "John Doe"
      },
      "metadata": {},
      "product_id": "pdt_123",
      "quantity": 1,
      "billing_currency": "USD",
      "discount_codes": ["IKHZ23M9GQ"],
      "return_url": "https://example.com",
      "trial_period_days": 10
      }'
      ```
    </CodeGroup>

    <CodeGroup>
      ```bash Checkout Session cURL Example expandable theme={null}
      curl --request POST \
      --url https://example.com/checkout \
      --header 'Content-Type: application/json' \
      --data '{
      "product_cart": [
        {
          "product_id": "pdt_123",
          "quantity": 1
        }
      ],
      "customer": {
        "email": "customer@example.com",
        "name": "John Doe"
      },
      "return_url": "https://example.com/success"
      }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Customer Portal Handler">
    <Info>
      Use this handler to send customers to the Dodo Payments Customer Portal, where they manage their subscriptions and details.
    </Info>

    <CodeGroup>
      ```typescript Next.js Route Handler expandable theme={null}
      // app/customer-portal/route.ts
      import { CustomerPortal } from "@dodopayments/nextjs";

      export const GET = CustomerPortal({
        bearerToken: process.env.DODO_PAYMENTS_API_KEY,
        environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
      });
      ```
    </CodeGroup>

    <CodeGroup>
      ```bash Customer Portal cURL Example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/customer-portal?customer_id=cus_123&send_email=true'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Webhook Handler">
    <Info>
      Use this handler to receive Dodo Payments webhook events in your Next.js app and verify their signatures.
    </Info>

    <CodeGroup>
      ```typescript Next.js Route Handler expandable theme={null}
      // app/api/webhook/dodo-payments/route.ts
      import { Webhooks } from "@dodopayments/nextjs";

      export const POST = Webhooks({
        webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY!,
        onPayload: async (payload) => {
          // handle the payload
        },
        // ... other event handlers for granular control
      });
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Checkout Route Handler

The checkout handler supports all three ways to take payments with Dodo Payments:

* **Static Payment Links:** Shareable URLs that collect payments without code.
* **Dynamic Payment Links:** Payment links you generate with custom details. They use deprecated endpoints.
* **Checkout Sessions:** Hosted checkout with a product cart, customer details, and customization options. This is the recommended flow.

<AccordionGroup>
  <Accordion title="Static Checkout (GET)">
    ### Supported Query Parameters

    <ParamField query="productId" type="string" required>
      Product identifier, for example `?productId=pdt_123`.
    </ParamField>

    <ParamField query="quantity" type="integer" default="1">
      Quantity of the product.
    </ParamField>

    <ParamField query="fullName" type="string">
      Customer's full name. Ignored if `firstName` or `lastName` is provided.
    </ParamField>

    <ParamField query="firstName" type="string">
      Customer's first name.
    </ParamField>

    <ParamField query="lastName" type="string">
      Customer's last name.
    </ParamField>

    <ParamField query="email" type="string">
      Customer's email address.
    </ParamField>

    <ParamField query="country" type="string">
      Customer's country, as an ISO 3166-1 alpha-2 code.
    </ParamField>

    <ParamField query="addressLine" type="string">
      Customer's address line.
    </ParamField>

    <ParamField query="city" type="string">
      Customer's city.
    </ParamField>

    <ParamField query="state" type="string">
      Customer's state or province.
    </ParamField>

    <ParamField query="zipCode" type="string">
      Customer's ZIP or postal code.
    </ParamField>

    <ParamField query="disableFullName" type="boolean">
      Set to `true` to disable the full name field.
    </ParamField>

    <ParamField query="disableFirstName" type="boolean">
      Set to `true` to disable the first name field.
    </ParamField>

    <ParamField query="disableLastName" type="boolean">
      Set to `true` to disable the last name field.
    </ParamField>

    <ParamField query="disableEmail" type="boolean">
      Set to `true` to disable the email field.
    </ParamField>

    <ParamField query="disableCountry" type="boolean">
      Set to `true` to disable the country field.
    </ParamField>

    <ParamField query="disableAddressLine" type="boolean">
      Set to `true` to disable the address line field.
    </ParamField>

    <ParamField query="disableCity" type="boolean">
      Set to `true` to disable the city field.
    </ParamField>

    <ParamField query="disableState" type="boolean">
      Set to `true` to disable the state field.
    </ParamField>

    <ParamField query="disableZipCode" type="boolean">
      Set to `true` to disable the ZIP code field.
    </ParamField>

    <ParamField query="paymentCurrency" type="string">
      Payment currency, for example `USD`.
    </ParamField>

    <ParamField query="showCurrencySelector" type="boolean" default="true">
      Show or hide the currency selector.
    </ParamField>

    <ParamField query="paymentAmount" type="number">
      Fixes the amount charged, in major currency units, for example `12.5` for \$12.50. Works with Pay What You Want products only, and is ignored if it's below the product's minimum price.
    </ParamField>

    <ParamField query="showDiscounts" type="boolean" default="true">
      Show or hide the discounts section.
    </ParamField>

    <ParamField query="metadata_*" type="string">
      Any query parameter that starts with `metadata_` is passed as metadata.
    </ParamField>

    The handler adds `returnUrl` from its config to the link as `redirect_url`.

    <Warning>
      If `productId` is missing, the handler returns a 400 response. Invalid query parameters and product IDs that don't exist also return 400.
    </Warning>

    ### Response Format

    Static checkout returns a JSON response with the checkout URL. In test mode, the URL uses `test.checkout.dodopayments.com`.

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Dynamic Checkout (POST)">
    * Send the parameters as a JSON body in a POST request.
    * Supports both one-time and recurring payments.
    * `billing` and `customer` are required.
    * For every supported body field, see:
      * [Request body for a One Time Payment Product](https://docs.dodopayments.com/api-reference/payments/post-payments)
      * [Request body for a Subscription Product](https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions)

    <Warning>
      Dynamic checkout proxies the deprecated `POST /payments` and `POST /subscriptions` endpoints. It keeps working for existing integrations, but new integrations should use checkout sessions.
    </Warning>

    ### Response Format

    Dynamic checkout returns a JSON response with the checkout URL:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Checkout Sessions (POST)">
    Checkout sessions create a hosted checkout for one-time purchases and subscriptions, with full control over customization. `product_cart` is the only required field. If the body has no `return_url`, the handler uses `returnUrl` from its config.

    For more details and every supported field, see the [Checkout Sessions Integration Guide](https://docs.dodopayments.com/developer-resources/checkout-session).

    A session created with `payment_method_id` returns no checkout URL, so the handler responds with 400. To charge a saved payment method, create the session with the SDK instead.

    ### Response Format

    Checkout sessions return a JSON response with the checkout URL:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/session/..."
    }
    ```
  </Accordion>
</AccordionGroup>

## Customer Portal Route Handler

The Customer Portal route handler creates a Customer Portal session for the customer you pass and redirects the browser to it.

<Warning>
  The handler doesn't check who is calling it. Anyone who requests it with a customer ID gets that customer's portal. Protect the route with your own authentication, and pass only the signed-in user's customer ID.
</Warning>

### Query Parameters

<ParamField query="customer_id" type="string" required>
  The customer ID for the portal session, for example `?customer_id=cus_123`.
</ParamField>

<ParamField query="send_email" type="boolean">
  If set to `true`, Dodo Payments also emails the portal link to the customer.
</ParamField>

The handler returns 400 if `customer_id` is missing, and 500 if the portal session can't be created.

## Webhook Route Handler

The webhook route handler verifies each request before it runs your code:

* **Method:** Only POST requests are supported. Other methods return 405.
* **Signature Verification:** Verifies the raw request body against the `webhook-id`, `webhook-timestamp`, and `webhook-signature` headers with `webhookKey`. Returns 401 if verification fails.
* **Payload Validation:** Parses the verified body as JSON and validates it with Zod. Returns 400 when a parsed payload doesn't match the webhook schema.
* **Error Handling:**
  * 401: Invalid signature
  * 400: Invalid payload
  * 500: Unexpected verification errors, malformed JSON, or errors thrown by your callbacks
* **Event Routing:** Calls `onPayload` for every event, then the handler for the event's type, and returns 200.

The adaptor doesn't catch errors thrown in your handlers. They propagate to Next.js, and the request fails.

### Supported Webhook Event Handlers

Each handler receives the verified payload for its event type:

<CodeGroup>
  ```typescript TypeScript expandable theme={null}
  onPayload?: (payload: WebhookPayload) => Promise<void>;
  onPaymentSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onPaymentFailed?: (payload: WebhookPayload) => Promise<void>;
  onPaymentProcessing?: (payload: WebhookPayload) => Promise<void>;
  onPaymentCancelled?: (payload: WebhookPayload) => Promise<void>;
  onRefundSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onRefundFailed?: (payload: WebhookPayload) => Promise<void>;
  onDisputeOpened?: (payload: WebhookPayload) => Promise<void>;
  onDisputeExpired?: (payload: WebhookPayload) => Promise<void>;
  onDisputeAccepted?: (payload: WebhookPayload) => Promise<void>;
  onDisputeCancelled?: (payload: WebhookPayload) => Promise<void>;
  onDisputeChallenged?: (payload: WebhookPayload) => Promise<void>;
  onDisputeWon?: (payload: WebhookPayload) => Promise<void>;
  onDisputeLost?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionActive?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionOnHold?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionRenewed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionPlanChanged?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionCancelled?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionFailed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionExpired?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionUpdated?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionPaused?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionUnpaused?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionUpdatePaymentMethod?: (payload: WebhookPayload) => Promise<void>;
  onLicenseKeyCreated?: (payload: WebhookPayload) => Promise<void>;
  onAbandonedCheckoutDetected?: (payload: WebhookPayload) => Promise<void>;
  onAbandonedCheckoutRecovered?: (payload: WebhookPayload) => Promise<void>;
  onDunningStarted?: (payload: WebhookPayload) => Promise<void>;
  onDunningRecovered?: (payload: WebhookPayload) => Promise<void>;
  onCreditAdded?: (payload: WebhookPayload) => Promise<void>;
  onCreditDeducted?: (payload: WebhookPayload) => Promise<void>;
  onCreditExpired?: (payload: WebhookPayload) => Promise<void>;
  onCreditRolledOver?: (payload: WebhookPayload) => Promise<void>;
  onCreditRolloverForfeited?: (payload: WebhookPayload) => Promise<void>;
  onCreditOverageCharged?: (payload: WebhookPayload) => Promise<void>;
  onCreditOverageReset?: (payload: WebhookPayload) => Promise<void>;
  onCreditManualAdjustment?: (payload: WebhookPayload) => Promise<void>;
  onCreditBalanceLow?: (payload: WebhookPayload) => Promise<void>;
  onEntitlementGrantCreated?: (payload: WebhookPayload) => Promise<void>;
  onEntitlementGrantDelivered?: (payload: WebhookPayload) => Promise<void>;
  onEntitlementGrantFailed?: (payload: WebhookPayload) => Promise<void>;
  onEntitlementGrantRevoked?: (payload: WebhookPayload) => Promise<void>;
  onPayoutCreated?: (payload: WebhookPayload) => Promise<void>;
  onPayoutOnHold?: (payload: WebhookPayload) => Promise<void>;
  onPayoutInProgress?: (payload: WebhookPayload) => Promise<void>;
  onPayoutFailed?: (payload: WebhookPayload) => Promise<void>;
  onPayoutSuccess?: (payload: WebhookPayload) => Promise<void>;
  ```
</CodeGroup>

For what each event means, see the [Webhook Event Guide](/developer-resources/webhooks/intents/webhook-events-guide).

## Prompt for LLM

Copy this prompt into your AI coding assistant to have it add the adaptor to your project. To give your agent the Dodo Payments docs and skills as well, install the [Agent Plugin](/developer-resources/build-with-ai-coding-agents).

```text expandable theme={null}

You are an expert Next.js developer assistant. Your task is to guide a user through integrating the @dodopayments/nextjs adapter into their existing Next.js project.

The @dodopayments/nextjs adapter provides route handlers for Dodo Payments' Checkout, Customer Portal, and Webhook functionalities, designed for the Next.js App Router.

First, install the necessary packages. Use the package manager appropriate for your project (npm, yarn, or bun) based on the presence of lock files (e.g., package-lock.json for npm, yarn.lock for yarn, bun.lockb for bun):

npm install @dodopayments/nextjs

Here's how you should structure your response:

    Ask the user which functionalities they want to integrate.

"Which parts of the @dodopayments/nextjs adapter would you like to integrate into your project? You can choose one or more of the following:

    Checkout Route Handler (for handling product checkouts)

    Customer Portal Route Handler (for managing customer subscriptions/details)

    Webhook Route Handler (for receiving Dodo Payments webhook events)

    All (integrate all three)"

    Based on the user's selection, provide detailed integration steps for each chosen functionality.

If Checkout Route Handler is selected:

Purpose: This handler manages different types of checkout flows. All checkout types (static, dynamic, and sessions) return JSON responses with checkout URLs for programmatic handling.
File Creation: Create a new file at app/checkout/route.ts in your Next.js project.

Code Snippet:

// app/checkout/route.ts
import { Checkout } from '@dodopayments/nextjs'

export const GET = Checkout({
bearerToken: process.env.DODO_PAYMENTS_API_KEY!,
returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
type: "static",
});

export const POST = Checkout({
bearerToken: process.env.DODO_PAYMENTS_API_KEY!,
returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
environment: process.env.DODO_PAYMENTS_ENVIRONMENT as "test_mode" | "live_mode",
type: "session", // or "dynamic" for dynamic link
});

Configuration & Usage:

    bearerToken: Your Dodo Payments API key. It's recommended to set this via the DODO_PAYMENTS_API_KEY environment variable.

    returnUrl: (Optional) The URL to redirect the user to after a successful checkout.

    environment: (Optional) Set to "test_mode" for testing, or omit/set to "live_mode" for production.

    type: (Optional) Set to "static" for GET/static checkout, "dynamic" for POST/dynamic checkout, or "session" for POST/checkout sessions.

Static Checkout (GET) Query Parameters:

    productId (required): Product identifier (e.g., ?productId=pdt_123)

    quantity (optional): Quantity of the product

    Customer Fields (optional): fullName, firstName, lastName, email, country, addressLine, city, state, zipCode

    Disable Flags (optional, set to true to disable): disableFullName, disableFirstName, disableLastName, disableEmail, disableCountry, disableAddressLine, disableCity, disableState, disableZipCode

    Advanced Controls (optional): paymentCurrency, showCurrencySelector, paymentAmount, showDiscounts

    Metadata (optional): Any query parameter starting with metadata_ (e.g., ?metadata_userId=abc123)

    Returns: {"checkout_url": "https://checkout.dodopayments.com/..."}

Dynamic Checkout (POST) - Returns JSON with checkout_url: Parameters are sent as a JSON body. Supports both one-time and recurring payments. Returns: {"checkout_url": "https://checkout.dodopayments.com/..."}. For a complete list of supported POST body fields, refer to:

    Docs - One Time Payment Product: https://docs.dodopayments.com/api-reference/payments/post-payments

    Docs - Subscription Product: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions


Checkout Sessions (POST) - (Recommended) A more customizable checkout experience. Returns JSON with checkout_url: Parameters are sent as a JSON body. Supports both one-time and recurring payments. Returns: {"checkout_url": "https://checkout.dodopayments.com/session/..."}. For a complete list of supported fields, refer to:

  Checkout Sessions Integration Guide: https://docs.dodopayments.com/developer-resources/checkout-session

Error Handling: If productId is missing or other parameters are invalid, the handler will return a 400 response.

If Customer Portal Route Handler is selected:

Purpose: This handler redirects a customer to their Dodo Payments customer portal. It does not authenticate the caller, so protect the route and pass only the signed-in user's customer ID.
File Creation: Create a new file at app/customer-portal/route.ts in your Next.js project.

Code Snippet:

// app/customer-portal/route.ts
import { CustomerPortal } from '@dodopayments/nextjs'

export const GET = CustomerPortal({
bearerToken: process.env.DODO_PAYMENTS_API_KEY!,
environment: "test_mode",
});

Query Parameters:

    customer_id (required): The customer ID for the portal session (e.g., ?customer_id=cus_123)

    send_email (optional, boolean): If set to true, sends an email to the customer with the portal link.

    Returns 400 if customer_id is missing.

If Webhook Route Handler is selected:

Purpose: This handler processes incoming webhook events from Dodo Payments, allowing your application to react to events like successful payments, refunds, or subscription changes.
File Creation: Create a new file at app/api/webhook/dodo-payments/route.ts in your Next.js project.

Code Snippet:

// app/api/webhook/dodo-payments/route.ts
import { Webhooks } from '@dodopayments/nextjs'

export const POST = Webhooks({
webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY!,
onPayload: async (payload) => {
// handle the payload
},
// ... other event handlers for granular control
});

Handler Details:

    Method: Only POST requests are supported. Other methods return 405.

    Signature Verification: The handler verifies the webhook signature using the webhookKey and returns 401 if verification fails.

    Payload Validation: The payload is validated with Zod. Returns 400 for invalid payloads.

Error Handling:

    401: Invalid signature

    400: Invalid payload

    500: Internal error during verification

Event Routing: Calls the appropriate event handler based on the payload type.

Supported Webhook Event Handlers:

    onPayload?: (payload: WebhookPayload) => Promise<void>

    onPaymentSucceeded?: (payload: WebhookPayload) => Promise<void>

    onPaymentFailed?: (payload: WebhookPayload) => Promise<void>

    onPaymentProcessing?: (payload: WebhookPayload) => Promise<void>

    onPaymentCancelled?: (payload: WebhookPayload) => Promise<void>

    onRefundSucceeded?: (payload: WebhookPayload) => Promise<void>

    onRefundFailed?: (payload: WebhookPayload) => Promise<void>

    onDisputeOpened?: (payload: WebhookPayload) => Promise<void>

    onDisputeExpired?: (payload: WebhookPayload) => Promise<void>

    onDisputeAccepted?: (payload: WebhookPayload) => Promise<void>

    onDisputeCancelled?: (payload: WebhookPayload) => Promise<void>

    onDisputeChallenged?: (payload: WebhookPayload) => Promise<void>

    onDisputeWon?: (payload: WebhookPayload) => Promise<void>

    onDisputeLost?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionActive?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionOnHold?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionRenewed?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionPlanChanged?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionCancelled?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionFailed?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionExpired?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionUpdated?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionPaused?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionUnpaused?: (payload: WebhookPayload) => Promise<void>

    onSubscriptionUpdatePaymentMethod?: (payload: WebhookPayload) => Promise<void>

    onLicenseKeyCreated?: (payload: WebhookPayload) => Promise<void>

    onAbandonedCheckoutDetected?: (payload: WebhookPayload) => Promise<void>

    onAbandonedCheckoutRecovered?: (payload: WebhookPayload) => Promise<void>

    onDunningStarted?: (payload: WebhookPayload) => Promise<void>

    onDunningRecovered?: (payload: WebhookPayload) => Promise<void>

    onCreditAdded?: (payload: WebhookPayload) => Promise<void>

    onCreditDeducted?: (payload: WebhookPayload) => Promise<void>

    onCreditExpired?: (payload: WebhookPayload) => Promise<void>

    onCreditRolledOver?: (payload: WebhookPayload) => Promise<void>

    onCreditRolloverForfeited?: (payload: WebhookPayload) => Promise<void>

    onCreditOverageCharged?: (payload: WebhookPayload) => Promise<void>

    onCreditOverageReset?: (payload: WebhookPayload) => Promise<void>

    onCreditManualAdjustment?: (payload: WebhookPayload) => Promise<void>

    onCreditBalanceLow?: (payload: WebhookPayload) => Promise<void>

    onEntitlementGrantCreated?: (payload: WebhookPayload) => Promise<void>

    onEntitlementGrantDelivered?: (payload: WebhookPayload) => Promise<void>

    onEntitlementGrantFailed?: (payload: WebhookPayload) => Promise<void>

    onEntitlementGrantRevoked?: (payload: WebhookPayload) => Promise<void>

    onPayoutCreated?: (payload: WebhookPayload) => Promise<void>

    onPayoutOnHold?: (payload: WebhookPayload) => Promise<void>

    onPayoutInProgress?: (payload: WebhookPayload) => Promise<void>

    onPayoutFailed?: (payload: WebhookPayload) => Promise<void>

    onPayoutSuccess?: (payload: WebhookPayload) => Promise<void>

    Environment Variable Setup:

To ensure the adapter functions correctly, you will need to manually set up the following environment variables in your Next.js project's deployment environment (e.g., Vercel, Netlify, AWS, etc.):

    DODO_PAYMENTS_API_KEY: Your Dodo Payments API Key (required for Checkout and Customer Portal).

    DODO_PAYMENTS_RETURN_URL: (Optional) The URL to redirect to after a successful checkout (for Checkout handler).

    DODO_PAYMENTS_WEBHOOK_KEY: Your Dodo Payments Webhook Secret (required for Webhook handler).

Example .env file:

DODO_PAYMENTS_API_KEY=your-api-key
DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT="test_mode" # or "live_mode"
DODO_PAYMENTS_RETURN_URL=your-return-url

Usage in your code:

bearerToken: process.env.DODO_PAYMENTS_API_KEY!
webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY!

Important: Never commit sensitive environment variables directly into your version control. Use environment variables for all sensitive information.

If the user needs assistance setting up environment variables for their specific deployment environment, ask them what platform they are using (e.g., Vercel, Netlify, AWS, etc.), and provide guidance. You can also add comments to their PR or chat depending on the context

```


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