SaaSyBase
SaaSyBase

Pricing & Coupons

This page covers the commercial model that sits above payment providers: how plans are shaped, how recurring and one-time purchases behave, how proration works, where users manage billing, and how coupons and receipts fit into the flow.

Plans and pricing model

A plan is the product definition your users buy. Providers fulfill the payment, but the app decides what a plan means: duration, token grant, renewal behavior, and whether it supports organizations.

Field or conceptWhat it controls
PlanName, description, price, duration, token grant, recurring behavior, organization support
PlanPriceProvider-specific localized price for a plan
autoRenewWhether the plan is recurring or one-time
supportsOrganizationsWhether the plan can power an organization workspace
tokenLimitHow many paid tokens or credits are granted

One-time vs recurring plans

One-time plans

A one-time plan has autoRenew=false. The user pays once and is not charged again automatically. The access window can either follow the configured duration or be marked as lifetime access.

  • Useful for short access windows like 24-hour or 7-day offers
  • Can also be modeled as a lifetime purchase when isLifetime=true
  • Often works as a credit or token top-up
  • Finite plans end when expiresAt is reached; lifetime plans stay active without renewal

In practice, a finite plan becomes fully inactive when the expiry lifecycle catches up with that timestamp. The built-in expiry job and grace-window settings control exactly when access is removed, so a just-expired plan may still be inside its configured grace period until the next expiry check runs.

Recurring plans

A recurring plan has autoRenew=true. It renews automatically according torecurringInterval and recurringIntervalCount.

  • Supports monthly, yearly, weekly, and other interval combinations
  • Can be cancelled at period end rather than immediately
  • Can participate in proration when switching between recurring plans

Personal vs workspace scope

Plans can also be personal or workspace-oriented. When supportsOrganizations=true, the plan is eligible to power an organization and team workflows.

Checkout modes and user flows

The app uses two checkout shapes depending on what the user is buying:

ModeUsed forEffect
paymentOne-time purchasesCreates a one-time payment rather than a renewing subscription
subscriptionRecurring plansCreates or updates a recurring subscription record

Users encounter these flows primarily through /pricing, /dashboard/plan, and /dashboard/billing.

What one-time purchases actually do

One-time purchases are more nuanced than “create a temporary plan.” The payment service resolves different behaviors depending on the user's current active subscription.

SituationBehavior
No active subscriptionCreate a new one-time subscription
Active one-time subscription in same plan familyExtend the existing one-time subscription
Active one-time subscription in different family (personal vs org-supporting mismatch)Replace the existing one-time subscription
Active recurring subscriptionTreat the purchase as a token or credit top-up instead of replacing the recurring plan

Lifetime one-time plans use the same flow shape with an explicit lifetime flag, so the branching stays minimal: the subscription is still created or extended through the normal one-time handlers, but the resulting access is treated as lifetime instead of finite-duration.

Note

The “buy a one-time offer over an active recurring plan” flow is a real top-up path, not just a pricing-page illusion.

Localized provider pricing

SaaSyBase supports per-provider, per-currency pricing through the PlanPrice model. A single plan can therefore have multiple localized prices without becoming multiple products in your app.

PlanPrice {
  planId
  provider
  currency
  amountCents
  externalPriceId
}

Example: the same plan can be $10 USD on Stripe and ₦15,000 NGN on Paystack without splitting your business logic into separate plans.

Recurring intervals

Recurring plans use both a unit and a multiplier:

FieldExampleMeaning
recurringIntervalmonthThe billing unit
recurringIntervalCount2Every 2 units, e.g. every 2 months

Note

Razorpay requires daily subscriptions to use recurringIntervalCount >= 7. Shorter daily cadences are skipped there while other providers can still work.

Proration and plan changes

Proration only applies when moving between recurring plans. It is not used for one-time purchases.

When it applies

  • The current subscription must be active and recurring
  • The target plan must also be recurring
  • The target plan must be different from the current plan
  • Recurring proration must be enabled in settings (ENABLE_RECURRING_PRORATION)

Proration flow

