Skip to main content

Overview

The Dodo Payments Checkout SDK provides a seamless way to integrate our payment overlay into your web application. Built with TypeScript and modern web standards, it offers a robust solution for handling payments with real-time event handling and customizable themes.
Overlay Checkout Cover Image

Demo

Interactive Demo

See the overlay checkout in action with our live demo.

Quick Start

Get started with the Dodo Payments Checkout SDK in just a few lines of code:
import { DodoPayments } from "dodopayments-checkout";

// Initialize the SDK
DodoPayments.Initialize({
  mode: "test", // 'test' or 'live'
  displayType: "overlay", // Optional: defaults to 'overlay' for overlay checkout
  onEvent: (event) => {
    console.log("Checkout event:", event);
  },
});

// Open checkout
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123"
});
Get your checkout URL from the create checkout session API.

Step-by-Step Integration Guide

1

Install the SDK

Install the Dodo Payments Checkout SDK using your preferred package manager:
npm install dodopayments-checkout
2

Initialize the SDK

Initialize the SDK in your application, typically in your main component or app entry point:
import { DodoPayments } from "dodopayments-checkout";

DodoPayments.Initialize({
  mode: "test", // Change to 'live' for production
  displayType: "overlay", // Optional: defaults to 'overlay' for overlay checkout
  onEvent: (event) => {
    console.log("Checkout event:", event);
    
    // Handle different events
    switch (event.event_type) {
      case "checkout.opened":
        // Checkout overlay has been opened
        break;
      case "checkout.closed":
        // Checkout has been closed
        break;
      case "checkout.error":
        // Handle errors
        console.error("Checkout error:", event.data?.message);
        break;
    }
  },
});
Always initialize the SDK before attempting to open the checkout. Initialization should happen once when your application loads.
3

Create a Checkout Button Component

Create a component that opens the checkout overlay:
// components/CheckoutButton.tsx
"use client";

import { Button } from "@/components/ui/button";
import { DodoPayments } from "dodopayments-checkout";
import { useEffect, useState } from "react";

export function CheckoutButton() {
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    // Initialize the SDK
    DodoPayments.Initialize({
      mode: "test",
      displayType: "overlay",
      onEvent: (event) => {
        switch (event.event_type) {
          case "checkout.opened":
            setIsLoading(false);
            break;
          case "checkout.error":
            setIsLoading(false);
            console.error("Checkout error:", event.data?.message);
            break;
        }
      },
    });
  }, []);

  const handleCheckout = async () => {
    try {
      setIsLoading(true);
      await DodoPayments.Checkout.open({
        checkoutUrl: "https://checkout.dodopayments.com/session/cks_123"
      });
    } catch (error) {
      console.error("Failed to open checkout:", error);
      setIsLoading(false);
    }
  };

  return (
    <Button 
      onClick={handleCheckout}
      disabled={isLoading}
    >
      {isLoading ? "Loading..." : "Checkout Now"}
    </Button>
  );
}
4

Add Checkout to Your Page

Use the checkout button component in your application:
// app/page.tsx
import { CheckoutButton } from "@/components/CheckoutButton";

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-24">
      <h1>Welcome to Our Store</h1>
      <CheckoutButton />
    </main>
  );
}
5

Handle Success and Failure Pages

Create pages to handle checkout redirects:
// app/success/page.tsx
export default function SuccessPage() {
  return (
    <div className="flex min-h-screen flex-col items-center justify-center">
      <h1>Payment Successful!</h1>
      <p>Thank you for your purchase.</p>
    </div>
  );
}

// app/failure/page.tsx
export default function FailurePage() {
  return (
    <div className="flex min-h-screen flex-col items-center justify-center">
      <h1>Payment Failed</h1>
      <p>Please try again or contact support.</p>
    </div>
  );
}
6

Test Your Integration

  1. Start your development server:
npm run dev
  1. Test the checkout flow:
    • Click the checkout button
    • Verify the overlay appears
    • Test the payment flow using test credentials
    • Confirm redirects work correctly
You should see checkout events logged in your browser console.
7

Go Live

When you’re ready for production:
  1. Change the mode to 'live':
DodoPayments.Initialize({
  mode: "live",
  displayType: "overlay",
  onEvent: (event) => {
    console.log("Checkout event:", event);
  }
});
  1. Update your checkout URLs to use live checkout sessions from your backend
  2. Test the complete flow in production
  3. Monitor events and errors

API Reference

Configuration

Initialize Options

