Skip to content
BuildBase

Managing Subscriptions from the Console

Change a plan, comp it, extend or end a trial, apply a discount, pause or re-sync a subscription for a customer, from the console or the admin API.

When a customer asks for a longer trial, a discount or a free month, your team can do it from the BuildBase console instead of the Stripe dashboard. Open User management > Workspaces > Workspaces and the workspace's row, or, for a person's own plan, the Billing tab of their user record, and use its Actions menu. Every action follows the same rules as a change the customer makes. It's recorded in the subscription's history, with who did it and why.

curl -X POST https://api.console.buildbase.app/api/subscriptions/actions/trial/extend \
  -H "Authorization: $BUILDBASE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "66f0c1d2e3a4b5c6d7e8f901",
    "trialEnd": "2026-11-30T23:59:59Z",
    "reason": "Waiting on their security review"
  }'

Each menu item is also a route under /api/subscriptions/actions/, so your own internal tools can do the same with an org API token. See Admin API for tokens.

Before you start

To use the menu, a console role needs create on the stripe_subscription_actions resource. It's a permission of its own, so a support role can read every subscription without being able to comp one (give it for free). Grant it under Settings > Roles. Checkout link also needs create on subscription_plan_versions, which its route checks.

Act on a subscription, step by step

Open workspaces in the console (opens the console in a new tab)

1. Open the workspace

In the left rail choose Users, then Workspaces under Workspaces. The list shows each workspace's Subscription; press View on the one you want. The Billing > Subscriptions list does not link to the workspace, so start here.

The Workspaces list with Jordan Lee's Workspace, active on Pro, paying in USD, and the View button highlighted as step 1

2. Open the Actions menu

On the workspace page, the Subscription card shows the plan, its status and what it includes. Press Actions. An action the subscription's state does not allow is greyed out, with the reason under it.

The Subscription card for Pro, Active, with the Actions menu open: Change plan, Comp plan, Extend trial and End trial now greyed out (Only while the subscription is on a trial), Reset trial eligibility, Apply discount, Remove discount greyed out, Cancel at period end, Cancel now, Resume, Pause, End pause, Re-sync from Stripe and Grant an item, and the Actions button highlighted as step 2

3. Change plan

Choose the Plan, its Version and the Billing interval, and press Preview the change: Stripe works out what is due today and the next invoice. Give a Reason and press Change plan. Only plans in the workspace's pricing group are accepted.

Change the plan: Plan Pro, Version 1 (v1, current), Billing interval Yearly, the preview Due today $261.01 highlighted as step 3 with Next invoice $290.00 on Nov 3, 2027, a reason, and the Change plan button

4. Comp plan

For how long is Until it is removed or a number of months; a comp shorter than the billing interval is not offered. Give a Reason and press Comp plan.

Comp the plan: A 100% coupon on the whole subscription to Pro, For how long Until it is removed highlighted as step 4, a reason, and the Comp plan button

5. Apply discount

Under Apply choose A coupon or A promotion code, then the Coupon or the code. When the subscription already holds a discount, Replace them swaps them for the new one; off, the new one sits beside them. Give a Reason and press Apply discount. Stripe takes it off from the next invoice; nothing is charged now.

Apply a discount: Apply A coupon, Coupon Launch week (20% off, 3 months) highlighted as step 5, a reason, and the Apply discount button

6. Cancel at period end

The workspace keeps its plan until the paid period ends; nothing is refunded, and Resume undoes it until then. Pick the Customer's reason (sent to Stripe), give your Reason and press Cancel at period end.

Cancel at the end of the period: the workspace keeps its plan until Dec 3, 2026, Customer's reason highlighted as step 6, a reason, and the Cancel at period end button

7. Cancel now

What the customer gets back starts on your setting under Settings > General, card Cancellation. Stripe ends the subscription at once and sends a final invoice for usage not billed yet; it cannot be resumed. Press End now.

End the subscription now: What the customer gets back, Nothing back for the unused time (your setting), highlighted as step 7, Customer's reason, a reason, and the End now button

