Skip to content

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

PropertyTypeRequiredDescription
pricemoneyrequiredThe amount, currency, and unit. Zero is a price. Never randomized.
termstextThe conditions the Customer accepts, refund rights included. Never randomized.
fromstringLineage: the slot it compiles from, as Hypothesis#<slot>@v<version>.
activationjsonThe Event, count and window that mark a Customer activated, such as Reminder.sent 20 times within 7 days.
creditmoneyThe Credit Grant each purchase issues, for an Offer that sells prepaid credit, such as $50 of calls.
atBoundstringWhat 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).
intervalstringHow often it bills: once, day, week, month or year.
availableFromdatetimeWhen it can first be bought. Unset: from when it is published.
availableUntildatetimeWhen it can last be bought. Existing Subscriptions continue past it.
trialjsonThe free trial every new Customer starts with: days, and card true to take a card up front. Unset: no trial.
seatsstringHow a per-seat Price counts: manual (the buyer sets the quantity) or members (people in the Customer’s Tenant, prorated as they change).
uptimejsonThe monthly uptime it promises, and the share of that month’s charge credited back below each level.
licensestringWhat a buyer may do with the records it sells: use them internally, display them to its own users, or redistribute them.
attributiontextThe credit line a buyer shows wherever the records appear.
privateToPartyThe one Party who sees it and may accept it, making it a private Offer; no pricing page lists it.

Object

JSON
{
  "$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:

OfferPriceFeaturesLimitsAt its boundOn sale
Starter (starter)$49 a monthDashboard.askCollection.query: 10,000 a calendar monthupgrade to FleetAlways
Fleet (fleet)$199 a monthCollection.export, Dashboard.askCollection.query: 100,000 a calendar monthoverageAlways
Route audit (route-audit)$499 onceNone.Document.render: 1 in all; Order.revise: 2 in allstop2026-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.

atBoundA call past the Limit
stopRefused: the Verb replies 402 payment-required.
overageAllowed: each unit past the Limit is billed through the Meter.
upgradeRefused 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, inverse accepts.
  • An Offer is branded by one Brand: each Offer carries exactly one Brand, whose name, voice and logo the buyer sees. brandedBy, inverse brands.
  • An Offer has many Coupons: a Coupon applies only to the Offers it names; an Offer may accept several Coupons. coupons, inverse discounts.
  • An Offer has many Funnels: each Funnel’s path ends at one Offer, after its landing Page, opt-in and Sequence. funnels, inverse leadsTo.
  • 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, inverse governs.
  • An Offer grants many Entitlements: an accepted Offer grants Entitlements, each a Verb on a Noun, optionally bounded by a Limit. grants, inverse grantedBy.
  • An Offer includes one Product: each Offer sells one Product; one Product sits inside many Offers at different prices and terms. includes, inverse includedIn.
  • An Offer is offered by one Startup: each Offer has one maker, which earns its revenue and answers for its terms. offeredBy, inverse offers.
  • An Offer is ordered in many Orders: an Order commits to buying one or more Offers once. orderedIn, inverse buys.
  • An Offer is priced at one Price: every Offer embeds one Price: amount, currency, unit and tiers; zero is a Price. pricedAt, inverse priceOf.
  • An Offer is promoted by many Ads: each Ad sells one Offer. promotedBy, inverse promotes.
  • An Offer is pursued in many Deals: a Deal asks one buyer to accept one or more Offers. pursuedIn, inverse pursues.
  • An Offer is quoted in many Quotes: a Quote prices one or more Offers for one buyer. quotedIn, inverse proposes.
  • An Offer has many Reviews: a Review evaluates one Offer; Reviews of a Product or Brand roll up through its Offers. reviews, inverse evaluates.
  • An Offer is sold in one Motion: each Offer sells through one Motion, which says who buys and who acts for them. soldIn, inverse sells.
  • An Offer has many Subscriptions: a Subscription bills one recurring Offer each Period until canceled. subscriptions, inverse renews.
  • An Offer targets many Personas: an Offer speaks to and is priced for named Personas. targets, inverse targetedBy.
  • An Offer has one Waitlist: a Waitlist admits its Leads to one Offer once that Offer opens. waitlist, inverse awaits.

Lifecycle

Offer lifecycle: draft, published, withdrawn (ends)draft → published: Offer.publishpublished → withdrawn: Offer.withdrawdraftpublishedwithdrawn
StateMeaningMoves to
draft (first)The Offer is being written: no party can see or accept it.published by Offer.publish
publishedParties can see the Offer, accept it and subscribe to it.withdrawn by Offer.withdraw
withdrawnThe Offer takes no new Customers; every Order and Subscription it made stays in force.None: it ends here.

Verbs

  1. createCreates an Offer.
    POST /{namespace}/offersdoOffer.created
  2. getReturns one Offer by id.
    GET /{namespace}/offers/{id}readNo Event
  3. listReturns Offers, newest first, one page at a time.
    GET /{namespace}/offersreadNo Event
  4. updateChanges the given properties of an Offer.
    PATCH /{namespace}/offers/{id}doOffer.updated
  5. deleteDeletes an Offer; its history is kept.
    DELETE /{namespace}/offers/{id}doOffer.deleted
  6. acceptAccept records that a party takes an Offer, which makes that party a Customer of the Startup.
    POST /{namespace}/offers/{offer}/acceptdoOffer.accepted
  7. grantGrant adds an Entitlement to an Offer: a Verb its Customers may call, optionally bounded by a Limit.
    POST /{namespace}/offers/{offer}/grantdoOffer.granted
  8. publishPublish makes an Offer available for parties to accept.
    POST /{namespace}/offers/{offer}/publishdoOffer.published
  9. subscribeSubscribe accepts a recurring Offer as a Subscription that renews each period until it ends.
    POST /{namespace}/offers/{offer}/subscribedoOffer.subscribed
  10. trialTrial 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}/trialdoOffer.trialed
  11. withdrawWithdraw closes a published Offer to new Customers and leaves every existing Order and Subscription in force.
    POST /{namespace}/offers/{offer}/withdrawdoOffer.withdrawn

Permissions

Which Access level may call each Verb. One-way Verbs wait their delay window.

Operationowneradminmemberviewer
Offer.createYesYesYesNo
Offer.getYesYesYesYes
Offer.listYesYesYesYes
Offer.updateYesYesYesNo
Offer.deleteYesYesYesNo
Offer.acceptYesYesYesNo
Offer.grantYesYesYesNo
Offer.publishYesYesYesNo
Offer.subscribeYesYesYesNo
Offer.trialYesYesYesNo
Offer.withdrawYesYesYesNo

Stripe

Product (product). The source of truth is db.sb, and Stripe holds a copy written from it.

PropertyStripe fieldSource of truth
pricedefault_pricedb.sb

Call it

Text
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.