interface InitializeOptions {
  mode: "test" | "live";
  displayType?: "overlay" | "inline";
  onEvent: (event: CheckoutEvent) => void;
}
OptionTypeRequiredDescription
mode"test" | "live"YesEnvironment mode: 'test' for development, 'live' for production
displayType"overlay" | "inline"NoDisplay type: 'overlay' for modal checkout (default), 'inline' for embedded checkout
onEventfunctionYesCallback function for handling checkout events

Checkout Options

interface CheckoutOptions {
  checkoutUrl: string;
  options?: {
    showTimer?: boolean;
    showSecurityBadge?: boolean;
    manualRedirect?: boolean;
  };
}
OptionTypeRequiredDescription
checkoutUrlstringYesCheckout session URL from the create checkout session API
options.showTimerbooleanNoShow or hide the checkout timer. Defaults to true. When disabled, you will receive the checkout.link_expired event when the session expires.
options.showSecurityBadgebooleanNoShow or hide the security badge. Defaults to true.
options.manualRedirectbooleanNoWhen enabled, the checkout will not automatically redirect after completion. Instead, you will receive checkout.status and checkout.redirect_requested events to handle the redirect yourself.

Methods

Open Checkout

Opens the checkout overlay with the specified checkout session URL.
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123"
});
You can also pass additional options to customize the checkout behavior:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    showTimer: false,
    showSecurityBadge: false,
    manualRedirect: true,
  },
});
When using manualRedirect, handle the checkout completion in your onEvent callback:
DodoPayments.Initialize({
  mode: "test",
  displayType: "overlay",
  onEvent: (event) => {
    if (event.event_type === "checkout.status") {
      const status = event.data?.message?.status;
      // Handle status: "succeeded", "failed", or "processing"
    }
    if (event.event_type === "checkout.redirect_requested") {
      const redirectUrl = event.data?.message?.redirect_to;
      // Redirect the customer manually
      window.location.href = redirectUrl;
    }
    if (event.event_type === "checkout.link_expired") {
      // Handle expired checkout session
    }
  },
});

Close Checkout

Programmatically closes the checkout overlay.
DodoPayments.Checkout.close();

Check Status

Returns whether the checkout overlay is currently open.
const isOpen = DodoPayments.Checkout.isOpen();
// Returns: boolean

Events

The SDK provides real-time events that you can listen to through the onEvent callback:

Checkout Status Event Data

When manualRedirect is enabled, you receive the checkout.status event with the following data:
interface CheckoutStatusEventData {
  message: {
    status?: "succeeded" | "failed" | "processing";
  };
}

Checkout Redirect Requested Event Data

When manualRedirect is enabled, you receive the checkout.redirect_requested event with the following data:
interface CheckoutRedirectRequestedEventData {
  message: {
    redirect_to?: string;
  };
}
DodoPayments.Initialize({
  onEvent: (event: CheckoutEvent) => {
    switch (event.event_type) {
      case "checkout.opened":
        // Checkout overlay has been opened
        break;
      case "checkout.payment_page_opened":
        // Payment page has been displayed
        break;
      case "checkout.customer_details_submitted":
        // Customer and billing details submitted
        break;
      case "checkout.closed":
        // Checkout has been closed
        break;
      case "checkout.redirect":
        // Checkout will perform a redirect
        break;
      case "checkout.error":
        // An error occurred
        console.error("Error:", event.data?.message);
        break;
      case "checkout.link_expired":
        // Checkout session has expired (only when showTimer is false)
        break;
      case "checkout.status":
        // Checkout status update (only when manualRedirect is enabled)
        const status = event.data?.message?.status;
        break;
      case "checkout.redirect_requested":
        // Redirect requested (only when manualRedirect is enabled)
        const redirectUrl = event.data?.message?.redirect_to;
        break;
    }
  }
});
Event TypeDescription
checkout.openedCheckout overlay has been opened
checkout.payment_page_openedPayment page has been displayed
checkout.customer_details_submittedCustomer and billing details have been submitted
checkout.closedCheckout overlay has been closed
checkout.redirectCheckout will perform a redirect
checkout.errorAn error occurred during checkout
checkout.link_expiredFired when the checkout session expires. Only received when showTimer is set to false.
checkout.statusFired when manualRedirect is enabled. Contains the checkout status (succeeded, failed, or processing).
checkout.redirect_requestedFired when manualRedirect is enabled. Contains the URL to redirect the customer to.

Implementation Options

Package Manager Installation

Install via npm, yarn, or pnpm as shown in the Step-by-Step Integration Guide.

CDN Implementation

