Skip to main content

Setting Up Billing for Your Users

Enable subscriptions and payments for the organizations using your kuploy-cloud platform. This guide walks you through connecting Stripe and creating the plans your end users will subscribe to.

Instance Plans vs. Platform Plans

The plans you configure here are instance plans — the subscriptions your customers (organizations) pay to you. These are separate from your platform plan at kuploy.app.

You control the pricing, limits, and names of instance plans.

Single payment surface

All payments — Stripe cards, Apple/Google Pay, and mobile money — flow through the Payment Gateway on Business+ plans, which runs on ePay. This guide stops at creating a Stripe account and defining your plans; wiring up the keys and webhook happens once, on the Payment Gateway admin page, not per rail.

1. Create a Stripe Account​

If you don't have a Stripe account yet:

  1. Go to stripe.com and click Start now
  2. Enter your email and create a password
  3. Verify your email address
  4. Complete business verification (can be done later for testing)
Test Mode

Stripe provides a Test mode for development. Toggle "Test mode" in the top-right of the Stripe Dashboard. Test mode uses fake money and test card numbers - perfect for setup and testing.

2. Get Your API Keys​

  1. In Stripe Dashboard, click Developers in the left sidebar
  2. Click API keys
  3. You'll see two keys:
    • Publishable key (pk_test_... or pk_live_...) - safe to expose
    • Secret key (sk_test_... or sk_live_...) - keep private!
  4. Click Reveal test key to copy your secret key
caution

Never share your secret key. Never commit it to git. Only enter it in secure settings.

3. Stripe Products Are Created Automatically​

You do not need to create Products or Prices in Stripe by hand. When you save a priced plan at /admin/plans, kuploy-cloud creates (or updates) the matching Stripe Product and Price on your own Stripe account, using the price you just entered.

/admin/plans (you)                    Stripe (your account)
┌───────────────────────┐ ┌─────────────────────────────┐
│ slug: "pro" │ │ Create/update Product │
│ price: 2000 │──on save──► │ Create/update Price │
│ currency: "cad" │ │ (archive the old Price) │
│ cycle: monthly │ └─────────────────────────────┘
└───────────────────────┘

Change a plan's price and the next save updates the Stripe Price. Existing subscriptions are not changed retroactively — only new checkouts use the updated price.

Free plans have no Stripe Price

A plan priced at 0 has nothing to charge, so no Stripe Product or Price is created for it. That is normally your default plan — the one new organizations land on without any payment step.

4. Connect Stripe via the Payment Gateway​

Your Stripe credentials live on a Provider record inside your epay-gateway deployment, not in a kuploy-cloud-only settings screen. This keeps one source of truth for every payment rail.

Follow the Payment Gateway setup guide to:

  • Connect kuploy-cloud to your epay-gateway deployment
  • Create a Stripe provider record on the gateway with your secret key (sk_test_... / sk_live_...) and webhook signing secret (whsec_...)
  • Point the Stripe webhook endpoint at the gateway (not directly at kuploy-cloud — the old /api/webhooks/stripe kuploy-cloud endpoint was removed in the cutover)

Once the gateway is connected, the Payment Gateway panel at Admin → Payment Gateway lights up "configured", and plan checkouts / billing portal / invoice listing all work without extra setup.

5. Define Your Plans​

Plans live in your instance, at Admin → Plans (/admin/plans). You set every name, price, quota and feature toggle yourself; kuploy.app never pushes a catalog down.

A fresh install seeds only free and internal. From there you can Suggest paid plans to get a Starter / Growth / Business ladder as hidden drafts to edit, or build each one by hand.

Your platform plan is a ceiling, not a template: a plan granting more than your kuploy.app tier allows is refused when you save it, and a feature only reaches an organization when both your platform tier and the org's plan grant it.

See Manage Your Plans for the full walkthrough — quotas, currency, the Internal tier, and what you can't delete.

6. Verify Your Plans​

  1. In kuploy-cloud, go to Admin → Plans
  2. Check each plan shows the name, price and currency you expect
  3. Confirm exactly one plan is marked Default — that is where new organizations land
  4. Stripe Products and Prices are provisioned on save — no manual Price ID entry required

7. Set Up Webhooks​

Stripe webhooks now flow Stripe → your epay-gateway → kuploy-cloud rather than directly to kuploy-cloud. Full setup is covered in the Payment Gateway guide — see Point your webhooks at kuploy-cloud.

At a glance:

  1. In the Stripe Dashboard, add an endpoint pointing at your epay-gateway:
    https://<your-gateway-host>/api/webhooks/stripe/<merchantCode>
  2. Subscribe to the subscription + invoice events (customer.subscription.*, invoice.payment_*).
  3. Paste the Stripe signing secret (whsec_...) into the Stripe provider record on your gateway — not into kuploy-cloud. The gateway verifies and relays to /api/webhooks/epay on kuploy-cloud.

