Deployaar offers three billing plans managed through Razorpay. Plan limits are enforced server-side on every mutation insideDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/paramveer-cyber/Deployaar/llms.txt
Use this file to discover all available pages before exploring further.
packages/services/billing/limits.ts — there is no client-side trust. When a limit is exceeded, the server throws a FORBIDDEN error with an upgrade message explaining exactly what the current plan allows and that an upgrade is required.
Plan Comparison
| Feature | Free | Pro | Pro Max |
|---|---|---|---|
| Max Projects | 1 | 5 | 15 |
| Max Feature Requests | 3 | 25 | 100 |
| AI Providers | Google only | Google + OpenAI | Anthropic + OpenAI + Google + DeepSeek |
| Included Models | gemini-2.0-flash | gemini-1.5-pro, gpt-4o | All models (no restriction) |
| Price (INR) | Free | ₹1,499 | ₹2,999 |
PR review always uses Anthropic regardless of the active plan —
ANTHROPIC_API_KEY must be set in your environment even if you are on the Free plan and want AI-powered pull request review to work.Limit Enforcement
Before any project or feature request is created, Deployaar runs an async guard that queries the organization’s billing information, fetches the plan limits, and compares against the current usage count.assertProjectLimit(organizationId)
Called by the project.create tRPC procedure before inserting a new project row. It counts all existing projects in the organization and compares that number against planLimitsMap[plan].maxProjects.
If the limit is already reached, it throws:
assertFeatureRequestLimit(projectId)
Called by the featureRequest.create tRPC procedure before inserting a new feature request. It resolves the project’s parent organization and counts all feature requests across the organization, comparing against planLimitsMap[plan].maxFeatureRequests.
If the limit is already reached, it throws:
Upgrading
Upgrading from Free to Pro or Pro Max is a two-step flow:Create an Order
Call the
billing.createOrder tRPC procedure (or POST /billing/orders), passing the organizationId and targetPlan ("pro" or "pro_max"). The server creates a Razorpay order and returns the orderId, amount, currency, and keyId needed to open the Razorpay checkout widget in the browser.Complete Payment in the Browser
Open the Razorpay checkout widget using the values returned in step 1. When the user completes payment, Razorpay returns
razorpayOrderId, razorpayPaymentId, and razorpaySignature.POST /api/razorpay/webhook. The webhook handler verifies the payload signature using RAZORPAY_WEBHOOK_SECRET and processes the following events:
| Webhook Event | Action |
|---|---|
payment.captured | Upgrades plan to targetPlan, sets billing status to active |
payment.failed | Sets billing status to past_due |
subscription.cancelled | Sets billing status to inactive |
Model Access Enforcement
Before any AI call is dispatched,assertModelAllowedForOrg is called with the organization ID, the requested provider, and the requested model string. It resolves the plan limits and performs two checks:
-
Provider check — Is the requested provider string in
limits.allowedAiProviders? If not, throwsFORBIDDENwith a message like:Your Free plan does not include access to the "anthropic" provider. Upgrade to unlock more models. -
Model check — If
limits.allowedModelsis non-empty, is the requested model in that list? If not, throwsFORBIDDENwith a message like:Your Pro plan does not include access to model "claude-sonnet-4-6". Upgrade to unlock more models.
allowedModels: [] (an empty array), which the enforcement logic treats as no model restriction — all models for the allowed providers are accessible.
Plan Limits Code Reference
The canonical source of truth for all plan limits is theplanLimitsMap constant in packages/services/billing/limits.ts:
getLimitsForPlan(billingPlan: string): PlanLimits resolves a plan key to its limits object, falling back to planLimitsMap.free if an unrecognised plan string is encountered. This means unknown plan values always default to the most restrictive tier.
Checking the Current Plan
Thebilling.getCurrentPlan tRPC procedure (or GET /billing/{organizationId}) returns the full current plan state for an organization: