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.
| Part | Field | What it decides |
|---|---|---|
| Entitlements | one Offer.grant per Verb | the Verbs a Customer may call |
| Limit | on an Entitlement | how many calls fit in a period, or in all time |
| At the bound | atBound | what a call past the Limit gets: stop, overage or upgrade |
| Price | amount and unit | what one unit costs: a call, a month, or a seat |
| Interval | interval | how 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:
| Offer | Price | Features | Limits | At its bound |
|---|---|---|---|---|
Starter (starter) | $15 per seat, billed monthly | Dashboard.ask | Collection.export: 10 per rolling day | upgrade to Pro |
Pro (pro) | $49 per seat, billed monthly | Dashboard.ask, Collection.export, SSOConnection.activate | None. | 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 has | The App shows | It comes from |
|---|---|---|
| A feature on a higher Offer | the button, with a lock and the Offer that unlocks it | an Entitlement with no Limit |
| A capped feature | a usage bar, then the upgrade at the cap | an Entitlement with a Limit, and the Offer's atBound |
| A per-seat Offer | seats used and paid, on the members screen | a Price whose unit is seat |
| A failed renewal | a banner to update the card, with everything still working | a 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.
| Move | Access | Money |
|---|---|---|
| Upgrade | the new grants work on the next call | the prorated difference, charged at once |
| Downgrade | the higher Offer holds to the end of the period | the lower amount from the next period |
| Past a new cap | existing records stay readable; new writes past the Limit get the upgrade | none |
| Cancel | full access until the period closes | nothing more |
| A failed charge | full access while retries run | retried on the dunning schedule |
The Customer updates the card and reads each invoice on Stripe, under the Startup's Brand.
Next
- Charge per seat: the ask for a per-seat Offer.
- Anatomy of an Offer: every field an Offer holds.
- Checking access: the check behind every gate.
- Recurring billing: proration, pauses and retries.