8. Test Your Setup​

Use Stripe test cards to verify everything works:

Card NumberResult
4242 4242 4242 4242Successful payment
4000 0000 0000 0002Card declined
4000 0000 0000 3220Requires 3D Secure

Use any future expiry date and any 3-digit CVC.

  1. Create a test user account
  2. Go to Billing and select a paid plan
  3. Complete checkout with a test card
  4. Verify the subscription appears in both kuploy-cloud and Stripe Dashboard

Assigning Plans Manually (Employees, Partners, Test Accounts)​

Some organizations on your platform should not be billed through Stripe — internal employees, partner accounts, or test accounts you provision yourself. For these, use Admin → Organizations & Plans in your kuploy-cloud dashboard:

  1. Search for the organization
  2. Click Change plan and pick a plan from the dropdown
  3. Save — the org now has an "active" subscription tagged Manual with a 30-day billing period (so build-minute quotas reset on a predictable boundary)

Manual subscriptions show a Manual badge in the org list. Their members see a "Your plan is managed by the platform administrator" notice on the billing page instead of Stripe checkout/portal buttons. Use Reset period to roll the billing period forward another 30 days, and Cancel to mark the manual sub as canceled.

Stripe-backed subs are read-only here

The Organizations admin refuses to change plans on Stripe-backed subscriptions to avoid drift between the database and Stripe. To change those, use the Stripe Dashboard — webhooks will sync the change back.

Going Live​

When ready for production:

  1. Complete Stripe business verification
  2. Toggle off "Test mode" in the Stripe Dashboard
  3. Swap the Stripe secret key + webhook signing secret on your epay-gateway Stripe provider record for the live values
  4. Update the Stripe webhook endpoint in the Stripe Dashboard to point at your production epay-gateway URL (test-mode and live-mode endpoints are separate)
  5. Re-save each priced plan at /admin/plans so its Product and Price are created on the live Stripe account
  6. Test with a real card (you can refund immediately)

kuploy-cloud itself has no Stripe keys to swap; the gateway is the single credentials surface.


Technical Reference​

For Kubernetes deployments, the only Stripe-related environment variables live on your epay-gateway deployment, not on kuploy-cloud. See admin/.env.example in the gateway repo for the full list.

kuploy-cloud only needs the gateway connection details (URL + admin key + merchant code + merchant key). Those are configured through Admin → Payment Gateway; for headless Kubernetes installs, the same four values are accepted as env vars:

VariableDescription
EPAY_GATEWAY_URLPublic URL of your epay-gateway deployment
EPAY_GATEWAY_ADMIN_KEYBearer token kuploy-cloud uses to call the gateway's management API
EPAY_MERCHANT_CODETenant merchant identifier inside the gateway
EPAY_MERCHANT_KEYHMAC secret used to verify relayed webhooks

Apply the usual way:

echo -n "your_admin_key" | base64
kubectl patch secret kuploy-secrets -n kuploy \
-p '{"data":{"EPAY_GATEWAY_ADMIN_KEY":"<base64-value>"}}'
kubectl rollout restart deployment/kuploy -n kuploy

Database Migrations​

Schema changes run automatically when a new container starts, before it accepts traffic. There are no migration commands for you to run, and no manual step during an upgrade — see Upgrading to Cloud.


Troubleshooting​

Checkout fails​

  1. Open Admin → Payment Gateway in kuploy-cloud and click Test Connection — a green check confirms kuploy-cloud can reach the gateway with the stored admin key.
  2. On your epay-gateway admin, verify the Stripe provider record has the right secret key for the current mode (test vs live).
  3. Check that plan sync completed and Stripe Prices were auto-provisioned:
    kubectl logs -n kuploy -l app.kubernetes.io/name=kuploy | grep -i "stripe.*price"

Webhooks not received​

  1. Confirm the Stripe Dashboard endpoint points at your epay-gateway (https://<gateway>/api/webhooks/stripe/<merchantCode>) — not at kuploy-cloud.
  2. On the gateway's Stripe provider record, the apiSecret must match the Stripe Dashboard's signing secret for that endpoint.
  3. kuploy-cloud's inbound endpoint is /api/webhooks/epay; check those logs for signature/verification errors.
  4. View Stripe-side delivery logs: Stripe Dashboard → Developers → Webhooks → Select endpoint.

Plans not showing​

Your plan catalog is local to your instance — nothing arrives from kuploy.app, so a sync problem is never the cause. At Admin → Plans, check that:

  1. The plan exists at all. A fresh install has only free and internal until you add more — use Suggest paid plans for a starting ladder.
  2. It is Active. Inactive plans keep existing subscribers but are hidden from new signups.
  3. It is Public. Non-public plans are hidden from /pricing and the upgrade picker; you can still assign an org to one from Admin → Organizations & Plans.
  4. Exactly one plan is marked Default, or new organizations have nowhere to land.