For quick integration without a build step, you can use our CDN:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Dodo Payments Checkout</title>
    
    <!-- Load DodoPayments -->
    <script src="https://cdn.jsdelivr.net/npm/dodopayments-checkout@latest/dist/index.js"></script>
    <script>
        // Initialize the SDK
        DodoPaymentsCheckout.DodoPayments.Initialize({
            mode: "test", // Change to 'live' for production
            displayType: "overlay",
            onEvent: (event) => {
                console.log('Checkout event:', event);
            }
        });
    </script>
</head>
<body>
    <button onclick="openCheckout()">Checkout Now</button>

    <script>
        function openCheckout() {
            DodoPaymentsCheckout.DodoPayments.Checkout.open({
                checkoutUrl: "https://checkout.dodopayments.com/session/cks_123"
            });
        }
    </script>
</body>
</html>

Theme Customization

You can customize the checkout appearance by passing a themeConfig object in the options parameter when opening checkout. The theme configuration supports both light and dark modes, allowing you to customize colors, borders, text, buttons, and border radius.

Basic Theme Configuration

DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    themeConfig: {
      light: {
        bgPrimary: "#FFFFFF",
        textPrimary: "#344054",
        buttonPrimary: "#A6E500",
      },
      dark: {
        bgPrimary: "#0D0D0D",
        textPrimary: "#FFFFFF",
        buttonPrimary: "#A6E500",
      },
      radius: "8px",
    },
  },
});

Complete Theme Configuration

All available theme properties:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    themeConfig: {
      light: {
        // Background colors
        bgPrimary: "#FFFFFF",        // Primary background color
        bgSecondary: "#F9FAFB",      // Secondary background color (e.g., tabs)
        
        // Border colors
        borderPrimary: "#D0D5DD",     // Primary border color
        borderSecondary: "#6B7280",  // Secondary border color
        
        // Text colors
        textPrimary: "#344054",       // Primary text color
        textSecondary: "#6B7280",    // Secondary text color
        textPlaceholder: "#667085",  // Placeholder text color
        textError: "#D92D20",        // Error text color
        textSuccess: "#10B981",      // Success text color
        
        // Button colors
        buttonPrimary: "#A6E500",           // Primary button background
        buttonPrimaryHover: "#8CC500",      // Primary button hover state
        buttonTextPrimary: "#0D0D0D",       // Primary button text color
        buttonSecondary: "#F3F4F6",         // Secondary button background
        buttonSecondaryHover: "#E5E7EB",     // Secondary button hover state
        buttonTextSecondary: "#344054",     // Secondary button text color
      },
      dark: {
        // Background colors
        bgPrimary: "#0D0D0D",
        bgSecondary: "#1A1A1A",
        
        // Border colors
        borderPrimary: "#323232",
        borderSecondary: "#D1D5DB",
        
        // Text colors
        textPrimary: "#FFFFFF",
        textSecondary: "#909090",
        textPlaceholder: "#9CA3AF",
        textError: "#F97066",
        textSuccess: "#34D399",
        
        // Button colors
        buttonPrimary: "#A6E500",
        buttonPrimaryHover: "#8CC500",
        buttonTextPrimary: "#0D0D0D",
        buttonSecondary: "#2A2A2A",
        buttonSecondaryHover: "#3A3A3A",
        buttonTextSecondary: "#FFFFFF",
      },
      radius: "8px", // Border radius for inputs, buttons, and tabs
    },
  },
});

Light Mode Only

If you only want to customize the light theme:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    themeConfig: {
      light: {
        bgPrimary: "#FFFFFF",
        textPrimary: "#000000",
        buttonPrimary: "#0070F3",
      },
      radius: "12px",
    },
  },
});

Dark Mode Only

If you only want to customize the dark theme:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    themeConfig: {
      dark: {
        bgPrimary: "#000000",
        textPrimary: "#FFFFFF",
        buttonPrimary: "#0070F3",
      },
      radius: "12px",
    },
  },
});

Partial Theme Override

You can override only specific properties. The checkout will use default values for properties you don’t specify:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    themeConfig: {
      light: {
        buttonPrimary: "#FF6B6B", // Only override primary button color
      },
      radius: "16px", // Override border radius
    },
  },
});

Theme Configuration with Other Options

You can combine theme configuration with other checkout options:
DodoPayments.Checkout.open({
  checkoutUrl: "https://checkout.dodopayments.com/session/cks_123",
  options: {
    showTimer: true,
    showSecurityBadge: true,
    manualRedirect: false,
    themeConfig: {
      light: {
        bgPrimary: "#FFFFFF",
        buttonPrimary: "#A6E500",
      },
      dark: {
        bgPrimary: "#0D0D0D",
        buttonPrimary: "#A6E500",
      },
      radius: "8px",
    },
  },
});

