Skip to content
Oclavex is in private preview, available to selected users. Public signup is blocked. Request access at [email protected].

Entitlements & offers

An entitlement is the central record: a customer’s grant to a product’s features, under a plan and a set of policies. Everything upstream (products, features, plans, add-ons) exists so you can issue good entitlements; everything downstream (activation, sessions, usage) flows from them.

  • Publication lifecycle — your editorial control; only a published entitlement can be activated. Draft and Published move freely in both directions. Disabling is deliberate: a published entitlement must be set back to Draft first — going straight from Published to Disabled is refused — and a disabled entitlement can be set back to Draft and re-published. Archived is final; in the portal only an offer can be archived. A Draft or archived offer is deleted once no Draft or Published entitlement made from it and no running rating campaign limited to it is left; an entitlement, which ends at Disabled, is deleted while it is Draft or Disabled and none of its activations still holds a license — disabling revokes them all. Once deleted, every route that names it by id answers 404, as for a deleted product or feature: GET …/entitlements/{id}, its policies, billing, activation codes and other parts, and every change to it; for an offer, also the entitlements made from it, its push and its promotion. The lookups by external reference and by billing anchor still find it, so a connector’s repeated event does not create it again.
  • Subscription status — Pending, Trialing, Active, Paused, PastDue (reserved), Expired, Canceled. The runtime state the customer experiences, computed from the entitlement’s policies and dates — except Paused, which is stored, not computed: pause/resume is a separate, reversible hold that blocks activation and consumption while keeping the record editable.

When a product is added to an entitlement, its features are copied in — a snapshot of the product as it is at that moment. The entitlement keeps its own copy, so later edits to the product don’t change a live customer’s grant. What a customer effectively has at any moment is that snapshot, plus any active add-on grants, plus the values from the assigned plan, resolved together.

Product Seats 5 · Export ✓ as it is on grant day Product — edited later Seats 5 → 10 the next new grant copies 10 time Entitlement its own copy: Seats 5 · Export ✓ later product edits don't reach it Session copied again: Seats 5 · Export ✓ the running license grant · features copied in activate · copied again ✕ never flows into existing grants What the customer effectively has = this snapshot + the assigned plan's values + active add-on grants.

The snapshot is the grant; the license is issued from it each time a device activates or refreshes. A feature whose catalog entry is Draft, Disabled or Archived stays in the snapshot but is left out of the license. So an entitlement or offer carrying a Draft feature is still published, ordered and activated, and once you publish the feature it reaches every holder at their next refresh.

An entitlement licenses the products of one suite — the group of products you sell together. Assigning the suite is what puts products on the entitlement: every product in it is licensed, every product’s features go into the snapshot, and the plan you apply is one of that suite’s plans.

Most grants are for a single product, and that works the same way: pricing a product creates a suite holding just it, so a one-product entitlement is a suite of one. There is one mechanism to learn, not two.

Changing the suite replaces the products with the new suite’s products, and clears the plan — the new suite’s plans are not the old one’s, so the earlier choice cannot carry over.

Policies decide how the entitlement may be activated and for how long — they combine:

  • Seat allocation — fixed or floating seats, with a lease and offline grace.
  • Trial — a trial window, optionally starting on first activation.
  • Time-restricted — valid between two dates, or for a period after first use.
  • Subscription — recurring periods with renewal and expiry.
  • Anonymous try — on an offer only: the terms visitors are issued an entitlement under, with no account. See Try activation.

An offer is a saved template (products, features, policies) you author once and turn into entitlements repeatedly, instead of filling in every field per customer — it is what your orders start from. Offers are internal to your catalog: an end user never sees one, only what was ordered from it.

An offer has no customer. The organization, contact details, order number and references belong to the entitlement, and you supply them when you order one — so the same offer serves every customer, and saving an existing entitlement as an offer leaves that customer’s details behind.

The license terms URL (EULA) set on an offer is copied onto each entitlement ordered from it, like every other offer field, so changing it on the offer later doesn’t reach entitlements already ordered. An entitlement’s own link can be changed for one customer. The application receives the entitlement’s link with its license, and the customer sees it as a License terms link on their license page in the user portal.

An offer takes orders, sign-ups and subscriptions only while it is Published. A new offer is saved as Draft, which means it is not open to orders yet; a Disabled or Archived offer no longer is. An order from an offer in any of those states is refused with license.offer_not_orderable, and nothing is created.