8. Pause

Choose how many Months. The pause starts when the paid period ends; nothing is billed and the plan stops working until it ends. End pause ends it early.

Pause the subscription: the workspace keeps its plan until Dec 3, 2026, Months 1 month highlighted as step 8, a reason, and the Pause button

9. Re-sync from Stripe

When the console and Stripe disagree, Re-sync from Stripe reads the subscription from Stripe and writes it here, as Stripe's own update event would. Nothing changes in Stripe, and the reason is optional.

Re-sync from Stripe: Reads the subscription from Stripe now and writes it here, an optional reason, and the Re-sync button highlighted

10. Grant an item

Choose the Item, how much (here Units a month for a quota, or Unlimited), an optional Ends on date and a Reason, and press Grant. A plan change keeps the grant; to give a whole plan, comp it instead.

Grant an item: Item Reports per month (Quota) highlighted as step 10, Units a month 1, Unlimited, Ends on, a reason, and the Grant button

For a workspace with no Stripe subscription, Checkout link makes a Stripe Checkout page for the plan you choose. Choose the Plan, its Version, the Currency when the version has more than one, and the Billing interval, and press Create link. Copy the link with Copy and send it to the customer yourself: BuildBase does not email it. When they pay, the subscription starts as if they had subscribed from your app.

Send a checkout link: Plan Pro, Version 3 (v3, current), Currency EUR and Billing interval Monthly, the link created, and the Copy button highlighted as step 11

  • Only plans sold to workspaces are offered. A person checks out only as themselves, from their own billing page, so a person's record has no Checkout link.
  • A plan you archived is refused with "This plan is no longer offered. Choose another plan." Unarchive it first. A version in no pricing group, such as one written for a single deal, still gets a link.
  • The link works for 24 hours. A new link for the workspace closes any earlier one, so send only the newest.
  • After paying, the customer returns to your app: the page set under Settings > General, card After checkout, else your app's own address. When you have neither, the dialog says the customer lands on a default page.

The same link is POST /api/organizations/payment/stripe/checkout/create-session with workspaceId, planVersionId, and optionally billingInterval, currency, successUrl and cancelUrl.

Check that it worked

Each action adds a row to the workspace's Subscription history, with what changed, who did it, from where, and the reason.

Subscription history: Subscription Resynced, Re-synced from Stripe, and Discount Applied, Applied coupon with the reason Launch week offer, agreed by email, both by Alex Morgan from the Admin-Console

A person's own plan has the same Actions on the Billing tab of their user record.

The actions

Each menu item does one thing to the subscription. The route is the same action over the API.

Menu itemRouteWhat it does
Change planchange-planMoves the subscription to another plan version exactly as the customer's own change would: an upgrade is charged now, a downgrade waits for the end of the period
Comp plancompGives the plan for free: a 100% coupon on a real Stripe subscription, forever or for 1 to 36 months
Extend trialtrial/extendMoves the trial's end later, at most 365 days out. Nothing is invoiced
End trial nowtrial/endEnds the trial. With a card on file, the plan is billed and goes active. Without one, it ends as the plan's trial settings say
Reset trial eligibilitytrial/reset-eligibilityLets the customer trial again. The person is the workspace's owner unless userId names someone else
Apply discountdiscount/applyAdds a coupon (couponId) or a promotion code (promotionCode). It sits beside the subscription's other discounts, or replaces them with replace
Remove discountdiscount/removeRemoves one discount. discountId names it when there are several
Cancel at period endcancelCancels when the paid period ends. Nothing is refunded
Cancel nowcancel-nowEnds the subscription at once, and it cannot be resumed. Stripe sends a final invoice for usage not billed yet. refund is none, prorated_credit or prorated_refund; left out, your choice under Settings > General, card Cancellation applies, and the menu starts on it. See Ending a subscription now
ResumeresumeUndoes a cancellation before the period ends
PausepausePauses a monthly subscription for months, starting when the paid period ends. Works even if you don't let customers pause
End pauseunpauseEnds a pause now
Re-sync from StriperesyncReads the subscription from Stripe and updates BuildBase to match, using the same handler a Stripe webhook runs. Nothing is written to Stripe
Checkout link/api/organizations/payment/stripe/checkout/create-sessionMakes a Stripe Checkout link for a workspace with no Stripe subscription, for you to send. Paying it starts the subscription. A person can't be sent one (SELF_CHECKOUT_ONLY)
Grant an item/api/subscriptions/grantsGives a feature, a limit or more quota on top of the plan. See Operator grants