TypeScript Types

For TypeScript users, all theme configuration types are exported:
import { ThemeConfig, ThemeModeConfig } from "dodopayments-checkout";

const themeConfig: ThemeConfig = {
  light: {
    bgPrimary: "#FFFFFF",
    // ... other properties
  },
  dark: {
    bgPrimary: "#0D0D0D",
    // ... other properties
  },
  radius: "8px",
};

Error Handling

The SDK provides detailed error information through the event system. Always implement proper error handling in your onEvent callback:
DodoPayments.Initialize({
  mode: "test",
  displayType: "overlay",
  onEvent: (event: CheckoutEvent) => {
    if (event.event_type === "checkout.error") {
      console.error("Checkout error:", event.data?.message);
      // Handle error appropriately
      // You may want to show a user-friendly error message
      // or retry the checkout process
    }
    if (event.event_type === "checkout.link_expired") {
      // Handle expired checkout session
      console.warn("Checkout session has expired");
    }
  }
});
Always handle the checkout.error event to provide a good user experience when errors occur.

Best Practices

  1. Initialize once: Initialize the SDK once when your application loads, not on every checkout attempt
  2. Error handling: Always implement proper error handling in your event callback
  3. Test mode: Use test mode during development and switch to live only when ready for production
  4. Event handling: Handle all relevant events for a complete user experience
  5. Valid URLs: Always use valid checkout URLs from the create checkout session API
  6. TypeScript: Use TypeScript for better type safety and developer experience
  7. Loading states: Show loading states while the checkout is opening to improve UX
  8. Manual redirects: Use manualRedirect when you need custom control over post-checkout navigation
  9. Timer management: Disable the timer (showTimer: false) if you want to handle session expiration manually

Troubleshooting

Possible causes:
  • SDK not initialized before calling open()
  • Invalid checkout URL
  • JavaScript errors in console
  • Network connectivity issues
Solutions:
  • Verify SDK initialization happens before opening checkout
  • Check for console errors
  • Ensure checkout URL is valid and from the create checkout session API
  • Verify network connectivity
Possible causes:
  • Event handler not properly set up
  • JavaScript errors preventing event propagation
  • SDK not initialized correctly
Solutions:
  • Confirm event handler is properly configured in Initialize()
  • Check browser console for JavaScript errors
  • Verify SDK initialization completed successfully
  • Test with a simple event handler first
Possible causes:
  • CSS conflicts with your application styles
  • Theme settings not applied correctly
  • Responsive design issues
Solutions:
  • Check for CSS conflicts in browser DevTools
  • Verify theme settings are correct
  • Test on different screen sizes
  • Ensure no z-index conflicts with overlay

Enabling Apple Pay

Apple Pay allows customers to complete payments quickly and securely using their saved payment methods. When enabled, customers can launch the Apple Pay modal directly from the checkout overlay on supported devices.
Apple Pay is supported on iOS 17+, iPadOS 17+, and Safari 17+ on macOS.
To enable Apple Pay for your domain in production, follow these steps:
1

Download and upload the Apple Pay domain association file

Download the Apple Pay domain association file.Upload the file to your web server at /.well-known/apple-developer-merchantid-domain-association. For example, if your website is example.com, make the file available at https://example.com/well-known/apple-developer-merchantid-domain-association.
2

Request Apple Pay activation

Email [email protected] with the following information:
  • Your production domain URL (e.g., https://example.com)
  • Request to enable Apple Pay for your domain
You’ll receive confirmation within 1-2 working days once Apple Pay has been enabled for your domain.
3

Verify Apple Pay availability

After receiving confirmation, test Apple Pay in your checkout:
  1. Open your checkout on a supported device (iOS 17+, iPadOS 17+, or Safari 17+ on macOS)
  2. Verify that the Apple Pay button appears as a payment option
  3. Test the complete payment flow
Apple Pay must be enabled for your domain before it will appear as a payment option in production. Contact support before going live if you plan to offer Apple Pay.

Browser Support

The Dodo Payments Checkout SDK supports the following browsers:
  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)
  • IE11+

Overlay vs Inline Checkout

Choose the right checkout type for your use case:
FeatureOverlay CheckoutInline Checkout
Integration depthModal on top of pageFully embedded in page
Layout controlLimitedFull control
BrandingSeparate from pageSeamless
Implementation effortLowerHigher
Best forQuick integration, existing pagesCustom checkout pages, high-conversion flows
Use overlay checkout for faster integration with minimal changes to your existing pages. Use inline checkout when you want maximum control over the checkout experience and seamless branding.
For more help, visit our Discord community or contact our developer support team.