Skip to main content

GitHub Repository

Minimal Go + Dodo Payments boilerplate

Overview

The Go boilerplate is a minimal Go server that sells your Dodo Payments products from a pricing page. It creates checkout sessions, verifies and handles webhooks, and opens the Customer Portal. Clone it as the starting point for your own Go backend.
The boilerplate needs Go 1.24.4 or later, the version set in its go.mod. It uses a cmd, internal, and templates layout, renders the pricing page with Go HTML templates, and calls the Dodo Payments API through the dodopayments-go SDK.

Features

  • Quick Setup: Clone the repository, add your API keys to .env, and start the server with make run.
  • Payment Integration: A checkout flow that creates checkout sessions with the dodopayments-go SDK.
  • Modern UI: A dark-themed pricing page built with Go HTML templates and Tailwind CSS.
  • Webhook Handling: Verifies the signature of each webhook before it processes the event.
  • Customer Portal: Self-serve subscription management through the Customer Portal.
  • Go Best Practices: A clean project layout with cmd, internal, and templates.
  • Pre-filled Checkout: Passes the customer’s name and email to checkout, so the customer doesn’t type them again.

Prerequisites

Before you begin, you need:
  • Go 1.24.4 or later. Check your version with go version.
  • A Dodo Payments account, to create an API key and a webhook signing key in the dashboard.
  • At least one product, created under Products in the dashboard.

Quick Start

1

Clone the Repository

2

Install Dependencies

make install runs go mod download and then go mod tidy. To download the modules without make, run:
3

Get API Credentials

Sign up at Dodo Payments, then copy both keys from the dashboard:
Create both keys in test mode while you develop. To switch to test mode, turn off the Live Mode switch in the dashboard sidebar.
4

Configure Environment Variables

Create a .env file in the project root from the template:
Set these values in .env:
.env
The server reads these variables at startup:The server exits at startup if either required key is missing. .env.example sets PORT and DODO_PAYMENTS_RETURN_URL to port 8080. This page uses port 8000, so set both to 8000 as shown, or replace 8000 with 8080 in the commands on this page.
Never commit your .env file to version control. The repository’s .gitignore already excludes it.
5

Add Your Products

Replace the sample product in internal/lib/products.go with your products. Copy each product ID from Products in the dashboard:
Price sets only the price that the pricing page displays, in the smallest currency unit: 9999 displays as $99.99. Checkout charges the price of the product in Dodo Payments.
6

Run the Development Server

make run builds the server into bin/server and starts it. To run the server without building a binary first, run:
Open http://localhost:8000 to see your pricing page.
You see a dark-themed pricing page that lists your products, ready to purchase.

Project Structure

The repository has this layout:

API Endpoints

The boilerplate includes the following pre-configured endpoints:

Customization

Update Product Information

Edit internal/lib/products.go to change:
  • Product IDs (from Products in your Dodo Payments dashboard)
  • Names
  • Pricing shown on the pricing page
  • Features
  • Descriptions
The pricing page template adds a /mo suffix to every price and shows Custom instead of a price when Price is 100000 or more. To change this, edit templates/index.html.

Pre-fill Customer Data

In templates/index.html, the handleCheckout function sends hardcoded customer data to /api/checkout. Replace it with your signed-in user’s data:
The handlePortal function reuses this customer data, and falls back to the same sample name and email. In a production app, inject these values from your authentication system in both functions.

Webhook Events

internal/api/webhook.go verifies each request with client.Webhooks.Unwrap and the key in DODO_PAYMENTS_WEBHOOK_KEY, then routes the event by its type. These events have a handler, and each handler logs the event data: The handler also accepts subscription.on_hold, subscription.failed, subscription.expired, and subscription.plan_changed without any action, and logs every other event type as unhandled. It responds with 200 to every verified event. For all event types, see the Webhook Event Guide. Add your business logic to the handler functions to:
  • Update user permissions in your database
  • Send confirmation emails
  • Provision access to digital products
  • Track analytics and metrics

Testing Webhooks Locally

Dodo Payments can’t reach localhost. To receive webhooks during development, expose your local server with a tunnel such as ngrok:
In the Dodo Payments Dashboard, add an endpoint with the forwarding URL that ngrok prints, followed by /api/webhook:
Copy the endpoint’s signing key into DODO_PAYMENTS_WEBHOOK_KEY, then restart the server.

Deployment

Build for Production

make build compiles the server into bin/server:
To build and start the binary without make, run:

Deploy to Vercel

Deploy with Vercel After you deploy, add the variables from your .env file to the Vercel project settings, because .env isn’t in the repository. Then set your webhook endpoint in the dashboard to https://yourdomain.com/api/webhook.

Docker

Create a Dockerfile in the project root. The build stage must use Go 1.24.4 or later to match go.mod:
The final image copies templates/ next to the binary, because the server loads the templates from the working directory. Build and run the image:
The container listens on the PORT value from .env, so keep PORT=8000 to match the port mapping.

Production Considerations

Before you deploy to production:
  • Set DODO_PAYMENTS_ENVIRONMENT to live_mode.
  • Use a live mode API key from the dashboard.
  • Point the webhook endpoint at your production domain, and use that endpoint’s signing key.
  • Set DODO_PAYMENTS_RETURN_URL to a page on your production domain.
  • Serve every endpoint over HTTPS.

Troubleshooting

Check that go version reports Go 1.24.4 or later, then download the modules again:
Common causes:
  • The product ID is invalid. Check that it exists under Products in the same mode as your API key.
  • The API key or DODO_PAYMENTS_ENVIRONMENT in .env is wrong. A test mode key needs test_mode.
  • For the exact error, check the server logs. The handler logs every failed request before it returns 500.
For local testing, expose your server with ngrok:
Set the webhook URL in your Dodo Payments dashboard to the ngrok URL. Then set DODO_PAYMENTS_WEBHOOK_KEY in .env to that endpoint’s signing key. If the server logs webhook verification failed, the key doesn’t match the endpoint.
The server loads templates/base.html and templates/index.html from the working directory. Start the server from the project root, or change the template paths in cmd/server/main.go.

Learn More

Go SDK

Complete Go SDK documentation

Webhooks Documentation

Learn about all webhook events and best practices

Checkout Sessions

Deep dive into checkout session configuration

API Reference

Complete Dodo Payments API documentation

Support

For help with the boilerplate:
Last modified on September 25, 2026