Every route under /api/subscriptions/actions/ takes:

  • workspaceId, or subject: { "type": "user", "id": "..." } for a person's own plan
  • a reason of up to 500 characters, required on all but Resume, End pause and Re-sync

You can't comp a person who has no plan yet (SELF_CHECKOUT_ONLY). A person's own plan only starts with a checkout they do themselves, so comp a plan they already hold.

Before you change a plan

Check the cost first. change-plan/preview shows what a change would charge before anything moves. It's the same preview the customer sees: what's due today, the next invoice, and for a downgrade, the date it takes effect. Send its prorationDate back on change-plan, and the change is charged exactly as the preview showed.

To move a subscriber onto a newer version of the same plan, change their plan to it here. A coupon limited to that plan keeps applying after the move.

Comps

A comp gives a customer a paid plan for free. It's always a real Stripe subscription with a 100% coupon, never a paid plan with nothing in Stripe behind it.

  • On a workspace that already pays, the comp coupon replaces every discount it had, and the history names the ones it replaced.
  • On a workspace with no plan, or on Free, it creates the subscription with the coupon and no card. Stripe makes it active, with a paid invoice of zero.

Until it ends, a comp covers the whole subscription: seats, metered overage (usage billed past the plan's allowance) and recurring add-ons included. A comp shorter than the plan's billing interval, such as six months on a yearly plan, would end before the next invoice it could cover, so it's refused with COMP_SHORTER_THAN_INTERVAL.

What the guard refuses

The rules about a subscription's state apply to your team just as they do to the customer, and there's no way around them. Two refusals come up most:

  • Two changes at once. A subscription takes one change at a time. A change that waits more than a few seconds for another to finish is refused with 409 SUBSCRIPTION_BUSY.
  • A change still waiting on its payment. Say an upgrade is waiting for the customer to confirm the payment with their bank (3-D Secure). Until it's paid, a plan change, a trial extend or end, a discount and a comp are all refused with 409 SUBSCRIPTION_PENDING_UPDATE. Otherwise Stripe would throw the waiting change away and void its invoice. Cancel and resume still go ahead.

See Error codes.

The history

Every action writes one row to the subscription's history: the action, whether it came from the console or the API, the person or token that took it, and the reason. The workspace's subscription card shows it, and GET /api/subscriptions/logs/workspace/:workspaceId reads it.

What you do sends the same notices as the customer's own change would:

  • an extended trial sends subscription.trial_extended, by email, push, webhook and Slack
  • a discount applied or removed sends subscription.discount_applied or subscription.discount_removed to your webhooks

There are 239 events in the catalog.

The other billing screens

The console's billing area has more for support and finance:

  • Revenue - monthly recurring revenue (MRR), customers by status, churn, trial conversion and cash, from your own data. See Revenue and billing health.
  • Grants - what each workspace and person holds beyond its plan, with revoke and refund. See Add-ons.
  • Coupons - coupons and promotion codes. See Promotion codes.
  • Credit ledger - every credit purchase, spend, grant, expiry and refund, with the balance after it. See Credits.
  • Payment webhooks - each Stripe event your account sent, with its customer and amount. Check Stripe setup under Billing > Credentials finds the events your endpoint misses. See Failed payments.

Next steps

  • Failed payments - Chasing a failed payment (dunning), the card-expiring notice and Stripe's recovery switches.
  • Add-ons - Refunds and grants.
  • Billing overview - What the customer sees on their side.