
checkout-integration
Dodo Payments checkout via hosted Checkout Sessions (client.checkoutSessions.create), static payment links, and overlay or inline checkout for one-time and subscription products. Use when building a pay button, checkout page, trial signup, custom fields, discount codes at checkout, or returnurl redirects; use subscription-integration for post-checkout lifecycle.
- Installs
- 997
- Last 24h
- —
- Trending rank
- —
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/dodopayments/skills --skill checkout-integration- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads checkout-integration automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Dodo Payments Checkout Integration
Use client.checkoutSessions.create(...) to build hosted checkout pages or overlay checkout modals. This is the recommended path for all new payment integrations.
When to use this skill
- Build a one-time payment checkout flow
- Create a subscription checkout with optional trial
- Embed checkout in an overlay or inline modal
- Collect customer billing info and custom fields at checkout
- Apply discount codes or handle currency selection
- Redirect customers after payment completes
Checkout Methods
Dodo Payments offers three ways to collect payment:
| Method | Best For | Setup |
|---|---|---|
| Checkout Sessions (recommended) | Most integrations; full control | Server-side SDK call |
| Static Payment Links | No-code sharing; reusable URLs | Dashboard or direct URL |
| Overlay/Inline Checkout | Checkout stays on your site | Client-side SDK |
Legacy: Dynamic Payment Links created via POST /payments or POST /subscriptions are deprecated. Use Checkout Sessions instead.
Core Concepts
Amounts in smallest currency unit: All prices are in cents (or equivalent). A $10 USD charge is 1000.
Checkout Session: A single-use session that generates a hosted checkout URL. Expires after 24 hours (or 15 minutes if confirm=true).
Return URL: Where the customer lands after payment. Dodo appends payment_id (one-time) or subscription_id (subscription), status, and when available license_key and email. It is a UI hint only, never proof of payment.
Entitlement on webhook: The browser redirect is not the source of truth. Always verify payment via webhook before granting access. See webhook-integration skill for verification.
Create a Checkout Session
Basic One-Time Payment
import DodoPayments from 'dodopayments';
const client = new DodoPayments({
bearerToken: process.env.DODO_PAYMENTS_API_KEY,
environment: 'test_mode', // or 'live_mode'
});
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: {
email: 'customer@example.com',
name: 'Jane Doe'
},
return_url: 'https://yoursite.com/checkout/success'
});
console.log('Redirect to:', session.checkout_url);
Response fields:
session_id: Unique checkout session IDcheckout_url: Hosted checkout URL (redirect customer here). Nullable whenconfirm=trueclient_secret: Present only ifconfirm=truepublishable_key: Present only ifconfirm=true. Pair it withclient_secretfor the inline SDK flowpayment_id: Present only ifconfirm=true
publishable_key is a per-session value returned for confirm-mode inline checkout. It is not a Stripe-style
publishable API key — Dodo issues no such credential, and every API key is secret and server-side only.
With Multiple Products
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_item_1', quantity: 2 },
{ product_id: 'pdt_item_2', quantity: 1 }
],
customer: { email: 'customer@example.com' },
return_url: 'https://yoursite.com/success'
});
With Existing Customer
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: { customer_id: 'cus_existing_id' },
return_url: 'https://yoursite.com/success'
});
With Billing Address and Tax ID
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: {
email: 'customer@example.com',
name: 'Jane Doe'
},
billing_address: {
country: 'US',
street: '123 Main St',
city: 'San Francisco',
state: 'CA',
zipcode: '94105'
},
tax_id: 'VAT123456789',
customer_business_name: 'Acme Corp',
return_url: 'https://yoursite.com/success'
});
With Discount Codes
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: { email: 'customer@example.com' },
discount_codes: ['PROMO10', 'WELCOME5'], // max 20, ordered
feature_flags: {
allow_discount_code: true
},
return_url: 'https://yoursite.com/success'
});
With Subscription and Trial
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_monthly_subscription', quantity: 1 }
],
subscription_data: {
trial_period_days: 14
},
customer: { email: 'subscriber@example.com' },
return_url: 'https://yoursite.com/success'
});
With Custom Fields
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: { email: 'customer@example.com' },
custom_fields: [
{
key: 'company_size',
label: 'Company Size',
field_type: 'dropdown',
options: ['1-10', '11-50', '51-200', '200+'],
required: true
},
{
key: 'use_case',
label: 'Primary Use Case',
field_type: 'text',
placeholder: 'e.g., analytics, reporting',
required: false
}
],
return_url: 'https://yoursite.com/success'
});
With Metadata
const session = await client.checkoutSessions.create({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: { email: 'customer@example.com' },
metadata: {
order_id: 'order_12345',
referral_code: 'FRIEND20',
campaign: 'summer_sale'
},
return_url: 'https://yoursite.com/success'
});
Next.js App Router
Full guide: references/server-examples.md.
Covers:
- API Route
- Client Component
- Success Page
Express.js
Full guide: references/server-examples.md.
Python (FastAPI)
Full guide: references/server-examples.md.
Overlay Checkout
Full guide: references/overlay-checkout.md.
Covers:
- Installation
- Server Route
- Browser Overlay and Inline Modes
Static Payment Links
No-code shareable links. No server-side API call needed.
Basic Format
https://checkout.dodopayments.com/buy/{productid}
In test mode the host is test.checkout.dodopayments.com (for example https://test.checkout.dodopayments.com/buy/{productid}); a test-mode product does not exist on the live host.
Example:
https://checkout.dodopayments.com/buy/pdt_example
With Query Parameters
https://checkout.dodopayments.com/buy/pdt_example?quantity=2&email=customer@example.com&redirect_url=https%3A%2F%2Fyoursite.com%2Fsuccess
Supported parameters:
quantity: Item quantityredirect_url: Success redirect URLemail: Prefill customer emailfullName,firstName,lastName: Prefill namecountry,city,state,zipCode,addressLine: Prefill addresspaymentCurrency: Force currencymetadata_*: Custom metadata (e.g.,metadata_orderId=123)
Retrieve and Preview Sessions
Retrieve Session Status
const status = await client.checkoutSessions.retrieve('cks_session_id');
console.log(status.id);
console.log(status.payment_status);
Preview Session (without creating)
const preview = await client.checkoutSessions.preview({
product_cart: [
{ product_id: 'pdt_example', quantity: 1 }
],
customer: { email: 'customer@example.com' },
billing_currency: 'EUR'
});
console.log('Preview total:', preview.current_breakup.total_amount);
Customization
Theme and Appearance
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'pdt_example', quantity: 1 }],
customer: { email: 'customer@example.com' },
customization: {
theme: 'dark', // 'light', 'dark', or 'system'
force_language: 'en',
show_order_details: true,
theme_config: {
font_size: 'md',
font_weight: 'normal',
radius: '8px',
pay_button_text: 'Complete Purchase',
light: {
bg_primary: '#ffffff',
text_primary: '#000000',
button_primary: '#0066ff'
}
}
},
return_url: 'https://yoursite.com/success'
});
Feature Flags
const session = await client.checkoutSessions.create({
product_cart: [{ product_id: 'pdt_example', quantity: 1 }],
customer: { email: 'customer@example.com' },
feature_flags: {
allow_discount_code: true,
allow_currency_selection: true,
allow_customer_editing_email: true,
allow_phone_number_collection: true,
require_phone_number: false,
allow_tax_id: true
},
return_url: 'https://yoursite.com/success'
});
Post-Payment Flow
Return URL Handling
After payment, the customer is redirected to your return_url with query parameters:
# One-time payment
https://yoursite.com/success?payment_id=pay_xxx&status=succeeded&email=customer%40example.com
# Subscription (with license keys)
https://yoursite.com/success?subscription_id=sub_xxx&status=active&license_key=LK-001,LK-002&email=customer%40example.com
Query parameters:
payment_id(one-time payments) orsubscription_id(subscriptions)status:succeeded(one-time) oractive(subscription) on success;failedif declined;processing(or arequires_*value) if it settles later;expiredif the session expiredlicense_key: present when the product issues license keys (comma-separated if several)email: present when the customer has an email on record
There is no session_id parameter. Treat processing/missing status as "unknown" and wait for the webhook.
Verify Payment Server-Side
Do not trust the browser redirect. Use the Express webhook route in
references/server-examples.md: it receives the raw signed body
before express.json(), fulfills one-time purchases on verified payment.succeeded using
event.data.customer.customer_id, and grants subscription access only on verified subscription.active.
Webhook signature verification is covered in the webhook-integration skill.
Common Mistakes
1. Granting access from the return URL The return URL redirect is not proof of payment. Never grant access or fulfill an order from its query parameters; wait for a verified webhook event.
2. Using deprecated APIs
Do not use client.payments.create() or client.subscriptions.create() for new integrations. Both are deprecated. Use client.checkoutSessions.create().
3. Forgetting the environment flag
The default is live_mode. Always set environment: 'test_mode' during development to avoid charging real cards.
4. Using the deprecated discount_code
Use discount_codes (an array). The singular discount_code string is deprecated (still accepted for backward compatibility) and cannot be combined with discount_codes in the same request.
5. Amounts in wrong unit
All amounts are in the smallest currency unit (cents for USD). $10 is 1000, not 10.
6. Reusing checkout URLs Checkout URLs are single-use. Create a new session for each checkout attempt.
7. Ignoring confirm=true behavior
When confirm=true, the session is finalized immediately and the checkout URL expires in 15 minutes instead of 24 hours. Use only when you have all required customer data.
8. Forgetting raw body for webhooks
Webhook signature verification requires the raw request body, not a re-serialized JSON object. Mount the
webhook route with express.raw({ type: 'application/json' }) before express.json().
9. Trusting a client-supplied product id
Do not accept an arbitrary pdt_ id from the browser. Authenticate the user, accept a public plan slug,
map it to an allowlisted product id on the server, and reject quantities that are not positive integers.
Resources
FAQ
What does the checkout-integration skill do?
Dodo Payments checkout via hosted Checkout Sessions (client.checkoutSessions.create), static payment links, and overlay or inline checkout for one-time and subscription products. Use when building a pay button, checkout page, trial signup, custom fields, discount codes at checkout, or returnurl redirects; use subscription-integration for post-checkout lifecycle.
How do I install checkout-integration?
Run npx skills add https://github.com/dodopayments/skills --skill checkout-integration in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/checkout-integration/ (personal) or .claude/skills/checkout-integration/ (project).
Which AI agents can use checkout-integration?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is checkout-integration safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains checkout-integration?
It is published by dodopayments in dodopayments/skills. It has 997 recorded installs.
More from dodopayments/skills
webhook-integration
dodopayments/skills
Dodo Payments webhook handling, covering endpoint setup, Standard Webhooks signature verification on the raw body, payment, subscription, and refund event types, idempotency with webhook-id, retries, and local testing. Use when receiving Dodo events, verifying webhook-signature headers, or syncing your database from payment.succeeded or subscription events.
subscription-integration
dodopayments/skills
Dodo Payments subscription lifecycle after checkout, covering trials, statuses like active, onhold, and cancelled, plan upgrades and downgrades, proration, cancellation, failed-payment recovery, mandates, and on-demand charges. Use when managing recurring billing, plan changes, dunning, or off-session charging; use checkout-integration to start the purchase.
dodo-best-practices
dodopayments/skills
Starting point for any Dodo Payments integration, covering Merchant of Record basics, SDK installation and client setup, test and live environments, API keys, and the canonical checkout-to-webhook flow. Use when starting a new integration, initializing the dodopayments client, choosing an architecture, or unsure which Dodo Payments skill applies.
billing-sdk
dodopayments/skills
BillingSDK, the open-source React and shadcn component library for Dodo Payments billing UI. Use when building pricing tables, pricing pages, account billing pages, usage meters, credit balances, invoice history, or cancel and upgrade UI in React or Next.js, or running @billingsdk/cli init; keep Dodo API calls server-side.
usage-based-billing
dodopayments/skills
Dodo Payments usage-based billing that charges per measured unit, covering meters, usage event ingestion by eventname, aggregation, free thresholds, priceperunit, and metered subscriptions. Use when billing per API call, AI token, storage, or bandwidth, sending usage events, or adding metered pricing to a plan; use credit-based-billing for prepaid credit pools.
license-keys
dodopayments/skills
Dodo Payments license keys for software products, covering activation, validation, and deactivation via client.licenses, activation limits, expiry, entitlement grants, revocation, and license webhooks. Use when gating a desktop app, CLI, plugin, or SaaS feature behind a license key, enforcing per-seat or per-device limits, or building a license dashboard.
Popular backend & apis skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
entra-app-registration
microsoft/azure-skills
Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.
google-agents-cli-adk-code
google/agents-cli
This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).
embedded-captions
heygen-com/hyperframes
Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.
entra-agent-id
microsoft/azure-skills
Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).
neon
neondatabase/agent-skills
Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.