StepRoute or stateWhat happens
PreviewGET /api/subscription/proration?planId=...Returns the estimated charge or credit, line items, and downgrade or upgrade context
ApplyPOST /api/subscription/prorationBegins the plan change and can place the subscription into a pending state
Pending stateprorationPendingSince + PENDINGThe subscription is waiting for provider-side confirmation
FinalizeWebhook confirmationSubscription returns to ACTIVE once the provider confirms the change

Downgrades and scheduling

Depending on provider and change type, some downgrades are scheduled for the end of the current cycle instead of applied immediately. The subscription can carry scheduledPlanId and scheduledPlanDate metadata for this.

Catalog sync and price auto-creation

When PAYMENT_AUTO_CREATE="true", the app can create missing provider-side catalog objects for supported providers during seed or plan save flows.

PAYMENT_AUTO_CREATE="true"

In the admin plan UI, manual provider price ID fields are advanced overrides. The normal workflow is to leave them blank and let sync populate them.

Cancellation and billing management

Cancellation is generally handled as cancel-at-period-end rather than immediate loss of access.

FlowRouteNotes
User cancelPOST /api/billing/cancelRequests cancel-at-period-end behavior
Billing portal / management linkPOST /api/billing/customer-portalCreates a provider-specific billing management session or redirect
Undo cancelPOST /api/billing/undo-cancelRestores auto-renew when supported

Provider behavior differs. Stripe supports a native customer portal directly. Paystack relies on an app-level workaround. Some providers rely more on hosted management URLs than a full Stripe-style portal.

Coupon system

Coupons are provider-aware but app-controlled. SaaSyBase supports both native provider coupons and in-app discount calculation.

CapabilityDetails
Discount typesPercent-off and amount-off
Durationonce, repeating for N months, or forever
Plan restrictionsCouponPlan join table limits redemption to specific plans
Currency awarenessAmount-off coupons can be currency-specific
Availability windowsstartsAt and endsAt
Usage capsMax redemptions and activation toggles

Provider behavior

Provider typeBehavior
Stripe / PaddleCan use provider-native coupon or promotion objects
Paystack / RazorpayDiscount is calculated in-app before checkout
Razorpay offersOptional offer linking can be driven through coupon metadata conventions

Do not apply the same discount twice. If your flow is already reducing the amount in-app for Paystack or Razorpay, make sure you are not also layering an equivalent provider-side discount on top of that checkout.

Where coupons appear

  • /admin/coupons for create/edit/activation
  • /dashboard/coupons for redeemed and pending user coupons
  • Pricing and checkout UI can surface coupon application during purchase flows
  • /api/admin/coupons and /api/dashboard/coupons for management and visibility

What the UI actually exposes

RouteAudienceWhat it does
/pricingPublic or signed-in userBrowse plans and start checkout
/dashboard/planSigned-in userReview current subscription, pending changes, and compare plans
/dashboard/billingSigned-in userManage billing, invoices, renewal timing, and payment methods or links
/dashboard/couponsSigned-in userView redeemed and pending coupons
/admin/plansAdminCreate, edit, price, activate, and sync plans
/admin/couponsAdminManage coupon rules and activation

Admin plan and subscription workflows

Admins manage the catalog from /admin/plans. The UI exposes both recurring and non-recurring offers, active subscriber counts, and sync helpers for provider price IDs.

Subscription lifecycle tools also exist in admin APIs, including schedule-cancel, expire, edit, and force-cancel flows. Those are documented in the API reference but matter here because they shape what billing management means operationally.

Invoices and refund receipts

SaaSyBase generates provider-agnostic PDF invoices and refund receipts server-side using pdf-lib. That gives every provider a consistent document experience.

DocumentWhat it includesRoute
Invoice PDFBranding, bill-to details, plan details, discounts, totals, provider reference/api/billing/invoice/[paymentId]
Refund receipt PDFRefund ID, amount refunded, original transaction details, coupon context/api/billing/refund-receipt/[paymentId]

Tip

If you need lower-level request and response details for any of these billing routes, use the API Reference.