
Checkout Integration
Wire Dodo Payments checkout sessions—hosted redirect, overlay modal, or payment links—for one-time and subscription carts.
Overview
Checkout-integration is an agent skill for the Build phase that creates Dodo Payments checkout sessions and payment flows.
Install
npx skills add https://github.com/dodopayments/skills --skill checkout-integrationWhat is this skill?
- Three checkout methods: Hosted Checkout, Overlay Checkout, Payment Links
- TypeScript SDK example for checkoutSessions.create with product_cart and customer
- Supports multiple products in one session and subscription-oriented flows per Dodo docs
- Points to official integration guide at docs.dodopayments.com
- Server-side bearer token pattern with DODO_PAYMENTS_API_KEY
- 3 checkout methods table (Hosted, Overlay, Payment Links)
Adoption & trust: 558 installs on skills.sh; 9 GitHub stars; 2/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need hosted or overlay checkout for Dodo Payments but are unsure how to structure sessions, carts, and customer fields in code.
Who is it for?
Indie SaaS or product builders adding Dodo Payments as their merchant of record checkout.
Skip if: Teams on Stripe-only stacks or no-code-only billing with zero custom backend—use Payment Links from dashboard alone may suffice without this skill.
When should I use this skill?
Guide for creating checkout sessions and payment flows with Dodo Payments - one-time, subscriptions, and overlay checkout.
What do I get? / Deliverables
You get working checkoutSessions.create patterns with redirect or overlay options aligned to Dodo’s integration guide.
- Checkout session creation code
- Integration approach choice (hosted vs overlay vs links)
Recommended Skills
Journey fit
Payment checkout is implemented during product build when you connect monetization to your app or site. Integrations is the shelf for third-party payment SDKs, session APIs, and return_url success flows.
How it compares
Agent skill for Dodo checkout API patterns—not a deployed MCP server or generic payment abstraction layer.
Common Questions / FAQ
Who is checkout-integration for?
Solo builders shipping paid products who chose Dodo Payments and need SDK-level checkout session setup.
When should I use checkout-integration?
During Build integrations when adding one-time or subscription checkout, hosted pages, or overlay modals before launch.
Is checkout-integration safe to install?
It describes API key usage via environment variables; review the Security Audits panel on this page and never commit bearer tokens.
SKILL.md
READMESKILL.md - Checkout Integration
# Dodo Payments Checkout Integration **Reference: [docs.dodopayments.com/developer-resources/integration-guide](https://docs.dodopayments.com/developer-resources/integration-guide)** Create seamless payment experiences with hosted checkout pages or overlay checkout modals. --- ## Checkout Methods | Method | Best For | Integration | |--------|----------|-------------| | **Hosted Checkout** | Simple integration, full-page redirect | Server-side SDK | | **Overlay Checkout** | Seamless UX, stays on your site | JavaScript SDK | | **Payment Links** | No-code, shareable links | Dashboard | --- ## Hosted Checkout ### Basic Implementation ```typescript import DodoPayments from 'dodopayments'; const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY, }); // Create checkout session const session = await client.checkoutSessions.create({ product_cart: [ { product_id: 'prod_xxxxx', quantity: 1 } ], customer: { email: 'customer@example.com', name: 'John Doe', }, return_url: 'https://yoursite.com/checkout/success', }); // Redirect customer to checkout // session.checkout_url ``` ### With Multiple Products ```typescript const session = await client.checkoutSessions.create({ product_cart: [ { product_id: 'prod_item_1', quantity: 2 }, { product_id: 'prod_item_2', quantity: 1 }, ], customer: { email: 'customer@example.com', }, return_url: 'https://yoursite.com/success', }); ``` ### With Customer ID (Existing Customer) ```typescript const session = await client.checkoutSessions.create({ product_cart: [ { product_id: 'prod_xxxxx', quantity: 1 } ], customer_id: 'cust_existing_customer', return_url: 'https://yoursite.com/success', }); ``` ### With Metadata ```typescript const session = await client.checkoutSessions.create({ product_cart: [ { product_id: 'prod_xxxxx', quantity: 1 } ], customer: { email: 'customer@example.com', }, metadata: { order_id: 'order_12345', referral_code: 'FRIEND20', user_id: 'internal_user_id', }, return_url: 'https://yoursite.com/success', }); ``` --- ## Next.js Implementation ### API Route ```typescript // app/api/checkout/route.ts import { NextRequest, NextResponse } from 'next/server'; import DodoPayments from 'dodopayments'; const client = new DodoPayments({ bearerToken: process.env.DODO_PAYMENTS_API_KEY!, }); export async function POST(req: NextRequest) { try { const { productId, quantity = 1, email, name, metadata } = await req.json(); if (!productId || !email) { return NextResponse.json( { error: 'Missing required fields' }, { status: 400 } ); } const session = await client.checkoutSessions.create({ product_cart: [{ product_id: productId, quantity }], customer: { email, name }, metadata, return_url: `${process.env.NEXT_PUBLIC_APP_URL}/checkout/success`, }); return NextResponse.json({ checkoutUrl: session.checkout_url, sessionId: session.checkout_session_id, }); } catch (error: any) { console.error('Checkout error:', error); return NextResponse.json( { error: error.message || 'Failed to create checkout' }, { status: 500 } ); } } ``` ### Client Component ```typescript // components/CheckoutButton.tsx 'use client'; import { useState } from 'react'; interface CheckoutButtonProps { productId: string; email: string; name?: string; children: React.ReactNode; } export function CheckoutButton({ productId, email, name, children }: CheckoutButtonProps) { const [loading, setLoading] = useState(false); const handleCheckout = async () => { setLoading(true); try { const response = await fetch('/api/checkout', { method: 'POST', headers: { 'Content-T