Each entitlement made from an offer records which one: an order, a sign-up, a Stripe or Salesforce subscription and a try alike. The offer’s Entitlements tab lists them. An entitlement made before that was recorded can be linked to its offer from its Order details. In the API, originOfferId on the entitlement names the offer, and the list takes the filter OriginOfferId==<offer id>. An offer’s policies stay editable while it is Published: a change reaches the entitlements ordered afterwards, and the ones already made keep theirs.

The same link decides who a rating campaign asks. A campaign’s offerIds limit it to the customers whose entitlement was made from one of those offers; an empty list asks every customer, and an entitlement made from no offer is asked only by such a campaign. GET …/rating-campaigns?offerId=<offer id> lists the campaigns that name an offer.

An entitlement deviates from its offer when a change was made to that customer alone since it was made: its plan changed (by an admin, an approved plan-change request, or the billing subscription), or an add-on the offer gave it was revoked, or one was added that the offer did not give. Customer changes win over the offer. The offer’s Entitlements tab says which entitlements deviate and why, and GET …/entitlements/offers/{offerId}/entitlements returns the same list with a deviations entry per changed part.

An offer’s plan and add-ons are pushed to the entitlements made from it only when you ask: a change reaches the next order, never an existing entitlement by itself. A push gives each entitlement the offer’s plan and add-ons and revokes the add-ons the offer no longer gives. Deviating entitlements are skipped unless the push includes them; then the offer wins over the customer’s change, except that an add-on added for that customer alone stays. A running temporary plan override of the entitlement’s own (a trial, a lapsed payment, one set for that customer) is never ended by a push, so that entitlement is skipped until it ends. What a push set is the offer’s again, so it no longer counts as a deviation. In the API, POST …/entitlements/offers/{offerId}/push?dryRun=true previews the counts and the deviating list, and the same call without dryRun applies it; includeDeviating in the body includes the deviating ones. An entitlement the push cannot change is listed under failed with the reason, and the others are changed all the same. Each changed entitlement gets an audit entry and sends the usual webhooks: Entitlement.PlanApplied, Entitlement.AddOnGranted and Entitlement.AddOnRevoked.

An offer can carry a promotion: a plan for a limited time, from startsAt to endsAt, optionally under a campaign. It changes nothing on the offer itself. While it runs, each new order from the offer gets it as a temporary plan override that ends on endsAt, with a plan-override touch of its campaign. An order that will start on a trial plan, an anonymous try, an entitlement a billing provider’s subscription makes and the platform’s own subscriptions do not get it. Its plan comes from the offer’s suite and is not the offer’s own plan. A push gives it to the entitlements already made from the offer only with includePromotion in the body; it replaces a promotion the same offer gave earlier, and never any other temporary override, so an entitlement on a trial, a lapsed payment or an override of its own is skipped. One whose trial is still to start or whose lapse is pending gets the rest of the push without the promotion. A promotion’s reason cannot be one the platform keeps for its own overrides (payment-lapsed, trial-policy-auto-apply, self-service-signup-trial). While a promotion of its offer runs on an entitlement, a push of the offer’s plan makes that plan the one the promotion returns to. A promotion ended for one customer before its end date makes that entitlement deviate (facet Promotion). In the API, PUT …/entitlements/offers/{offerId}/promotion sets or replaces it and DELETE …/entitlements/offers/{offerId}/promotion removes it; the offer carries it as promotion, and an entitlement holding one has temporaryOverride.sourceOfferId set to the offer. An offer takes no temporary override of its own: POST …/entitlements/{offerId}/temporary-override is refused for one.

Two settings let a Published offer issue by itself, without anyone in your team ordering from it. Automatic user issuance gives every user their own entitlement when they confirm their email address. Anonymous try gives every visiting device a short-lived one with no account at all, deleted once it expires or once that visitor signs up. Neither survives a copy of the offer: an offer you duplicate issues nothing until you say so.

On an entitlement, two reference fields keep it linked to your other systems: externalReference for the grant itself (scheme:type:id, e.g. crm:order:4711) and customerExternalReference for the owning account. Neither is enforced unique — keep them one-to-one yourself.

Billing has a record of its own on the entitlement: who bills it (a Stripe connector, you by invoice, or nobody), how and how often, the invoice contact, the customer’s purchase-order reference, and — written by the connector — the provider’s subscription and customer ids and the state the subscription last reported. An offer carries the billing method as the template for the entitlements ordered from it; the contact and the subscription ids never come from an offer. See Billing for the modes a record can be in, and Stripe for what the connector writes there.