OpenBilling

OpenBilling

Portable billing docs for OpenBilling's current Stripe and Dodo MVP surface.

OpenBilling

OpenBilling is a narrow TypeScript SDK for a targetted set of shared SaaS billing workflows:

  • Create hosted checkouts
  • Create hosted billing portal links
  • Verify provider webhooks
  • Normalize a small set of billing events (as of MVP, the focus was on core events)

The goal is portability, as your Saas scales and grows you shouldn't feel locked into a billing provider due to tech debt. Your app can keep the same workflow-level code for checkout, portal access, and webhook handling, while still being explicit about provider-specific details. ie. Such as Stripe priceId values and Dodo productId values.

What is supported today

  • Stripe
  • Dodo Payments
  • Hosted checkout creation
  • Hosted billing portal links
  • Webhook verification
  • Normalized webhook mapping for payment.succeeded, subscription.active, subscription.cancelled, and unknown

What OpenBilling does not try to hide

OpenBilling keeps the shared surface small on purpose. It does not pretend Stripe and Dodo model catalog data the same way.

  • Stripe checkout currently requires priceId
  • Dodo checkout currently requires productId
  • Unsupported webhook events fall back to unknown
  • Raw provider payloads remain available through raw

Quick example

import {
  Provider,
  type BillingProvider,
  type BillingProviderName,
} from '@openbilling/core';
import { createDodoProvider } from '@openbilling/dodo';
import { createStripeProvider } from '@openbilling/stripe';

function getBillingProvider(
  providerName: BillingProviderName,
): BillingProvider {
  switch (providerName) {
    case Provider.Stripe:
      return createStripeProvider({
        apiKey: process.env.STRIPE_API_KEY!,
        webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
      });

    case Provider.Dodo:
      return createDodoProvider({
        apiKey: process.env.DODO_API_KEY!,
        webhookSecret: process.env.DODO_WEBHOOK_SECRET!,
      });

    default:
      throw new Error('Unsupported billing provider.');
  }
}

The workflow code can stay shared, but the provider-specific catalog identifier still needs to come from the active adapter.

Non-goals

The current MVP does not document or support:

  • Invoices
  • Refunds
  • Disputes
  • Taxes
  • Usage billing
  • Seat billing
  • Marketplace or Connect-style payments
  • Payout flows
  • Entitlement management
  • Analytics dashboards

Next steps

On this page