SaaS.Dev

Plans inside your App

How an Offer locks a feature, caps a count and prices each seat inside an App, and what each screen shows when a Customer's Offer moves.

An Offer decides what a Customer may do inside an App: which Verbs it grants, how far each goes, and what each seat costs. A Startup writes it once, as part of the definition.

What an Offer holds

Every gate in an App comes from one of these parts of the Offer the Customer holds.

PartFieldWhat it decides
Entitlementsone Offer.grant per Verbthe Verbs a Customer may call
Limiton an Entitlementhow many calls fit in a period, or in all time
At the boundatBoundwhat a call past the Limit gets: stop, overage or upgrade
Priceamount and unitwhat one unit costs: a call, a month, or a seat
Intervalintervalhow often it bills: once, day, week, month or year

An Entitlement bounded by a Limit has kind limit; one without has kind feature. The kind is computed, never set.

SaaS starts every Startup with two Offers in this shape:

OfferPriceFeaturesLimitsAt its bound
Starter (starter)$15 per seat, billed monthlyDashboard.askCollection.export: 10 per rolling dayupgrade to Pro
Pro (pro)$49 per seat, billed monthlyDashboard.ask, Collection.export, SSOConnection.activateNone.None.

Entitlement.check answers whether a Customer may call a Verb now, how much of its Limit remains, and which Offer lifts it. It changes nothing and never refuses.

What the App shows

A feature is a Verb the Offer grants, and a cap is the same grant with a Limit.

PlanOffers on screen

In the design, the App reads each Customer's Offer before every screen and every call. Every row below comes from the Offer, and the Startup writes no gating code for any of them.

The Customer hasThe App showsIt comes from
A feature on a higher Offerthe button, with a lock and the Offer that unlocks itan Entitlement with no Limit
A capped featurea usage bar, then the upgrade at the capan Entitlement with a Limit, and the Offer's atBound
A per-seat Offerseats used and paid, on the members screena Price whose unit is seat
A failed renewala banner to update the card, with everything still workinga Subscription in pastDue

A locked button stays in view, with the name of the Offer that unlocks it. Past the cap, the Verb refuses with 402 payment-required, naming the next Offer.

The same answer reaches the API and the MCP server. An Agent calling the App meets the same Offer as a person clicking it.

Seats

A per-seat Offer prices each person: its Price has the unit seat. Tenant.invite asks a person to join the Customer's Tenant. When no seat is free, it adds one through Subscription.resize, which prorates the current period.

Price per seat only when each extra person gets value of their own. leaseclock.com charges $15 a seat, but one manager often tracks 200 leases alone. So its starter Offer also bounds Lease.create at 50, with a Limit that never resets, and atBound: upgrade offers pro at the 51st.

PlanSeats on screen

In the design, the members screen shows seats used and seats paid. An invite past the paid count adds a seat, and the Customer pays the part-month charge through Stripe.

When the Offer moves

A change of Offer never deletes a record. Past a new cap, existing records stay readable and only new writes stop.

PlanOffer changes in the App

In the design, each move reaches the App on the next call.

MoveAccessMoney
Upgradethe new grants work on the next callthe prorated difference, charged at once
Downgradethe higher Offer holds to the end of the periodthe lower amount from the next period
Past a new capexisting records stay readable; new writes past the Limit get the upgradenone
Cancelfull access until the period closesnothing more
A failed chargefull access while retries runretried on the dunning schedule

The Customer updates the card and reads each invoice on Stripe, under the Startup's Brand.

Next

Contents