Version

Plans API

A plan is what a project sells: the price, the currency, the billing cycle or the dated windows, the eligibility rules and the resources a purchase unlocks.

A plan is what a project sells: the price, the currency, the billing cycle or the dated windows, the eligibility rules and the resources a purchase unlocks. Every plan has a kind that decides its whole shape. A subscription renews on a cycle and carries a billing block; a pass sells one dated access window per purchase and carries a pass block; a pass_series sells a slate of other pass plans' windows in one go and carries a pass_series block. The kind names exactly one block, and the other two are absent.

A plan exists and, separately, is on sale. Publish and unpublish flip active and are how intake is paused while the plan stays on the books and editable; delete removes the row, and is refused while a customer still holds an unfinished window. A sales_cap pauses the plan by itself when it fills, eligibility narrows who may buy, resources are the places the plan grants, and the storefront order and a series' next season are actions of their own. Plans live under a project at /v1/projects/{project}/plans, and POST takes the same discriminated shape the reads return.

Every change announces itself as a plan.* event; a kind: pass plan also emits pass.* events as its windows are scheduled, open and close, and a series emits pass_series.* alongside them.

Background

The shape is a discriminated union

kind is always present, and it names exactly one nested object that accompanies it:

kindCarriesSells
subscriptionbillingAccess that begins at payment and renews on a cycle.
passpassOne dated access window per purchase.
pass_seriespass_seriesA slate of other pass plans' windows, sold once.

The other two blocks are absent, not null. Presence is a consequence of the tag, never a signal in its own right: read kind and you know what you are holding.

This replaced a nullable pass object. The previous shape emitted pass: null on ordinary plans and told consumers to branch on its presence. That is a type tag smuggled in as a presence check: it cannot express a third kind, and it left every integrator inferring the rule. It also emitted billing_cycle, trial_days and recurring on every plan including passes, where they mean nothing. A field that is present and lying is worse than one that is absent, so the cycle fields now appear only on the kind that has a cycle.

Writes mirror reads exactly, so a payload you read back is a payload you can send. The read endpoint shows one worked plan per kind, field by field.

Two axes: existence and availability

DELETE removes the row; publish and unpublish flip active. Prefer unpublish for "pause intake while keeping the plan on the books": members who already joined keep their access either way, and an unpublished plan stays fully editable.

Endpoints

How is this guide?

Last updated on

Version

On this page

Subscriby is a product
designed by you — for you.
No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request

For AI agents: llms.txt · llms-full.txt