Every Organization has exactly one real Plan —
price, limits, and feature flags, never inferred from a separate tier label. See the
public pricing page for the
real, current catalog, or fetch it directly:
GET /api/v1/billing/ -> { plan, usage, paystack } (your own Organization)
GET /api/v1/billing/plans/ -> the full real catalog, for the upgrade UIusage.applications.count and usage.mau.count are computed live from real rows
(a live Application count; monthly active users
counted from real sign-in activity in the current period) — never a cached estimate that
can drift from what actually happened.
Reaching Plan.max_applications blocks creating another Application (a real 400 from POST /api/v1/applications/)
— it never blocks anyone from signing in, and never disables an Application you've already
registered. The same principle applies to every other plan-gated feature (custom domain,
white-label branding, webhooks, API keys, SCIM): the check happens server-side, at the
point of use, not just hidden in this dashboard's UI, and a downgrade takes effect
immediately on the next check, not just on new creation attempts.
POST /api/v1/billing/upgrade/ { "plan_slug": "growth-monthly" }
-> { authorization_url, reference } Redirects the browser to Paystack's own hosted checkout page
(authorization_url) — no card details ever touch
this platform's own servers. The Organization's Plan only actually changes once Paystack
confirms the charge via a real, signature-verified webhook, never optimistically on
redirect — closing the checkout tab without completing payment leaves the Organization on
its current plan, not a half-upgraded state.
POST /api/v1/billing/cancel/ Cancels the real Paystack subscription first; the Organization only drops to the free plan once that cancellation is confirmed —
never charged again after a successful cancellation request, and never silently downgraded
while a subscription might still be active on Paystack's side. The same real
cancellation path is reused, not reimplemented, when an Organization is deleted outright
(see Organizations & Applications — a Paystack failure during that flow blocks and rolls back the whole deletion, rather
than deleting the Organization while still billing it).
No self-service downgrade scheduling (a downgrade takes effect immediately on request,
same as cancellation — there's no "at the end of the current billing period" option yet).
Enterprise pricing is not self-service — its Plan row has no fixed price (null means "contact us"),
negotiated outside this flow entirely.