Skip to content

Plans

The admin plans page is not a public pricing editor.

In the shipped template, it manages one specific operational setting:

  • AI credits quota override per billing plan

GET /api/admin/plans combines:

  • static plan definitions from server/config/plans.ts
  • local billing-plan rows from the database

The result shows, for each plan:

  • planKey
  • display name
  • Stripe product ID if present
  • active status
  • explicit creditsQuota override, if any
  • default credits quota from the codebase
  • effective quota actually used by the app

PATCH /api/admin/plans/[planKey] updates:

  • the plan’s explicit creditsQuota

Setting it to null resets the plan back to the built-in default from plans.ts.

This is the important part: changing a plan quota is not just a config write.

The current implementation also recalculates affected credits wallets:

  • free plan override affects wallets for orgs without an operable paid subscription
  • paid plan override affects wallets for orgs currently on that paid plan

For affected organizations, the endpoint updates wallet state immediately, but not all changes take effect the same way:

  • quota increases apply immediately
  • quota decreases are deferred by keeping the current monthlyQuota and writing the lower value into pendingMonthlyQuota

That means existing subscribers get more credits right away after an upgrade, but a downgrade does not cut the current cycle short. The lower quota takes effect on the next credits reset.

This matches the shipped template behavior used elsewhere in billing:

  • subscription upgrades immediately raise the effective quota
  • subscription downgrades stay on the current quota until the next wallet reset

So if you are documenting this for operators, describe downgrades as “effective next reset” rather than “effective immediately.”

This page does not currently:

  • create new plan keys
  • change public pricing copy
  • edit Stripe recurring price IDs
  • move customers between plans directly

Those are separate concerns handled elsewhere.