Offer
An Offer is a Product, under a Brand, at a price, on terms, made by a Startup.
An Offer is a Product, under a Brand, at a Price, on terms, made by a Startup. One Product sells as many Offers, and a Customer accepts an Offer, never a Product.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
price | money | required | The amount, currency, and unit. Zero is a price. Never randomized. |
terms | text | The conditions the Customer accepts, refund rights included. Never randomized. | |
from | string | Lineage: the slot it compiles from, as Hypothesis#<slot>@v<version>. | |
activation | json | The Event, count and window that mark a Customer activated, such as Reminder.sent 20 times within 7 days. | |
credit | money | The Credit Grant each purchase issues, for an Offer that sells prepaid credit, such as $50 of calls. | |
atBound | string | What a call past an Entitlement’s Limit gets: stop, overage or upgrade (refuse it, bill it through the Meter, or move to the next Offer). | |
interval | string | How often it bills: once, day, week, month or year. | |
availableFrom | datetime | When it can first be bought. Unset: from when it is published. | |
availableUntil | datetime | When it can last be bought. Existing Subscriptions continue past it. | |
trial | json | The free trial every new Customer starts with: days, and card true to take a card up front. Unset: no trial. | |
seats | string | How a per-seat Price counts: manual (the buyer sets the quantity) or members (people in the Customer’s Tenant, prorated as they change). | |
uptime | json | The monthly uptime it promises, and the share of that month’s charge credited back below each level. | |
license | string | What a buyer may do with the records it sells: use them internally, display them to its own users, or redistribute them. | |
attribution | text | The credit line a buyer shows wherever the records appear. | |
privateTo | Party | The one Party who sees it and may accept it, making it a private Offer; no pricing page lists it. |
Object
{
"$id": "https: //api.sb/ petpantry.shop/ offers/ offer_1",
"$type": "Offer",
"price": {
"amount": 54,
"currency": "USD"
},
"terms": "Full refund within 14 days of purchase. Delivery in 2 business days.",
"from": "Hypothesis#approach@v1",
"activation": {},
"credit": {
"amount": 54,
"currency": "USD"
},
"atBound": "stop",
"interval": "once",
"availableFrom": "2026-10-22T12: 00: 00Z",
"availableUntil": "2026-10-22T12: 00: 00Z",
"trial": {
"days": 14,
"card": true
},
"seats": "manual",
"uptime": {
"target": 99.9,
"credits": [
{
"below": 99.9,
"percent": 10
},
{
"below": 99,
"percent": 25
}
]
},
"license": "internal",
"attribution": "Renewal data from Leaseline",
"privateTo": "party_1"
}Anatomy
RouteWise (routewise.dev), a sample business, sells three Offers:
| Offer | Price | Features | Limits | At its bound | On sale |
|---|---|---|---|---|---|
Starter (starter) | $49 a month | Dashboard.ask | Collection.query: 10,000 a calendar month | upgrade to Fleet | Always |
Fleet (fleet) | $199 a month | Collection.export, Dashboard.ask | Collection.query: 100,000 a calendar month | overage | Always |
Route audit (route-audit) | $499 once | None. | Document.render: 1 in all; Order.revise: 2 in all | stop | 2026-11-01 to 2027-01-31 |
An Entitlement bounded by a Limit has kind limit; one without has kind feature. The kind is computed, never set.
atBound | A call past the Limit |
|---|---|
stop | Refused: the Verb replies 402 payment-required. |
overage | Allowed: each unit past the Limit is billed through the Meter. |
upgrade | Refused with 402 payment-required, naming the next Offer, which Entitlement.check returns as upgrade. |
Offer.publish puts each Offer on every buy surface: checkout, paymentLink, pricingTable, portalEntry, mcpBuyTool, http402.
Relationships
- An Offer is accepted by many Customers: a party becomes a Customer by accepting any Offer, at any price including zero.
acceptedBy, inverseaccepts. - An Offer is branded by one Brand: each Offer carries exactly one Brand, whose name, voice and logo the buyer sees.
brandedBy, inversebrands. - An Offer has many Coupons: a Coupon applies only to the Offers it names; an Offer may accept several Coupons.
coupons, inversediscounts. - An Offer has many Funnels: each Funnel’s path ends at one Offer, after its landing Page, opt-in and Sequence.
funnels, inverseleadsTo. - An Offer is governed by one Outcome Contract: an Outcome Contract warrants the result an Offer sells: its done state, acceptance, assurance and remedy.
governedBy, inversegoverns. - An Offer grants many Entitlements: an accepted Offer grants Entitlements, each a Verb on a Noun, optionally bounded by a Limit.
grants, inversegrantedBy. - An Offer includes one Product: each Offer sells one Product; one Product sits inside many Offers at different prices and terms.
includes, inverseincludedIn. - An Offer is offered by one Startup: each Offer has one maker, which earns its revenue and answers for its terms.
offeredBy, inverseoffers. - An Offer is ordered in many Orders: an Order commits to buying one or more Offers once.
orderedIn, inversebuys. - An Offer is priced at one Price: every Offer embeds one Price: amount, currency, unit and tiers; zero is a Price.
pricedAt, inversepriceOf. - An Offer is promoted by many Ads: each Ad sells one Offer.
promotedBy, inversepromotes. - An Offer is pursued in many Deals: a Deal asks one buyer to accept one or more Offers.
pursuedIn, inversepursues. - An Offer is quoted in many Quotes: a Quote prices one or more Offers for one buyer.
quotedIn, inverseproposes. - An Offer has many Reviews: a Review evaluates one Offer; Reviews of a Product or Brand roll up through its Offers.
reviews, inverseevaluates. - An Offer is sold in one Motion: each Offer sells through one Motion, which says who buys and who acts for them.
soldIn, inversesells. - An Offer has many Subscriptions: a Subscription bills one recurring Offer each Period until canceled.
subscriptions, inverserenews. - An Offer targets many Personas: an Offer speaks to and is priced for named Personas.
targets, inversetargetedBy. - An Offer has one Waitlist: a Waitlist admits its Leads to one Offer once that Offer opens.
waitlist, inverseawaits.
Lifecycle
| State | Meaning | Moves to |
|---|---|---|
draft (first) | The Offer is being written: no party can see or accept it. | published by Offer.publish |
published | Parties can see the Offer, accept it and subscribe to it. | withdrawn by Offer.withdraw |
withdrawn | The Offer takes no new Customers; every Order and Subscription it made stays in force. | None: it ends here. |
Verbs
createCreates an Offer.POST /{namespace}/offersgetReturns one Offer by id.GET /{namespace}/offers/{id}listReturns Offers, newest first, one page at a time.GET /{namespace}/offersupdateChanges the given properties of an Offer.PATCH /{namespace}/offers/{id}deleteDeletes an Offer; its history is kept.DELETE /{namespace}/offers/{id}acceptAccept records that a party takes an Offer, which makes that party a Customer of the Startup.POST /{namespace}/offers/{offer}/acceptgrantGrant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit.POST /{namespace}/offers/{offer}/grantpublishPublish makes an Offer available for parties to accept.POST /{namespace}/offers/{offer}/publishsubscribeSubscribe accepts a recurring Offer as a Subscription that renews each period until it ends.POST /{namespace}/offers/{offer}/subscribetrialTrial starts a Customer on an Offer free for a set number of days, with or without a card, converting or ending by its terms.POST /{namespace}/offers/{offer}/trialwithdrawWithdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force.POST /{namespace}/offers/{offer}/withdraw
Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.
| Operation | owner | admin | member | viewer |
|---|---|---|---|---|
Offer.create | Yes | Yes | Yes | No |
Offer.get | Yes | Yes | Yes | Yes |
Offer.list | Yes | Yes | Yes | Yes |
Offer.update | Yes | Yes | Yes | No |
Offer.delete | Yes | Yes | Yes | No |
Offer.accept | Yes | Yes | Yes | No |
Offer.grant | Yes | Yes | Yes | No |
Offer.publish | Yes | Yes | Yes | No |
Offer.subscribe | Yes | Yes | Yes | No |
Offer.trial | Yes | Yes | Yes | No |
Offer.withdraw | Yes | Yes | Yes | No |
Stripe
Product (product). The source of truth is db.sb, and Stripe holds a copy written from it.
| Property | Stripe field | Source of truth |
|---|---|---|
price | default_price | db.sb |
Call it
Publish the offer “RouteWise API”.Example
A dental bookkeeping Startup sells one Product as two Offers: $600 a month for monthly closes, or $2,400 once for catch-up books. Both carry its one Brand.