Subscriptions & billing
Tiers and the free quota
Every user has a subscription tier and a usage count:
| Tier | Heavy actions |
|---|---|
FREE | 25 total |
PRO | Unlimited |
BUSINESS | Unlimited |
ENTERPRISE | Unlimited |
A "heavy action" is any PDF tool run or a send-for-signature. Before it runs, QuotaService.checkAndConsume reloads the user, and on FREE at the limit it throws:
Free plan limit reached (25 uses). Upgrade to Pro for unlimited access.
Otherwise it increments the counter. Paid tiers short-circuit the check entirely.
Two ways to pay
Subscriptions
| Endpoint | |
|---|---|
GET /api/public/plans | The public plan catalog |
POST /api/payments/subscription-order | Create a Razorpay order for a plan |
POST /api/payments/verify-subscription | Verify payment → activate the subscription |
GET /api/subscriptions/my | The caller's current subscription |
A Subscription links a user to a PlanMaster, with a start / end date, the amount paid, a billing cycle, and a status. Cancellation records the time and reason.
One-time per-tool purchases
A FREE user who needs just one tool can buy lifetime access to that tool without a subscription:
| Endpoint | |
|---|---|
POST /api/payments/tool-order | Razorpay order for one toolKey |
POST /api/payments/verify-tool | Verify → write a ToolPurchase row |
GET /api/payments/my-tools · /my-purchases | What the user owns |
POST /api/payments/consume/{toolKey} | Use a purchased tool |
A ToolPurchase is unique per (user, toolKey) and records the amount in paisa, the currency, and the funding Razorpay payment id.
The plan catalog
PlanMaster rows are the catalog — a planKey (PRO_MONTHLY, PRO_YEARLY, …), a tier, a billing cycle, a price, a duration in days, and a JSON list of feature strings. A platform owner manages them from the admin console.
Razorpay webhook
POST /api/public/razorpay/webhook receives payment events out-of-band and is guarded by RAZORPAY_WEBHOOK_SECRET. With no Razorpay keys configured, the payment surface is disabled and tiers are managed by an admin directly.