Skip to main content

Billing architecture

How money moves between you (the operator), your customers (the orgs), and kuploy.app — and where each layer's state lives.

Three layers

   ┌──────────────────────────────────────────┐
│ Layer 1: tenant → kuploy.app (Stripe) │
│ You pay kuploy.app for the platform. │
│ Plan determines aggregate caps + which │
│ features your customers can be granted. │
└──────────────────────────────────────────┘

│ L1 license-sync ships
│ features + limits down

┌──────────────────────────────────────────┐
│ Layer 2: org → tenant (your gateway) │
│ Your customers pay you for the plan you │
│ define on /admin/plans. Storage of the │
│ org's subscription lives in your own DB. │
│ Feature gates compose L1 × L2: an org │
│ gets a feature only if BOTH your tier │
│ AND its plan grant it. │
└──────────────────────────────────────────┘



┌──────────────────────────────────────────┐
│ Layer 3: customer → org (epay-gateway) │
│ Each org collects invoice payments from │
│ its own customers through a per-org │
│ merchant on the epay-gateway (cinetpay, │
│ om-webpay, djomy, …). Funds flow to │
│ the org's bank, not yours. │
└──────────────────────────────────────────┘

What kuploy.app handles (your L1)

When you sign up at kuploy.app:

  • You pick a platform plan (Hobby / Starter / Growth / Business / Enterprise for kuploy-cloud, Solo / Studio / Agency / Reseller for leeram-business).
  • kuploy.app charges your card via Stripe on its own Stripe account.
  • Your plan ships back to your deployment as a license-sync payload containing features (boolean capabilities) and limits (aggregate quotas).

Upgrade or downgrade your platform plan at kuploy.app/#pricing. Your deployment picks up the change on the next license sync (within ~60 seconds).

What your deployment handles (your L2)

  • Your customers (orgs) sign up directly on your deployment.
  • You define the plans they choose from at /admin/plans — quotas, features, prices, currencies. See Manage Your Plans.
  • Their payments land in your Stripe account (for now — the epay-gateway L2 path is in roadmap).
  • The feature an org sees is the intersection of your L1 platform tier and its L2 plan. Granting whitelabel: true on an L2 plan when your platform tier doesn't include white-label is refused at edit time.

What your customers' customers handle (L3)

  • Each org on your deployment can connect a per-org epay-gateway merchant (cinetpay / om-webpay / djomy).
  • Their invoice payments go directly to that merchant — funds land in the org's bank, not yours.
  • You don't see L3 money. You only see that your orgs have payment collection turned on (an entitlement gated by your L1 tier).

Where everything lives

Inside kuploy.app:

  • Hub (private, single instance) — kuploy.app. Identity (Better Auth), license issuance, L1 plan catalogs, Stripe charging.
  • Per-product subscription rows: a uniform tenant_subscription table keyed by (tenantId, productType). Both kuploy-cloud and leeram-business read/write through the same shape.

In your deployment:

  • License cache — synced from the hub via @kuploy/saas-kit/license. Holds your platform tier's features + limits + grace period.
  • Local L2 catalog — your own plans table (and cloud_plans on kuploy-cloud). Operator-owned.
  • Org subscriptions — your subscriptions table mapping each org to its L2 plan.
  • Feature gate — composes L1 (from license cache) × L2 (from the org's plan row). The composeFeature primitive ships from @kuploy/saas-kit/plans.

The Internal tier

There's a special L2 plan called Internal that grants every feature your L1 tier permits and bypasses all billing for the org. Use it for dogfood orgs, comp'd accounts, or temporary lifts during support incidents. See Manage Your Plans → The Internal tier.

Internal grants up to — but never above — your L1 ceiling. A Studio operator assigning an org to Internal still won't unlock Agency-only features for that org.

Read more