/admin/pricing) to manage plans, features, and FAQs.
Plan list
The pricing page shows all plans ordered bysort_order, with stats for total plans, active plans, total features, and total FAQs. Each plan card displays its name, monthly and yearly price, subscriber count, and active/inactive status.
Creating a plan
Fill in core details
| Field | Required | Notes |
|---|---|---|
| Name | Yes | Displayed to customers. Supports multiple locales (stored as JSON). |
| Slug | Yes | URL-safe identifier, must be unique. Auto-generated from name if left blank. |
| Description | Yes | Short description shown on the pricing page. |
| Monthly price | Yes | In dollars (e.g. 29). Stored internally in cents. Enter 0 for free plans. |
| Yearly price | No | In dollars. Stored internally in cents. Leave blank if no annual billing. |
| Seats | No | Maximum number of seats for the plan. |
| Sort order | Yes | Determines display order. Lower = earlier. |
| Active | — | Toggle to make the plan visible and available to subscribe. |
| Popular | — | Highlights the plan with a “Popular” badge on the pricing page. |
| Enterprise | — | Marks the plan as an enterprise tier. |
| Discount text | No | Short label shown near the price (e.g. “Save 20%”). |
Set feature values
Every feature defined in the system must have a value for this plan. See Feature quotas below.
Feature quotas
Features are defined in thefeatures table and linked to plans via the plan_feature_values pivot table. Each feature has a slug that the application uses to enforce quota limits at runtime.
Quota fields on a plan
When creating or editing a plan, the following quota fields are available directly:| Field | Feature slug | Description |
|---|---|---|
| Agents quota | agents | Maximum number of AI agents the customer can create |
| Knowledge base quota | knowledge_bases | Maximum knowledge bases |
| Phone numbers quota | phone_numbers | Maximum phone numbers that can be imported |
| Batch calls quota | batch_calls | Maximum concurrent or total batch calling jobs |
| Voice design quota | voice_design | ElevenLabs voice design credits |
| Instant voice clone quota | instant_voice_clone | Instant voice clone slots |
| Conversational AI minutes | conversational_ai_minutes | ElevenLabs Conversational AI minutes per billing period |
Feature record in the database via the feature_values array. Set the value to 0 to deny access to a feature, or a positive integer to allow that many units.
Free plans
A plan is considered free when its monthly price (price field in cents) is 0. Free plans:
- Do not require Stripe product/price IDs.
- Are excluded from gateway sync operations.
- Still enforce feature quotas.
Editing a plan
Click the edit icon on a plan card. The form is identical to the creation form. If the monthly or yearly price is changed, the corresponding Stripe prices are updated automatically. Feature values are replaced in full on save — all existingPlanFeatureValue records for the plan are deleted and recreated from the submitted form data.
Enabling and disabling plans
Toggle the Active switch on the plan form, or use the quick-toggle action on the plan card. Inactive plans are hidden from the public pricing page and cannot be subscribed to. Existing subscriptions on an inactive plan are not affected.Deleting a plan
Click Delete on the plan card. If the plan has astripe_product_id, the Stripe product is archived first.
Gateway sync
Sync pushes plan pricing to all active payment gateways (Stripe, Razorpay, Paystack). Free plans (price 0) are skipped automatically.Sync a single plan
Click Sync to gateways on a plan card. The system iterates over all activePaymentProvider records and calls the appropriate gateway SDK:
Stripe sync
Stripe sync
Creates or updates a Stripe Product with the plan name and description. Creates monthly and yearly Price objects if the respective prices are > 0. Stores the resulting IDs in
stripe_product_id, stripe_monthly_price_id, and stripe_yearly_price_id.Razorpay sync
Razorpay sync
Creates Razorpay Plans for monthly and yearly billing cycles. Razorpay credentials are validated before syncing — if the account is not activated or KYC is incomplete, the sync will fail with a descriptive error.
Paystack sync
Paystack sync
Creates Paystack plans for monthly and yearly billing cycles. Stores plan codes in
paystack_monthly_plan_code and paystack_yearly_plan_code.Sync all plans
Click Sync all plans on the pricing index page to sync every active paid plan across all active payment providers in one operation.Check sync status
Use Check sync status to see which plans are missing gateway IDs and need to be synced.Payment provider IDs stored per plan
| Provider | Fields on pricing_plans table |
|---|---|
| Stripe | stripe_product_id, stripe_monthly_price_id, stripe_yearly_price_id |
| Razorpay | razorpay_monthly_plan_id, razorpay_yearly_plan_id |
| Paystack | paystack_monthly_plan_code, paystack_yearly_plan_code |
FAQ management
The pricing page also manages FAQs displayed on the public pricing page.Reorder FAQs
Drag and drop FAQ rows or use the reorder endpoint to submit a new
sort_order for each FAQ.