Create secure, hosted checkout experiences that handle the complete payment flow for both one-time purchases and subscriptions with full customization control.
Session Validity: Checkout sessions are valid for 24 hours by default. If you pass confirm=true in your request, the session will only be valid for 15 minutes.
import DodoPayments from 'dodopayments';// Initialize the Dodo Payments clientconst client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY, environment: 'test_mode', // defaults to 'live_mode'});async function createCheckoutSession() { try { const session = await client.checkoutSessions.create({ // Products to sell - use IDs from your Dodo Payments dashboard product_cart: [ { product_id: 'prod_123', // Replace with your actual product ID quantity: 1 } ], // Pre-fill customer information to reduce friction customer: { email: '[email protected]', name: 'John Doe', phone_number: '+1234567890' }, // Billing address for tax calculation and compliance billing_address: { street: '123 Main St', city: 'San Francisco', state: 'CA', country: 'US', // Required: ISO 3166-1 alpha-2 country code zipcode: '94102' }, // Where to redirect after successful payment return_url: 'https://yoursite.com/checkout/success', // Custom data for your internal tracking metadata: { order_id: 'order_123', source: 'web_app' } }); // 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 routeapp.post('/create-checkout', async (req, res) => { try { const session = await createCheckoutSession(); res.json({ checkout_url: session.checkout_url }); } catch (error) { res.status(500).json({ error: 'Failed to create checkout session' }); }});
Copy
Ask AI
import osfrom dodopayments import DodoPayments# Initialize the Dodo Payments clientclient = DodoPayments( bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"), # This is the default and can be omitted environment="test_mode", # defaults to "live_mode")def create_checkout_session(): """ Create a checkout session for a single product with customer data pre-filled. Returns the session object containing checkout_url for customer redirection. """ try: session = client.checkout_sessions.create( # Products to sell - use IDs from your Dodo Payments dashboard product_cart=[ { "product_id": "prod_123", # Replace with your actual product ID "quantity": 1 } ], # Pre-fill customer information to reduce checkout friction customer={ "email": "[email protected]", "name": "John Doe", "phone_number": "+1234567890" }, # Billing address for tax calculation and compliance billing_address={ "street": "123 Main St", "city": "San Francisco", "state": "CA", "country": "US", # Required: ISO 3166-1 alpha-2 country code "zipcode": "94102" }, # Where to redirect after successful payment return_url="https://yoursite.com/checkout/success", # Custom data for your internal tracking metadata={ "order_id": "order_123", "source": "web_app" } ) # Redirect your customer to this URL to complete payment print(f"Checkout URL: {session.checkout_url}") print(f"Session ID: {session.session_id}") return session except Exception as error: print(f"Failed to create checkout session: {error}") raise error# Example usage in a Flask routefrom flask import Flask, jsonify, requestapp = Flask(__name__)@app.route('/create-checkout', methods=['POST'])def create_checkout(): try: session = create_checkout_session() return jsonify({"checkout_url": session.checkout_url}) except Exception as error: return jsonify({"error": "Failed to create checkout session"}), 500
Copy
Ask AI
// Direct API call using fetch - useful for any JavaScript environmentasync function createCheckoutSession() { try { const response = await fetch('https://test.dodopayments.com/checkouts', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.DODO_PAYMENTS_API_KEY}` }, body: JSON.stringify({ // Products to sell - use IDs from your Dodo Payments dashboard product_cart: [ { product_id: 'prod_123', // Replace with your actual product ID quantity: 1 } ], // Pre-fill customer information to reduce checkout friction customer: { email: '[email protected]', name: 'John Doe', phone_number: '+1234567890' }, // Billing address for tax calculation and compliance billing_address: { street: '123 Main St', city: 'San Francisco', state: 'CA', country: 'US', // Required: ISO 3166-1 alpha-2 country code zipcode: '94102' }, // Where to redirect after successful payment return_url: 'https://yoursite.com/checkout/success', // Custom data for your internal tracking metadata: { order_id: 'order_123', source: 'web_app' } }) }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const session = await response.json(); // 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: Redirect user to checkoutcreateCheckoutSession().then(session => { window.location.href = session.checkout_url;});
Direct your customer to the checkout URL to complete their purchase.
Copy
Ask AI
// Redirect immediatelywindow.location.href = session.checkout_url;// Or open in new windowwindow.open(session.checkout_url, '_blank');
Alternative Integration Options: Instead of redirecting, you can embed the checkout directly in your page using Overlay Checkout (modal overlay) or Inline Checkout (fully embedded). Both options use the same checkout session URL.
3
Handle the return
After payment, customers are redirected to your return_url with additional query parameters for payment status.
Array of products to include in the checkout session. Each product must have a valid product_id from your Dodo Payments dashboard.
Mixed Checkout: You can combine one-time payment products and subscription products in the same checkout session. This enables powerful use cases like setup fees with subscriptions, hardware bundles with SaaS, and more.
Amount the customer pays if pay_what_you_want is enabled. If disabled, this field will be ignored.Format: Represented in the lowest denomination of the currency (e.g., cents for USD). For example, to charge $1.00, pass 100.
Find Your Product IDs: You can find product IDs in your Dodo Payments dashboard under Products → View Details, or by using the List Products API.
Customer’s phone number in international format. Required for some payment methods and fraud prevention.Format: Include country code, e.g., "+1234567890" for US numbers
Complete street address including house number, street name, and apartment/unit number if applicable.Example: "123 Main St, Apt 4B" or "456 Oak Avenue"
Two-letter ISO country code (ISO 3166-1 alpha-2). This field is always required when billing_address is provided.Examples: "US" (United States), "CA" (Canada), "GB" (United Kingdom), "DE" (Germany)
Control which payment methods are available to customers during checkout. This helps optimize for specific markets or business requirements.Available Options: credit, debit, upi_collect, upi_intent, apple_pay, google_pay, amazon_pay, klarna, affirm, afterpay_clearpay, sepa, ach, cashapp, multibanco, bancontact_card, eps, ideal, przelewy24, paypal
Critical: Always include credit and debit as fallback options to prevent checkout failures when preferred payment methods are unavailable.
Override the default currency selection with a fixed billing currency. Uses ISO 4217 currency codes.Supported Currencies: USD, EUR, GBP, CAD, AUD, INR, and moreExample: "USD" for US Dollars, "EUR" for Euros
This field is only effective when adaptive pricing is enabled. If adaptive pricing is disabled, the product’s default currency will be used.
Product price for the initial charge to customer. If not specified, the stored price of the product will be used.Format: Represented in the lowest denomination of the currency (e.g., cents for USD). For example, to charge $1.00, pass 100.
The billing_currency override only takes effect when adaptive currency is enabled in your account settings. If adaptive currency is disabled, this parameter will have no effect.
11. Using Existing Payment Methods for Instant Checkout
Use a customer’s saved payment method to create a checkout session that processes immediately, skipping payment method collection:
Copy
Ask AI
const session = await client.checkoutSessions.create({ product_cart: [ { product_id: 'prod_premium_plan', quantity: 1 } ], customer: { customer_id: 'cus_123' // Required when using payment_method_id }, payment_method_id: 'pm_abc123', // Use customer's saved payment method confirm: true, // Required when using payment_method_id return_url: 'https://yourapp.com/success'});
When using payment_method_id, confirm must be set to true and an existing customer_id must be provided. The payment method will be validated for eligibility with the payment’s currency.
The payment method must belong to the customer and be compatible with the payment currency. This enables one-click purchases for returning customers.
Use redirect_immediately: true when you have a custom success page that provides better user experience than the default payment success page. This is especially useful for mobile apps and embedded checkout flows.
When redirect_immediately is enabled, customers are redirected to your return_url immediately after payment completion, skipping the default success page entirely.
Previously, when creating a payment link with Dynamic Links, you were required to provide the customer’s complete billing address.With Checkout Sessions, this is no longer necessary. You can simply pass along whatever information you have, and we’ll handle the rest. For example:
If you only know the customer’s billing country, just provide that.
The checkout flow will automatically collect the missing details before moving the customer to the payment page.
On the other hand, if you already have all the required information and want to skip directly to the payment page, you can pass the full data set and include confirm=true in your request body.