Skip to main content

Terraform Registry

Provider documentation for each resource, data source, and action.

Example Repository

A complete AI SaaS catalog with plan, apply, drift, and end-to-end workflows.

Overview

The Dodo Payments Terraform provider keeps your pricing in configuration files in your Git repository. You define products, prices, meters, credits, discounts, entitlements, and webhook endpoints in code. A pricing change then goes through the same steps as a code change: a pull request, a reviewed plan, and an apply from CI. This gives your pricing four properties that dashboard edits do not have:
  • Review before release. terraform plan shows each product, price, and discount that a change creates, updates, or archives. A teammate approves the plan before customers see the new price.
  • Version history. Each pricing change is a commit with an author, a reviewer, and a reason. To undo a change, revert the commit and apply again.
  • One catalog in each mode. The same configuration builds your catalog in test mode and in live mode. You test a pricing change end to end in test mode, then apply the same commit to live mode.
  • Drift detection. A scheduled terraform plan finds changes that someone made in the dashboard, so the repository stays the source of truth.
The provider manages the catalog: the objects that define what you sell and at what price. Customers, subscriptions, payments, and refunds are not in the provider. Your application creates them at runtime with the API or an SDK.

What You Can Manage

Each catalog object has a resource. Each resource also has a data source for one object, a data source for a list of objects, and a list resource for terraform query. The provider also has these Terraform objects:
  • The ephemeral resource dodopayments_webhook_secret reads the signing secret of a webhook endpoint without a copy in the state.
  • The actions dodopayments_product_unarchive, dodopayments_addon_unarchive, dodopayments_meter_unarchive, dodopayments_product_collection_unarchive, and dodopayments_credit_entitlement_undelete restore an archived or deleted object.

Getting Started

You need Terraform 1.12 or later and a test mode API key. Create the key in the dashboard under Developer → API Keys while test mode is on.
The provider connects to live mode when you do not set environment. Set environment = "test_mode" until you are ready to change your live catalog.
1

Configure the Provider

Create a file named versions.tf:
versions.tf
2

Set the API Key

The provider reads the API key from the DODO_PAYMENTS_API_KEY environment variable:
3

Define a Product

Create a file named products.tf. Prices are in the smallest currency unit, so 4900 is $49.00:
products.tf
For the meaning of the subscription period, see Subscriptions.
4

Plan and Apply

Download the provider, review the plan, and create the product:
terraform apply prints the new product ID. The product is also in the dashboard, in test mode.

Modeling a Pricing Catalog

A real catalog has tiers, billing cycles, and rules between them. In Terraform, you write the pricing model once as data and generate the objects from it. To change a price, you change one number, and the plan shows each object that the change affects. This example builds three tiers in two billing cycles, puts them in one product collection, and adds a launch discount for the annual plans:
catalog.tf
This configuration shows patterns that the dashboard cannot give you:
  • One source for each price. The discount and the collection refer to the products, not to product IDs. When you add a tier, the collection and the discount get the new plan in the same apply.
  • Pricing rules as checks. The precondition stops the plan when an annual price does not save at least 10%. Use precondition blocks and check blocks for each rule that your pricing must keep.
  • Reviewable changes. When you change pro.monthly from 4900 to 5900, the plan shows one change to dodopayments_product.plan["pro_monthly"] before anything changes.
The example repository extends this model with meters, a shared credit balance with rollover and overage, a usage-based Enterprise plan, localized EUR and INR prices, add-ons, credit packs, and three discount types.

Reviewing Pricing Changes With GitOps

With GitOps, the main branch of your repository is the record of your live catalog. Nobody edits pricing in the dashboard. Each change is a pull request, and CI applies the change after the merge. A GitOps setup for the provider has these parts: This GitHub Actions job applies the catalog after a merge to the main branch:
.github/workflows/apply.yml
The job plans again after the merge, so its plan can differ from the plan in the pull request. This occurs when the dashboard or another merge changed the catalog after the review. Compare the job summary with the reviewed plan, and use the drift check to find dashboard changes early. The concurrency group makes a second apply wait for the first one. The job also needs credentials for your state backend. The example repository uses Workload Identity Federation, so CI has no long-lived cloud key. It also has the plan, drift, and end-to-end workflows.
Give the plan job read-only access to the state, and run its plan with -lock=false, because a state lock needs write access on most backends. Give write access only to the main branch. Then a pull request can show a plan, but only a merge can change your catalog.

Promoting Changes From Test Mode to Live Mode

Each API key works in one mode, and object IDs are different in each mode. Keep one state for each mode, and refer to resources instead of writing IDs in the configuration. Then the same configuration builds the same catalog in both modes. Set the mode with a variable or with the DODO_PAYMENTS_ENVIRONMENT environment variable:
To release a pricing change:
1

Apply in Test Mode

Apply the commit with the test mode API key and the test mode state.
2

Test the Change

Create a checkout for the changed products in test mode. Use the test cards to complete a purchase.
3

Apply in Live Mode

Apply the same commit with the live mode API key and the live mode state.

Detecting Dashboard Changes

A change in the dashboard does not update your configuration. The next terraform apply reverts each dashboard change to an argument that your configuration sets. To find these changes before an apply does, run a plan on a schedule:
The command returns 0 when the catalog matches the configuration and 2 when it does not. The example repository runs this command each night. When the result is 2, it opens an issue with the summary of the plan. When a later run returns 0, it closes the issue. To keep a dashboard change, copy it into the configuration in a pull request. To discard it, run the apply workflow again.

Importing Existing Products

You can bring objects that you created in the dashboard under Terraform management. Import an object with an import block and its ID:
With Terraform 1.14 or later, terraform query lists the objects in your account and writes the configuration for you. Create a file with the .tfquery.hcl extension:
catalog.tfquery.hcl
Then generate a resource block and an import block for each product:
Move the blocks that you want into your configuration, run terraform plan, and confirm that the plan imports the objects with no other changes.

Keeping the Webhook Secret Out of State

The ephemeral resource dodopayments_webhook_secret reads the signing secret of a webhook endpoint during a run. Terraform does not write an ephemeral value to the plan or the state. Pass the secret to a write-only argument, such as the secret data of a secret manager:
Your webhook receiver reads the secret from the secret manager. To verify webhook signatures, see Webhooks.

Deleting a Resource

When you remove a resource from the configuration, Terraform destroys it. The provider archives some objects and deletes others. An action can restore some of them. The table shows what happens to each object.
The API cannot restore an archived brand. Before you remove a dodopayments_brand resource, make sure that you do not need the brand again.
To prevent an accidental destroy of a product that customers subscribe to, add prevent_destroy to its lifecycle block.

Products

Product types, prices, and settings that the provider manages.

Product Collections

Group plans and set the rules for upgrades and downgrades.

Credit-Based Billing

Credit balances with rollover, expiry, and overage.

Test Mode vs Live Mode

How the two modes keep their objects and API keys apart.
Last modified on October 25, 2026