MuseMVP Docs
Billing

Dodo Payments

Configure the Dodo Payments gateway.

MuseMVP integrates Dodo Payments as one of its payment gateways. Through the unified Muse Billing module, it handles subscriptions, one-time purchases, and the customer portal with the same contract and access model as Creem and Stripe. This guide explains how to configure the Dodo gateway and understand how it works.

Set the default gateway

When Dodo Payments is your primary checkout provider, point the billing default gateway to muse_dodo and keep the public value in sync:

MUSE_BILLING_DEFAULT_GATEWAY="muse_dodo"
NEXT_PUBLIC_MUSE_BILLING_DEFAULT_GATEWAY="muse_dodo"

Gateway selection

You can still override the gateway per checkout request. These variables only define the default used by pricing and launch flows.

Get MUSE_DODO_GATEWAY_API_KEY

Before deploying or running locally, configure the required secrets.

# Dodo Payments API key
MUSE_DODO_GATEWAY_API_KEY="DODO_PAYMENTS_API_KEY"
# Optional: force Dodo environment ("test_mode" | "live_mode")
# If omitted, production uses live_mode and other environments use test_mode.
MUSE_DODO_GATEWAY_ENV="test_mode"

Retrieve your API key from the Dodo Payments Dashboard under Developer → API.

Key Security

MUSE_DODO_GATEWAY_API_KEY is server-side only; never expose it to the client or version control.

Get MUSE_DODO_GATEWAY_WEBHOOK_SECRET

# Webhook signing secret
MUSE_DODO_GATEWAY_WEBHOOK_SECRET="DODO_PAYMENTS_WEBHOOK_SECRET"

In the Dodo Payments Dashboard, create a Webhook and set the callback URL to:

https://example.com/api/muse-billing/notify/muse_dodo

Select the event types to listen for (or all):

  • payment.succeeded
  • payment.failed
  • payment.processing
  • payment.cancelled
  • subscription.active
  • subscription.updated
  • subscription.on_hold
  • subscription.renewed
  • subscription.plan_changed
  • subscription.cancelled
  • subscription.failed
  • subscription.expired

Copy the webhook signing secret into MUSE_DODO_GATEWAY_WEBHOOK_SECRET.

Key Security

MUSE_DODO_GATEWAY_WEBHOOK_SECRET is required in production and must stay server-side only.

Create products and get product IDs

Product IDs come from config.payments.productCatalog.*.gatewayProductIds.muse_dodo in src/config/index.ts by default, and can be overridden via environment variables:

# Pro monthly subscription product ID
NEXT_PUBLIC_MUSE_DODO_PRICE_PRO_MONTHLY_ID="prod_muse_dodo_monthly_xxx"
# Pro yearly subscription product ID
NEXT_PUBLIC_MUSE_DODO_PRICE_PRO_YEARLY_ID="prod_muse_dodo_yearly_xxx"
# Lifetime one-time product ID
NEXT_PUBLIC_MUSE_DODO_PRICE_LIFETIME_ID="prod_muse_dodo_lifetime_xxx"

After creating the corresponding products in the Dodo Payments Dashboard, fill in the product IDs via the environment variables above or in src/config/index.ts.

Local development testing

Download Ngrok

Ngrok (https://dashboard.ngrok.com/get-started/setup/windows) is a reverse proxy tool that exposes your local development server to the public internet.

Run

ngrok http 3000

Callback domain

Use the terminal domain shown above as the callback URL in your webhook configuration.

Switch to test mode

Ensure MUSE_DODO_GATEWAY_ENV is set to test_mode and use Dodo Payments test mode in the Dashboard to run payment tests.

Test mode

Payments in Dodo test mode do not result in real charges, making it safe for local testing of subscription and one-time purchase flows.

How it works

Learn how Muse Billing integrates Dodo Payments into the system.

Integration files

src/modules/muse-billing/lib/gateways/dodo/gateway.ts
src/modules/muse-billing/lib/gateways/dodo/mappers.ts
src/backend/api/routes/muse-billing/router.ts
FilePurpose
dodo/gateway.tsDodo gateway implementation: checkout session launch, webhook parsing, customer portal.
dodo/mappers.tsMaps Dodo webhook events and subscription states into Muse contract snapshots.
router.tsAPI routes: exposes /api/muse-billing/* endpoints.

Core workflow

The action flow for payment and accessing the customer portal:

Frontend calls POST /api/muse-billing/launch with productId, optional gatewayId (defaults to orchestrator selection), etc.

Server resolves the Dodo product ID from the config.payments.productCatalog mapping.

Creates a Dodo checkout session and returns launchUrl for the frontend to redirect to the hosted checkout page.

After payment, Dodo sends a webhook; the server verifies the signature and syncs contract lifecycle and access window to the database.

When the user needs to access the platform portal, call POST /api/muse-billing/customer-hub to get a redirect link to the Dodo customer portal for managing subscriptions or downloading receipts.