Overview
The Better Auth adaptor,@dodopayments/better-auth, is a Better Auth plugin that connects your users to Dodo Payments. It provides:
- Optional customer creation or email-based customer linking on sign-up
- Checkout sessions, the preferred checkout method, with product slug mapping
- A self-service Customer Portal
- Usage ingestion and reporting endpoints for usage-based billing
- Webhook event processing with signature verification
- TypeScript types for every endpoint
You need a Dodo Payments account and API keys to use this integration.
Prerequisites
- Node.js 16 or later
- Access to your Dodo Payments dashboard
- An existing project that uses Better Auth 1.4 or a later 1.x release
Installation
1
Install Dependencies
Run this command in your project root:
The adaptor, the Dodo Payments SDK, Better Auth, and Zod are installed.
Setup
1
Configure Environment Variables
Add these variables to your
.env file. Create the API key under Developer → API Keys in the dashboard. You get the webhook secret when you add the webhook endpoint, as described under Webhooks on this page. BETTER_AUTH_SECRET is a random string of at least 32 characters.2
Set Up Server-Side Integration
Create or update The plugin adds a
src/lib/auth.ts:dodoCustomerId field to the Better Auth user table, where it stores each user’s Dodo Payments customer ID. After you add the plugin, update your database schema with the Better Auth CLI.3
Set Up Client-Side Integration
Create or update
src/lib/auth-client.ts:Usage Examples
Use
authClient.dodopayments.checkoutSession for new integrations. The
legacy checkout method is deprecated and kept only for backward
compatibility.Creating a Checkout Session (Preferred)
Create a checkout session from a configured slug or from a product cart, then redirect the customer to the returned URL:checkoutSession fills in some fields for you:
- Billing address: Not required up front, because checkout collects it from the customer. To pre-fill it, pass
billing_address. - Customer: For a signed-in user, the plugin uses the email and name from their Better Auth session and ignores any
customerobject you pass. Without a signed-in user, it uses thecustomerobject. - Other fields: The argument accepts the same fields as the request body of the Create Checkout Session endpoint, plus
slugandreferenceId.
slug nor product_cart, the request fails with a 400 error.
The return URL comes from the
successUrl configured in the server plugin,
resolved against your app’s URL. The plugin ignores any return_url in the
client payload.Legacy Checkout (Deprecated)
The legacy method requiresbilling and customer, and creates a payment link through the deprecated dynamic checkout flow. Fields you set in customer override the email and name from the session.
Accessing the Customer Portal
The portal endpoints require a signed-in user with a verified email address. If the user has no Dodo Payments customer yet, the plugin finds one by email or creates one.customer.portal() returns the portal URL:
Listing Customer Data
List the signed-in customer’s subscriptions and payments.page starts at 1, and status filters the results:
Tracking Metered Usage
Enable theusage() plugin on the server to record usage events for usage-based billing and let customers see their usage. Both methods require a signed-in user with a verified email address.
authClient.dodopayments.usage.ingestrecords an event for the signed-in user.authClient.dodopayments.usage.meters.listlists the signed-in customer’s usage events. It acceptspage_number,page_size,event_name,meter_id,start, andendquery parameters.
meter_id, the list includes all of the customer’s usage events. With meter_id, it includes only the events that match that meter.
Webhooks
The webhooks plugin verifies the signature of each Dodo Payments event and
calls your handlers. The default endpoint is
/api/auth/dodopayments/webhooks.1
Generate and Set Webhook Secret
In the dashboard, go to Developer → Webhooks and add your endpoint URL, for example
https://<your-domain>/api/auth/dodopayments/webhooks. Copy the endpoint’s signing secret into your .env file:2
Handle Webhook Events
Pass a handler for each event you want to process.
onPayload runs for every event:{ received: true }.
Supported Webhook Event Handlers
Each handler receives the verified payload for its event type:Configuration Reference
Plugin Options
Plugin Options
- client (required): DodoPayments client instance
- createCustomerOnSignUp (optional): Create a Dodo Payments customer when a user signs up, or link an existing customer with the same email. The plugin also updates the customer when the user’s details change.
- use (required): Array of plugins to enable (checkout, portal, usage, webhooks)
- getCustomerParams (optional): Function that receives the Better Auth
Userand returns extra fields to attach to the Dodo Payments customer on creation and update (e.g.metadata,phone_number). It can be async.
Checkout Plugin Options
Checkout Plugin Options
- products: Array of
{ productId, slug }objects, or an async function that returns one - successUrl: URL to redirect to after successful payment
- authenticatedUsersOnly: Require user authentication (default:
false)
Troubleshooting & Tips
Common Issues
Common Issues
- Invalid API key: Check
DODO_PAYMENTS_API_KEYin.env, and check that the key’s mode matchesenvironment. - Webhook signature mismatch: Check that the webhook secret matches the one set in the Dodo Payments dashboard.
- Customer not created: Check that
createCustomerOnSignUpis set totrue. - Portal or usage requests return 401: The user’s email address isn’t verified.
Best Practices
Best Practices
- Use environment variables for all secrets and keys.
- Test in
test_modebefore you switch tolive_mode. - Log webhook events for debugging and auditing.