Overview
Webhooks are critical for keeping your database synchronized with Dodo Payments. When payments are processed or subscriptions change, Dodo Payments sends webhook events to your Supabase Function, which updates your database accordingly.Prerequisites
- Supabase project created (see Supabase Setup)
- Database schema deployed (see Database Setup)
- Supabase CLI installed (
npm install -g supabaseorbun install -g supabase) DODO_WEBHOOK_SECRETfrom Dodo Payments dashboard
Webhook Function Overview
The webhook function is located at:Function Architecture
The webhook handler:- Verifies webhook signatures using the
DODO_WEBHOOK_SECRET - Processes webhook events based on event type
- Updates the database with payment and subscription data
- Manages user subscription tiers based on subscription status
Handled Event Types
Payment Events
payment.succeeded- Payment completed successfullypayment.failed- Payment attempt failedpayment.processing- Payment is being processedpayment.cancelled- Payment was cancelled
Subscription Events
subscription.active- Subscription is now active (upgrades user tier)subscription.plan_changed- Subscription plan was changed (updates user tier)subscription.renewed- Subscription was renewedsubscription.on_hold- Subscription is temporarily on holdsubscription.cancelled- Subscription was cancelled (downgrades user)subscription.expired- Subscription expired (downgrades user)subscription.failed- Subscription payment failed (downgrades user)
Deploy the Webhook Function
Log in to Supabase CLI
Authenticate with Supabase:This will open a browser window for authentication.
Get your project reference ID
Find your Supabase project reference in your project URL:Copy the
[your-project-ref] part.Deploy the webhook function
Run the deployment command:Replace
[your-project-ref] with your actual project reference.The
--no-verify-jwt flag is included in the deployment script because webhook endpoints should be publicly accessible without JWT authentication. Security is handled through webhook signature verification instead.Set environment variables
After deployment, configure the function’s environment variables:
- Go to your Supabase project dashboard
- Navigate to Edge Functions → dodo-webhook
- Click on Settings
- Add the following secrets:
SUPABASE_URL: Your Supabase project URLSUPABASE_SERVICE_ROLE_KEY: Your service role keyDODO_WEBHOOK_SECRET: Your Dodo Payments webhook secret
Configure Dodo Payments Webhook
Select events
Choose which events to send to your webhook. For full functionality, select:Payment Events:
- payment.succeeded
- payment.failed
- payment.processing
- payment.cancelled
- subscription.active
- subscription.plan_changed
- subscription.renewed
- subscription.on_hold
- subscription.cancelled
- subscription.expired
- subscription.failed
You can select “All events” to ensure you receive all current and future event types.
Webhook Function Code Structure
Main Handler
The function uses Deno’sserve API:
Key Functions
managePayment()
Upserts payment records to thepayments table:
manageSubscription()
Upserts subscription records to thesubscriptions table:
updateUserTier()
Links active subscriptions to user accounts:downgradeToHobbyPlan()
Removes subscription when cancelled or expired:Testing Your Webhook
Test in Dodo Payments Dashboard
- Go to Settings → Webhooks
- Find your webhook endpoint
- Click Send test event
- Select an event type (e.g.,
payment.succeeded) - Click Send
Monitor Function Logs
View real-time logs in Supabase:- Go to Edge Functions → dodo-webhook
- Click on Logs
- You’ll see incoming requests and any errors
Verify Database Updates
After sending a test event, check your database:- Go to Database → Table Editor
- Select the
paymentsorsubscriptionstable - Verify that test data appears
Troubleshooting
Webhook signature verification failed
Webhook signature verification failed
Cause: The
DODO_WEBHOOK_SECRET is incorrect or not set.Solution:- Verify the secret in Dodo Payments dashboard matches the one set in Supabase
- Check that the secret is properly set in Edge Functions settings
- Redeploy the function after updating secrets
Function returns 500 error
Function returns 500 error
Cause: Database connection or environment variable issues.Solution:
- Check that
SUPABASE_URLandSUPABASE_SERVICE_ROLE_KEYare set correctly - Verify your database tables exist by running
db:pushagain - Check function logs for specific error messages
Events received but database not updating
Events received but database not updating
Cause: Table structure mismatch or missing fields.Solution:
- Ensure your database schema matches the latest version
- Run
bun run db:pushto sync schema changes - Check function logs for SQL errors
CORS errors in logs
CORS errors in logs
Cause: CORS headers not properly configured.Solution: The function includes CORS headers, but if you’re still seeing errors:
- Ensure the OPTIONS handler is responding correctly
- Check that
corsHeadersincludes your domain - Verify the request method is allowed
Security Considerations
Next Steps
Run Development Server
Start your application and test the complete flow
Deploy to Production
Deploy your application to Vercel or your preferred platform
